#apollo-federation #graphql #federation #gateway #http-request

apollo-gateway-rs

Apollo-gateway-rs 是用 Rust 实现的 Apollo Federation

15 个版本

0.9.5 2024 年 5 月 15 日
0.9.2 2024 年 4 月 10 日
0.9.1 2024 年 2 月 23 日
0.9.0 2023 年 11 月 14 日
0.7.8 2022 年 4 月 24 日

#294 in HTTP 服务器

Download history 187/week @ 2024-05-03 183/week @ 2024-05-10 33/week @ 2024-05-17 6/week @ 2024-05-24 3/week @ 2024-05-31 7/week @ 2024-06-07 8/week @ 2024-06-14 53/week @ 2024-07-05 6/week @ 2024-07-12

1,110 每月下载量

MIT/Apache

370KB
11K SLoC

Apollo-gateway-rs 是 Apollo Federation 的 Rust 实现。

如果您有疑问或发现错误或需要功能,请创建问题。

快速入门

定义您的远程源并实现 RemoteGraphQLDataSource

pub struct CommonSource {
    pub name: String,
    pub addr: String,
    pub tls: bool,
}
impl RemoteGraphQLDataSource for CommonSource {
    fn name(&self) -> &str {
        &self.name
    }
    fn address(&self) -> &str {
        &self.addr
    }
    fn tls(&self) -> bool {
        self.tls
    }
}

构建带有您源的门户新服务器

let gateway_server = GatewayServer::builder()
        .with_source(CommonSource::new("countries", "countries.trevorblades.com", true))
        .build();

配置 reqwest 处理器

use async_graphql::http::{GraphQLPlaygroundConfig, playground_source};
use apollo_gateway_rs::{actix::{graphql_request, graphql_subscription}};

pub async fn playground() -> HttpResponse {
    let html = playground_source(GraphQLPlaygroundConfig::new("/").subscription_endpoint("/"));
    HttpResponse::Ok()
        .content_type("text/html; charset=utf-8")
        .body(html)
}
fn configure_api(config: &mut actix_web::web::ServiceConfig) {
    config.service(
        actix_web::web::resource("/")
            .route(actix_web::web::post().to(graphql_request))
            .route(
                actix_web::web::get()
                    .guard(actix_web::guard::Header("upgrade", "websocket"))
                    .to(graphql_subscription),
            )
            .route(actix_web::web::get().to(playground)),
    );
}

并启动 actix-web 服务器!

async fn main() -> std::io::Result<()> {
    let gateway_server = GatewayServer::builder()
        .with_source(CommonSource::new("countries", "countries.trevorblades.com", true))
        .build();
    let gateway_server = Data::new(gateway_server);
    HttpServer::new(move || App::new()
        .app_data(gateway_server.clone())
        .configure(configure_api)
    )
        .bind("0.0.0.0:3000")?
        .run()
        .await
}

您可以在 examples/actix/common_usage 中查看完整示例

特性

网关可以在执行跨子图之前修改传入请求的详细信息。例如,您的子图可能都使用相同的授权令牌来关联传入请求与特定用户。网关可以将该令牌添加到它发送到子图的每个操作中。

#[async_trait::async_trait]
impl GraphqlSourceMiddleware for AuthSource {
    async fn did_receive_response(&self, response: &mut Response, ctx: &Context) -> anyhow::Result<()> {
        let session = ctx.get_session();
        if let Some(jwt) = response.headers.get("user-id")
            .and_then(|header| header.parse().ok())
            .and_then(|user_id| create_jwt(user_id).ok()) {
            session.insert("auth", jwt);
        }
        Ok(())
    }
}
#[async_trait::async_trait]
impl GraphqlSourceMiddleware for UserSource {
    async fn will_send_request(&self, request: &mut Request, ctx: &Context) -> anyhow::Result<()> {
        let session = ctx.get_session();
        if let Some(user_id) = session.get("auth")
                .ok()
                .flatten()
                .and_then(|identity| decode_identity(identity).ok())
                .map(|claims| claims.claims.id) {
            request.headers.insert("user-id".to_string(), user_id.to_string());
        }
        Ok(())
    }
}

您可以在 examples/actix/authentication 中找到完整示例

从配置加载源

您可以直接定义源或使用 DefaultSource 并从 json 文件中加载它。

let gateway_server = GatewayServer::builder()
    .with_sources_from_json::<DefaultSource>("sources.json")?
    .build();

您可以在 examples/actix/from_config 中查看完整示例

订阅支持

Apollo-gateway-rs 支持订阅,如果您想使用它,请使用 apollo_gateway_rs::actix::graphql_subscription。

后端实现

  • Actix-web
  • Rocket
  • Warp
  • Axum

贡献

欢迎贡献!

依赖项

~79MB
~1.5M SLoC