5 个版本 (3 个重大更新)

0.5.0 2023年2月16日
0.4.0 2023年2月1日
0.3.0 2022年11月16日
0.1.1 2022年9月29日
0.1.0 2022年9月29日

1844Web 编程

每月23 次下载

Apache-2.0

175KB
3K SLoC

speakeasy-rust-sdk

180100416-b66263e6-1607-4465-b45d-0e298a67c397

Speakeasy 是您的 API 平台团队即服务。使用我们的嵌入式 SDK 来管理所有 API 操作,包括请求日志和仪表板嵌入,从流量生成测试用例,以及理解 API 渐变。

Speakeasy Rust SDK 用于评估 API 请求/响应。目前与 axum 和 actix 兼容。

要求

支持的框架

  • Axum
  • Actix 4
  • Actix 3

使用方法

在 crates 上可用:crates.io/crates/speakeasy-rust-sdk

文档可在以下位置找到:docs.rs/speakeasy-rust-sdk

运行

cargo add speakeasy-rust-sdk --features actix4

或者直接将其添加到您的 Cargo.toml

speakeasy-rust-sdk = {version = "0.3.0", features = ["actix4"]}

最小配置

在我们的平台上免费注册。创建工作区并生成 API 密钥后,按照以下方式在您的 API 中启用 Speakeasy

(有关 axum 配置,请参阅以下示例 examples/axum/)

main() 函数开头配置 Speakeasy

use actix_web::{
    get, post,
    web::{self, ReqData},
    App, HttpResponse, HttpServer, Responder,
};
use speakeasy_rust_sdk::{middleware::actix3::Middleware, Config, SpeakeasySdk};

#[actix_web::main]
async fn main() -> std::io::Result<()> {
   HttpServer::new(|| {
        let config = Config {
            // retrieve from Speakeasy API dashboard.
            api_key: "YOUR API KEY HERE".to_string(),
            // enter a name that you'd like to associate captured requests with.
            // This name will show up in the Speakeasy dashboard. e.g. "PetStore" might be a good ApiID for a Pet Store's API.
            // No spaces allowed.
            api_id: "YOUR API ID HERE".to_string(),
            // enter a version that you would like to associate captured requests with.
            // The combination of ApiID (name) and VersionID will uniquely identify your requests in the Speakeasy Dashboard.
            // e.g. "v1.0.0". You can have multiple versions for the same ApiID (if running multiple versions of your API)
            version_id: "YOUR VERSION ID HERE".to_string(),
        };

        // Create a new Speakeasy SDK instance
        let mut sdk = SpeakeasySdk::try_new(config).expect("API key is valid");

        // create middleware
        let speakeasy_middleware = Middleware::new(sdk);
        let (request_capture, response_capture) = speakeasy_middleware.into();

        App::new()
            .wrap(request_capture)
            .wrap(response_capture)
            ...
    })
    .bind(("127.0.0.1", 8080))?
    .run()
    .await
}

构建和部署您的应用程序,然后即可。您的 API 正在您刚刚创建的 Speakeasy 工作区中跟踪,下次登录时将在仪表板上可见。请访问我们的 文档网站 了解更多信息。

本地配置

SDK 提供了一种将捕获的请求重定向到 Speakeasy 平台本地部署的方法。这是通过以下列出的环境变量实现的。这些应在集成 SDK 的服务环境中设置

  • SPEAKEASY_SERVER_URL - 本地 Speakeasy 平台的 GRPC 端点 URL。默认情况下为 grpc.prod.speakeasyapi.dev:443
  • SPEAKEASY_SERVER_SECURE - 是否在本地 Speakeasy 平台上使用 TLS。默认情况下为 true,如果使用不安全连接,则设置为 SPEAKEASY_SERVER_SECURE="false"

请求匹配

Speakeasy SDK 默认会尽可能将请求与您提供的 OpenAPI Schema 匹配。它是通过提取每个捕获的请求使用的支持路由器或框架中的路径模板,并尝试将其与 OpenAPI Schema 中定义的路径匹配来实现的,例如

// The path template "/v1/users/{id}" is captured automatically by the SDK
#[get("v1/users/{id}")]
async fn handler_function(id: web::Path<String>) -> impl Responder {
    // handler function code
}

这并不总是成功或可能,这意味着接收到的请求将被标记为 unmatched,并且可能不会与 Speakeasy Dashboard 中的您的 API、版本或 ApiEndpoints 关联。

为了帮助 SDK 在这些情况下,您可以按请求处理程序提供路径提示,以匹配您的 OpenAPI Schema 中的路径

#[post("/special_route")]
async fn special_route(controller: ReqData<Arc<RwLock<MiddlewareController>>>) -> HttpResponse {
    // Provide a path hint for the request using the OpenAPI Path templating format:
    //  https://swagger.org.cn/specification/#path-templating-matching
    controller
        .write()
        .unwrap()
        .set_path_hint("/special_route/{wildcard}");

	// the rest of your handlers code
}

捕获客户 ID

为了帮助将请求与您的 API 的客户/用户关联,您可以按请求处理程序提供客户 ID

#[post("/index")]
async fn index(controller: ReqData<Arc<RwLock<MiddlewareController>>>) -> HttpResponse {
    controller
        .write()
        .unwrap()
        .set_customer_id("123customer_id".to_string());

    // rest of the handlers code
}

