Crate cloudpub_sdk

Crate cloudpub_sdk 

Source
Expand description

§CloudPub Rust SDK

CloudPub Rust SDK предоставляет простой интерфейс для взаимодействия с платформой CloudPub. CloudPub обеспечивает безопасное туннелирование и публикацию сервисов, позволяя безопасно открывать локальные сервисы в интернет.

§Возможности

  • Публикация сервисов: Открытие локальных сервисов (HTTP, HTTPS, TCP, UDP, WebSocket, RTSP) в интернет
  • Безопасное туннелирование: Все соединения шифруются и аутентифицируются
  • Несколько протоколов: Поддержка различных протоколов, включая HTTP/HTTPS, TCP/UDP, WebSocket и RTSP
  • Аутентификация: Встроенная поддержка аутентификации на основе токенов и учетных данных
  • Управление сервисами: Запуск, остановка, список и управление опубликованными сервисами
  • Событийно-ориентированная архитектура: Поддержка async/await с управлением состоянием на основе событий

§Быстрый старт

Добавьте SDK в ваш Cargo.toml:

[dependencies]
cloudpub-sdk = "2.4.2"

§Базовое использование

§Простая публикация сервиса

use cloudpub_sdk::Connection;
use cloudpub_sdk::protocol::{Protocol, Auth, Endpoint};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Создание соединения с учетными данными
    let mut conn = Connection::builder()
        .credentials("user@example.com", "password")
        .build()
        .await?;

    // Публикация локального веб-сервиса
    let endpoint = conn.publish(
        Protocol::Http,
        "localhost:3000".to_string(),
        Some("My Web App".to_string()),
        Some(Auth::None),
        None, // acl
        None, // headers
        None, // rules
    ).await?;

    println!("Service published at: {}", endpoint.as_url());

    // Ожидание сигнала Ctrl+C для остановки
    tokio::signal::ctrl_c().await?;

    // Очистка
    conn.unpublish(endpoint.guid).await?;
    Ok(())
}

§Расширенная публикация сервиса с ACL, заголовками и правилами фильтрации

use cloudpub_sdk::Connection;
use cloudpub_sdk::protocol::{
    Protocol, Auth, Endpoint, Acl, Header, FilterRule,
    Role, FilterAction
};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let mut conn = Connection::builder()
        .credentials("admin@example.com", "password")
        .build()
        .await?;

    // Настройка списка контроля доступа
    let acl = vec![
        Acl { user: "admin@example.com".to_string(), role: Role::Admin as i32 },
        Acl { user: "user@example.com".to_string(), role: Role::Reader as i32 },
        Acl { user: "writer@example.com".to_string(), role: Role::Writer as i32 },
    ];

    // Добавление пользовательских HTTP заголовков
    let headers = vec![
        Header { name: "X-API-Version".to_string(), value: "2.0".to_string() },
        Header { name: "Access-Control-Allow-Origin".to_string(), value: "*".to_string() },
        Header { name: "X-Custom-Header".to_string(), value: "CloudPub".to_string() },
    ];

    // Определение правил фильтрации для обработки запросов
    let rules = vec![
        FilterRule {
            order: 0,
            action_type: FilterAction::FilterAllow as i32,
            action_value: None,
            data: "http.path starts_with \"/api/\" and http.headers[\"X-API-Key\"] contains \"valid\"".to_string(),
        },
        FilterRule {
            order: 1,
            action_type: FilterAction::FilterDeny as i32,
            action_value: None,
            data: "http.path matches \"^/admin.*\" and not (ip.src >= 192.168.1.0 and ip.src <= 192.168.1.255)".to_string(),
        },
        FilterRule {
            order: 2,
            action_type: FilterAction::FilterRedirect as i32,
            action_value: Some("https://api.example.com/v2/".to_string()),  // URL перенаправления
            data: "http.path starts_with \"/api/v1/\"".to_string(),
        },
    ];

    // Публикация сервиса со всеми расширенными возможностями
    let endpoint = conn.publish(
        Protocol::Https,
        "localhost:8443".to_string(),
        Some("Secured API Server".to_string()),
        Some(Auth::Basic),
        Some(acl),
        Some(headers),
        Some(rules),
    ).await?;

    println!("Advanced service published at: {}", endpoint.as_url());

    Ok(())
}

§Расширенная конфигурация

use cloudpub_sdk::Connection;
use std::time::Duration;

// Создание соединения с расширенной конфигурацией
let conn = Connection::builder()
    .config_path("/custom/path/config.toml")  // Пользовательский файл конфигурации
    .log_level("debug")                       // Включить отладочное логирование
    .verbose(true)                            // Вывод логов в консоль
    .timeout(Duration::from_secs(60))         // Установить таймаут операции
    .token("existing-auth-token")             // Использовать существующий токен
    .build()
    .await?;

