Skip to content

Conductor is a cutting-edge, open-source GraphQL Gateway, fully compliant with the GraphQL specification and designed to supercharge any API with powerful features and proxy flows.

License

Notifications You must be signed in to change notification settings

the-guild-org/conductor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

a1cc943 · Jan 8, 2024
Jan 8, 2024
Nov 19, 2023
Dec 31, 2023
Jan 7, 2024
Jan 7, 2024
Jan 1, 2024
Dec 28, 2023
Jan 3, 2024
Jan 8, 2024
Jan 8, 2024
Nov 19, 2023
Dec 28, 2023
Jan 7, 2024
Jan 7, 2024
Oct 1, 2023
Dec 27, 2023
Dec 31, 2023
Dec 26, 2023

Repository files navigation

Conductor (take 2) (Rust GraphQL Gateway)

Getting Started

  1. Clone
  2. Run: cargo run -- temp/config.yaml to run it locally

Usage

When no arguments are specified, it defaults the config path to ./config.json

cargo run ./temp/config.yaml
# or
cargo run ./temp/config.json

Architecture

This document will describe the architecture of the GraphQL gateway written in Rust.

Project Structure

The GraphQL Gateway's source code is divided into four main modules:

  1. config: Handles the loading and parsing of the Gateway configuration files.

  2. endpoint: The endpoint module is responsible for managing endpoints, their runtime, and processing incoming GraphQL requests.

  3. gateway: The gateway module contains the engine which manages the lifecycle of the gateway server.

  4. source: This module includes the source service that processes the GraphQL requests to their respective sources.

Modules

config

The config module parses the configuration for the gateway from a specified file. The configuration includes server settings, logger settings, source definitions, and endpoint definitions. It supports both JSON and YAML formats for the schema.

endpoint

The endpoint module defines the EndpointRuntime struct which handles incoming requests for a specific endpoint. The EndpointRuntime contains the endpoint's configuration and a reference to the service that will process its requests (upstream_service). The call method is used to process incoming requests.

gateway

The gateway module contains the main Gateway struct that manages the lifecycle of the gateway server. When the Gateway is initialized, it creates a map of GraphQLSourceService structs for each source defined in the configuration and a map of EndpointRuntime structs for each endpoint. These maps are then used to route incoming requests to the correct service.

source

The source module contains the SourceService trait that defines the interface for services that process GraphQL requests, this is there so that later on other Sources than plain GraphQL like loading Supergraph from Hive/Apollo Studio.

graphql_source

The graphql_source module includes the GraphQLSourceService which is an implementation of the SourceService trait for GraphQL sources.

plugins_manager

The plugins_manager module includes the PluginsManager which includes all of the available traits to implement representing the different kind of hooks that can be implemented and plugged in.

Server Startup Process

The startup process of the server is handled in src/main.rs. The steps are as follows:

  1. Load the configuration file. config.json or config.yaml
  2. Instantiate a PluginsManager and add all of the necessary hooks.
  3. Create a new Gateway instance using the loaded configuration and the PluginsManager.
  4. Create a new Router and attach a route for each endpoint defined in the gateway's configuration.
  5. Start the server and await incoming requests.

Request Processing Flow

  1. The router routes the request to the correct EndpointRuntime.
  2. The endpoint's call method is invoked with the request body as a parameter.
  3. The call function creates a new SourceRequest from the body, which includes the body fields for a valid graphql request (query, variables, and operationName).
  4. The PluginsManager's exec_before_req(&mut req) is invoked, which is a method that hides the implementation of looping over the registered before request plugins and executes them.
  5. The SourceRequest is sent to the endpoint's upstream_service.
  6. The upstream_service processes the SourceRequest and returns a SourceResponse.
  7. The PluginsManager's exec_post_res(&mut req) is invoked, which is a method that hides the implementation of looping over the registered post response plugins and executes them.
  8. The SourceResponse is returned as the response to the client's request.

Error Handling

Errors are primarily handled through the SourceError enum, which includes variants for different types of errors that can occur when processing a request.

Tech Stack

  • tokio for async runtime
  • hyper for network
  • axum as HTTP server
  • tower to composing services and building flows