注意:这不是必需的,但强烈推荐。通过设置客户 ID,您可以在 Speakeasy Dashboard 中轻松地将请求与您的客户/用户关联,从而在 请求查看器 中启用过滤器。

遮罩敏感数据

Speakeasy 可以遮罩 SDK 捕获的查询字符串参数、头部、cookie 和请求/响应体中的敏感数据。这对于保持敏感数据隔离并保留对捕获的数据的控制非常有用。

您可以为全局设置遮罩选项,这些选项将应用于所有请求和响应。

#[actix_web::main]
async fn main() -> std::io::Result<()> {
   HttpServer::new(|| {
        let config = Config {
            // retrieve from Speakeasy API dashboard.
            api_key: "YOUR API KEY HERE".to_string(),
            // enter a name that you'd like to associate captured requests with.
            // This name will show up in the Speakeasy dashboard. e.g. "PetStore" might be a good ApiID for a Pet Store's API.
            // No spaces allowed.
            api_id: "YOUR API ID HERE".to_string(),
            // enter a version that you would like to associate captured requests with.
            // The combination of ApiID (name) and VersionID will uniquely identify your requests in the Speakeasy Dashboard.
            // e.g. "v1.0.0". You can have multiple versions for the same ApiID (if running multiple versions of your API)
            version_id: "YOUR VERSION ID HERE".to_string(),
        };

        // Create a new Speakeasy SDK instance
        let mut sdk = SpeakeasySdk::try_new(config).expect("API key is valid");

        // Configure masking for query
        sdk.masking().with_query_string_mask("secret", "********");
        sdk.masking()
            .with_query_string_mask("password", StringMaskingOption::default());

        // Configure masking for request
        sdk.masking()
            .with_request_field_mask_string("password", StringMaskingOption::default());

        // Configure masking for **response**
        sdk.masking()
            .with_response_field_mask_string("secret", StringMaskingOption::default());

        // create middleware
        let speakeasy_middleware = Middleware::new(sdk);
        let (request_capture, response_capture) = speakeasy_middleware.into();

        App::new()
            .wrap(request_capture)
            .wrap(response_capture)
            ...
    })
    .bind(("127.0.0.1", 8080))?
    .run()
    .await
}

但是,如果您想更具有选择性,可以使用我们的中间件控制器来遮罩某些敏感数据,允许您在不同的处理程序中按需遮罩字段

use speakeasy_rust_sdk::{Masking, MiddlewareController, SpeakeasySdk, StringMaskingOption};

#[post("/index")]
async fn index(controller: ReqData<Arc<RwLock<MiddlewareController>>>) -> HttpResponse {
    // create a specific masking for this request/response
    let mut masking = Masking::default();
    masking.with_request_field_mask_string("password", StringMaskingOption::default());

    // set new masking for this request/response
    controller.write().unwrap().set_masking(masking);

    // rest of the handlers code
}

Masking 结构可以设置多个选项来遮罩请求中的敏感数据

  • masking.with_query_string_mask - with_query_string_mask 将使用可选的遮罩字符串遮罩指定的查询字符串。
  • masking.with_request_header_mask - with_request_header_mask 将使用可选的遮罩字符串遮罩指定的请求头部。
  • masking.with_response_header_mask - with_response_header_mask 将使用可选的遮罩字符串遮罩指定的响应头部。
  • masking.with_request_cookie_mask - with_request_cookie_mask 将使用可选的遮罩字符串遮罩指定的请求 cookie。
  • masking.with_response_cookie_mask - with_response_cookie_mask 将使用可选的遮罩字符串遮罩指定的响应 cookie。
  • masking.with_request_field_mask_string - with_request_field_mask_string 将使用可选的遮罩遮罩指定的请求体字段。仅支持字符串字段。使用正则表达式进行匹配。
  • masking.with_request_field_mask_number - with_request_field_mask_number 将使用可选的遮罩遮罩指定的请求体字段。仅支持数字字段。使用正则表达式进行匹配。
  • masking.with_response_field_mask_string - with_response_field_mask_string 将使用可选掩码对指定的响应体字段进行屏蔽。仅支持字符串字段。使用正则表达式进行匹配。
  • masking.with_response_field_mask_number - with_response_field_mask_number 将使用可选掩码对指定的响应体字段进行屏蔽。仅支持数字字段。使用正则表达式进行匹配。

有关屏蔽的完整文档,请参阅 docs.rs/speakeasy-rust-sdk

嵌入式请求查看器访问令牌

Speakeasy SDK 可以生成嵌入式请求查看器的访问令牌,用于查看由 SDK 捕获的请求。

有关配置筛选器的说明,请点击 这里.

以下是生成访问令牌的示例

use speakeasy_rust_sdk::speakeasy_protos::embedaccesstoken::{
    embed_access_token_request::Filter, EmbedAccessTokenRequest,
};

let request = EmbedAccessTokenRequest {
    filters: vec![Filter {
        key: "customer_id".to_string(),
        operator: "=".to_string(),
        value: "a_customer_id".to_string(),
    }],
    ..Default::default()
};

let token_response = app_state
    .speakeasy_sdk
    .get_embedded_access_token(request)
    .await
    .unwrap();

示例

依赖关系

~8–25MB
~418K SLoC