§Расширенные возможности

§Списки контроля доступа (ACL)

Контроль доступа к вашим сервисам на основе ролей пользователей:

let acl = vec![
    Acl {
        user: "admin@example.com".to_string(),
        role: Role::Admin as i32  // Полный доступ
    },
    Acl {
        user: "reader@example.com".to_string(),
        role: Role::Reader as i32  // Доступ только на чтение
    },
    Acl {
        user: "writer@example.com".to_string(),
        role: Role::Writer as i32  // Доступ на чтение-запись
    },
    Acl {
        user: "guest@example.com".to_string(),
        role: Role::Nobody as i32  // Нет доступа
    },
];

§Пользовательские HTTP заголовки

Добавление пользовательских заголовков в HTTP/HTTPS ответы:

let headers = vec![
    Header {
        name: "X-API-Version".to_string(),
        value: "2.0".to_string()
    },
    Header {
        name: "Access-Control-Allow-Origin".to_string(),
        value: "*".to_string()
    },
    Header {
        name: "Cache-Control".to_string(),
        value: "no-cache, no-store, must-revalidate".to_string()
    },
];

§Правила фильтрации

Определение правил для управления маршрутизацией запросов и доступом на основе различных параметров соединения. Правила обрабатываются по порядку (по полю order), и первое подходящее правило применяется.

let rules = vec![
    // Разрешить доступ к API только из локальной сети
    FilterRule {
        order: 0,
        action_type: FilterAction::FilterAllow as i32,
        action_value: None,
        data: "ip.src >= 192.168.1.0 and ip.src <= 192.168.1.255 and http.path starts_with \"/api/\"".to_string(),
    },

    // Блокировать доступ к админ-панели снаружи
    FilterRule {
        order: 1,
        action_type: FilterAction::FilterDeny as i32,
        action_value: None,
        data: "http.path matches \"^/admin.*\"".to_string(),
    },

    // Перенаправление старых API эндпоинтов на новую версию
    // action_value содержит URL перенаправления для FilterRedirect
    FilterRule {
        order: 2,
        action_type: FilterAction::FilterRedirect as i32,
        action_value: Some("https://api.example.com/v2/".to_string()),  // Redirect URL
        data: "http.path starts_with \"/api/v1/\"".to_string(),
    },

    // Блокировать запросы из определенных стран
    FilterRule {
        order: 3,
        action_type: FilterAction::FilterDeny as i32,
        action_value: None,
        data: "geo.country != \"Россия\"".to_string(),
    },

    // Разрешить только аутентифицированные API запросы
    FilterRule {
        order: 4,
        action_type: FilterAction::FilterAllow as i32,
        action_value: None,
        data: "http.path starts_with \"/api/\" and http.headers[\"Authorization\"] contains \"Bearer\"".to_string(),
    },
];

Доступные переменные для фильтр выражений:

  • ip.src, ip.dst - IP адреса источника и назначения
  • port.src, port.dst - Порты источника и назначения
  • protocol - Протокол соединения (“tcp”, “udp”, “http”)
  • http.host, http.path, http.method - HTTP-специфичные поля
  • http.headers["Header-Name"] - Доступ к HTTP заголовкам
  • geo.country, geo.region, geo.city, geo.code - Данные геолокации

Операторы:

  • Сравнение: ==, !=, >, <, >=, <=
  • Строковые: matches (regex), contains, starts_with, ends_with
  • Логические: and, or, not

§Типы сервисов

CloudPub поддерживает несколько протоколов сервисов:

§HTTP/HTTPS сервисы

use cloudpub_sdk::protocol::{Protocol, Auth, Endpoint};

// Публикация HTTP сервиса с базовой аутентификацией
let http_endpoint = conn.publish(
    Protocol::Http,
    "localhost:8080".to_string(),
    Some("API Server".to_string()),
    Some(Auth::Basic),  // Требовать пароль для доступа
    None, // acl
    None, // headers
    None, // rules
).await?;

// Публикация HTTPS сервиса
let https_endpoint = conn.publish(
    Protocol::Https,
    "localhost:8443".to_string(),
    Some("Secure API".to_string()),
    Some(Auth::Basic),  // Требовать токен для доступа
    None, // acl
    None, // headers
    None, // rules
).await?;

§TCP/UDP сервисы

use cloudpub_sdk::protocol::{Protocol, Auth};

// Публикация TCP сервиса (например, SSH)
let tcp_endpoint = conn.publish(
    Protocol::Tcp,
    "localhost:22".to_string(),
    Some("SSH Server".to_string()),
    Some(Auth::None),
    None, // acl
    None, // headers
    None, // rules
).await?;

// Публикация UDP сервиса (например, DNS)
let udp_endpoint = conn.publish(
    Protocol::Udp,
    "localhost:53".to_string(),
    Some("DNS Server".to_string()),
    Some(Auth::None),
    None, // acl
    None, // headers
    None, // rules
).await?;

§WebSocket сервисы

use cloudpub_sdk::protocol::{Protocol, Auth};

// Публикация TCP сервиса
let tcp_endpoint = conn.publish(
    Protocol::Tcp,
    "localhost:8080".to_string(),
    Some("TCP Server".to_string()),
    Some(Auth::None),
    None, // acl
    None, // headers
    None, // rules
).await?;

// Публикация UDP сервиса
let udp_endpoint = conn.publish(
    Protocol::Udp,
    "localhost:8443".to_string(),
    Some("UDP Server".to_string()),
    Some(Auth::Basic),
    None, // acl
    None, // headers
    None, // rules
).await?;

§RTSP стриминговые сервисы

use cloudpub_sdk::protocol::{Protocol, Auth};

// Публикация RTSP потока с учетными данными в URL
// Формат: rtsp://username:password@host:port/path
let rtsp_endpoint = conn.publish(
    Protocol::Rtsp,
    "rtsp://camera:secret123@192.168.1.100:554/live/stream1".to_string(),
    Some("Security Camera".to_string()),
    Some(Auth::Basic),  // Аутентификация доступа в CloudPub
    None, // acl
    None, // headers
    None, // rules
).await?;

// RTSP без учетных данных (публичный поток)
let public_rtsp = conn.publish(
    Protocol::Rtsp,
    "rtsp://localhost:554/public".to_string(),
    Some("Public Stream".to_string()),
    Some(Auth::None),
    None, // acl
    None, // headers
    None, // rules
).await?;

§Управление сервисами

§Список сервисов

use cloudpub_sdk::protocol::Endpoint;
// Получить все зарегистрированные сервисы
let services = conn.ls().await?;

for service in services {
    let name = service.client.as_ref()
        .and_then(|c| c.description.clone())
        .unwrap_or_else(|| "Без имени".to_string());
    println!("Service: {}", name);
    println!("  GUID: {}", service.guid);
    println!("  URL: {}", service.as_url());
    println!("  Status: {}", service.status.unwrap_or_else(|| "Unknown".to_string()));
    println!("  Protocol: {:?}", service.remote_proto);
}

§Запуск и остановка сервисов

// Временно остановить сервис
conn.stop("service-guid-123".to_string()).await?;

// Перезапустить сервис
conn.start("service-guid-123".to_string()).await?;

// Постоянно удалить сервис
conn.unpublish("service-guid-123".to_string()).await?;

// Удалить все сервисы
conn.clean().await?;

§Управление конфигурацией

§Чтение и запись опций

// Установка значений конфигурации
conn.set("server", "api.cloudpub.com")?;
conn.set("port", "443")?;
conn.set("ssl", "true")?;

// Получение значений конфигурации
let server = conn.get("server")?;
println!("Server: {}", server);

// Получение всех опций конфигурации
let options = conn.options();
for (key, value) in options {
    println!("{}: {}", key, value);
}

§Управление аутентификацией

use cloudpub_sdk::Connection;

// Аутентификация с учетными данными
let mut conn = Connection::builder()
    .credentials("user@example.com", "password")
    .build()
    .await?;

// Позже, выход для очистки токена
conn.logout()?;

// Повторная аутентификация с сохраненным токеном
let conn = Connection::builder()
    .token("saved-auth-token")
    .build()
    .await?;

§Вспомогательные функции

§Проверка состояния сервера

// Измерение задержки сервера (возвращает микросекунды)
let latency_us = conn.ping().await?;
let latency_ms = latency_us as f64 / 1000.0;
println!("Server latency: {}μs ({:.2}ms)", latency_us, latency_ms);

if latency_ms > 100.0 {
    println!("Warning: High latency detected!");
}

§Управление кэшем

// Очистка локального кэша
conn.purge()?;
println!("Cache cleared");

§Обработка ошибок

Все методы SDK возвращают Result<T> для правильной обработки ошибок:

use cloudpub_sdk::Connection;

match Connection::builder()
    .credentials("user@example.com", "wrong-password")
    .build()
    .await
{
    Ok(conn) => {
        println!("Connected successfully");
    },
    Err(e) => {
        eprintln!("Connection failed: {}", e);
        // Обработка специфичных типов ошибок
        if e.to_string().contains("authentication") {
            eprintln!("Authentication failed. Please check your credentials.");
        }
    }
}

§Полный пример

Вот полный пример, демонстрирующий полный жизненный цикл с расширенными возможностями:

use cloudpub_sdk::Connection;
use cloudpub_sdk::protocol::{
    Protocol, Auth, Endpoint, Acl, Header, FilterRule,
    Role, FilterAction
};
use std::time::Duration;
use tokio::time::sleep;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Инициализация соединения с конфигурацией
    println!("Connecting to CloudPub...");
    let mut conn = Connection::builder()
        .credentials("admin@example.com", "secure-password")
        .log_level("info")
        .verbose(true)
        .timeout_secs(30)
        .build()
        .await?;

    println!("Connected successfully!");

    // Публикация нескольких сервисов
    println!("\nPublishing services...");

    // Простой веб-сервис без расширенных возможностей
    let web_service = conn.publish(
        Protocol::Http,
        "localhost:3000".to_string(),
        Some("Web Application".to_string()),
        Some(Auth::None),
        None, // Нет ACL ограничений
        None, // Нет пользовательских заголовков
        None, // Нет правил фильтрации
    ).await?;
    println!("✓ Web app: {}", web_service.as_url());

    // API сервер с ACL и пользовательскими заголовками
    let api_acl = vec![
        Acl { user: "api_admin@example.com".to_string(), role: Role::Admin as i32 },
        Acl { user: "api_user@example.com".to_string(), role: Role::Reader as i32 },
    ];
    let api_headers = vec![
        Header { name: "X-API-Version".to_string(), value: "2.0".to_string() },
        Header { name: "Access-Control-Allow-Origin".to_string(), value: "*".to_string() },
    ];
    let api_service = conn.publish(
        Protocol::Https,
        "localhost:8443".to_string(),
        Some("API Server".to_string()),
        Some(Auth::Basic),
        Some(api_acl),
        Some(api_headers),
        None, // Нет правил фильтрации
    ).await?;
    println!("✓ API server: {}", api_service.as_url());

    // SSH сервис с правилами фильтрации для безопасности
    let ssh_rules = vec![
        FilterRule {
            order: 0,
            action_type: FilterAction::FilterAllow as i32,
            action_value: None,
            data: "ip.src == 192.168.1.10 or ip.src == 10.0.0.5".to_string(),  // Разрешить только определенные IP
        },
        FilterRule {
            order: 1,
            action_type: FilterAction::FilterDeny as i32,
            action_value: None,
            data: "ip.src matches \".*\"".to_string(),  // Заблокировать все остальные IP
        },
    ];
    let ssh_service = conn.publish(
        Protocol::Tcp,
        "localhost:22".to_string(),
        Some("SSH Access".to_string()),
        Some(Auth::Basic),
        None, // Нет ACL
        None, // Нет заголовков (TCP не использует HTTP заголовки)
        Some(ssh_rules),
    ).await?;
    println!("✓ SSH: {}", ssh_service.as_url());

    // Проверка состояния сервера
    println!("\nChecking server health...");
    let latency_us = conn.ping().await?;
    println!("Server latency: {}μs ({:.2}ms)", latency_us, latency_us as f64 / 1000.0);

    // Список всех сервисов
    println!("\nActive services:");
    let services = conn.ls().await?;
    for (i, service) in services.iter().enumerate() {
        let name = service.client.as_ref()
            .and_then(|c| c.description.clone())
            .unwrap_or_else(|| "Без имени".to_string());
        println!("{}. {} - {}",
            i + 1,
            name,
            service.as_url()
        );
    }

    // Работать некоторое время
    println!("\nServices are running. Press Ctrl+C to stop...");
    tokio::select! {
        _ = tokio::signal::ctrl_c() => {
            println!("\nShutting down...");
        }
        _ = sleep(Duration::from_secs(3600)) => {
            println!("\nTimeout reached");
        }
    }

    // Очистка
    println!("Очистка сервисов...");
    for service in services {
        conn.unpublish(service.guid).await?;
        let name = service.client.as_ref()
            .and_then(|c| c.description.clone())
            .unwrap_or_else(|| "Без имени".to_string());
        println!("✓ Removed: {}", name);
    }

    println!("All services stopped. Goodbye!");
    Ok(())
}

§Потокобезопасность

Структура Connection использует внутреннюю синхронизацию и может безопасно использоваться между потоками через Arc<Mutex<Connection>> при необходимости.

§Лицензия

Этот SDK лицензирован под лицензией Apache 2.0.

Modules§

protocol

Structs§

ClientOpts
Connection
Управляет соединением с сервером CloudPub.
ConnectionBuilder
Строитель для создания и настройки экземпляров Connection.

Enums§

ConnectionEvent
Представляет различные события, происходящие в течение жизненного цикла соединения.

Type Aliases§

CheckSignalFn
Псевдоним типа для функции проверки сигналов.