Skip to content

ideal-world/spacegate

Repository files navigation

Preview version, will not guarantee the stability of the API! Do NOT use in production environment!


A library-first, lightweight, high-performance, cloud-native supported API gateway🪐


Build Status License

SpaceGate("Spacegates are Stargates suspended in space, or in planetary orbit") From "Stargate".

💖 Core functions

  • Tiny: based on rust, the executable file only takes 6MB.
  • Cloud Native: Implemented the Kubernetes Gateway API specification.
  • Easy to extent: Build your own plugin with rust in just two function.
  • Easy to extent: Build your own plugin with rust in just two function.
  • High performance
  • Low resource usage

Usage

Use spacegate in k8s

Install for kubernetes

kubectl apply -f https://github.com/ideal-world/spacegate/releases/download/0.2.0-alpha.1/spacegate-0.2.0-alpha.1.yaml

Open spacegate admin web,and enjoy!

Use spacegate as an executable binary

Build and Install

Build and install on your own linux machine.

Install spacegate

sh resource/install/install.sh

Install spacegate-admin manage tool (Optional)

This official manage tool will provide you a web interface to edit gateway's config.

sh resource/install/install-admin.sh

manage tool

Configure your gateway

Visit localhost:9991 if you installed spacegate-admin manage tool.

firefox localhost:9991

Or visit config folder

ls /etc/spacegate

After you edited config, use systemctl to reload config.

sudo systemctl reload spacegate

Install plugin

Check the plugin folder:

ls /lib/spacegate/plugins

Just and put the .so file under the plugin folder and configure it.

Use spacegate as a rust lib

You can use spacegate-kernel or spacegate-shell. The The former one is relatively low-level, while the latter integrates plugins and configuration systems.

Use spacegate-shell

spacegate-shell = { git="https://github.com/ideal-world/spacegate", branch="dev" }

Start up by a config change listener

async fn main() {
    let listener = todo!("create a listener!");
    spacegate_shell::startup(listener).await;
}

or just using build-in listeners

// file config
spacegate_shell::startup_file("/etc/spacegate").await;
// k8s resource
spacegate_shell::startup_k8s(Some("spacegate-namespace")).await;
// fetch from redis
spacegate_shell::startup_redis("redis://my-redis").await;

Use spacegate-kernel

spacegate-kernel = { git="https://github.com/ideal-world/spacegate", branch="dev" }

Create a listener and a gateway service

let cancel = CancellationToken::default();
// create a gateway service
let gateway = gateway::Gateway::builder("test_gateway")
    .http_routers([(
        "test_gateway".to_string(),
        HttpRoute::builder()
            .rule(
                HttpRouteRule::builder()
                    .match_item(HttpPathMatchRewrite::prefix("/baidu"))
                    .backend(HttpBackend::builder().schema("https").host("www.baidu.com").port(443).build())
                    .build(),
            )
            .build(),
    )])
    .build();
let addr = SocketAddr::from_str("[::]:9002")?;
// create a listener
let listener = SgListen::new(
    addr,
    gateway.as_service(),
    cancel.child_token(),
);
// start listen
listener.listen().await?;

Create your own plugins in rust

All you need to do is to implements a Plugin trait

use spacegate_plugin::{SgResponse, SgRequest, Inner, BoxError, PluginConfig, Plugin};

pub struct ServerHeaderPlugin {
    header_value: String,
}

impl Plugin for ServerHeaderPlugin {
    // an unique code for this plugin
    const CODE: &'static str = "server-header";
    // this will be called when request passthrough this plugin
    async fn call(&self, req: SgRequest, inner: Inner) -> Result<SgResponse, BoxError> {
        // pre-request process

        // call inner to pass this request into inner layers
        let mut resp = inner.call(req).await;    

        // post-request process
        resp.headers_mut().insert("server", self.header_value.parse()?);

        // return the result
        Ok(resp)
    }

    // create a plugin instance from config
    fn create(plugin_config: PluginConfig) -> Result<Self, BoxError> {
        let Some(header_value) = plugin_config.spec.get("header_value") else {
            return Err("missing header_value".into())
        };
        Ok(Self {
           header_value: header_value.as_str().unwrap_or("spacegate").to_string(),
        })
    }
}

Use the plugin as a static lib

In your application program.

// register the plugin into global plugin repository
spacegate_plugin::PluginRepository::global().register::<ServerHeaderPlugin>()

Use the plugin as a dynamic linked lib

Use the macro dynamic_lib

use spacegate_plugin::dynamic_lib;
dynamic_lib! { ServerHeaderPlugin }

and set the crate-type to dylib

[lib]
crate-type = ["dylib"]

After you got the lib file, load it in application program.

For example:

spacegate_plugin::PluginRepository::global().register_dylib("/lib/spacegate/plugins/mylib.so")

Why create this project

There are a lot of API gateway products out there, but they are mostly in the form of standalone services. The customization ability is relatively poor, and the cost of using and deploying is relatively high.

This project is based on the Rust language and uses hyper as the base network library. The goal is to: provide a library-first, lightweight, high-performance, cloud-native supported API gateway .

📦 Components

Crate Type Description
spacegate-kernel Crate Docs rust-lib Kernel functions for creating a gateway service
spacegate-ext-redis Crate Docs rust-lib Redis features extension
spacegate-ext-axum Crate Docs rust-lib Axum web-server features extension
spacegate-shell Crate Docs rust-lib Integrated collection including a plugin system, config listeners and a easy-to-use program entrance.
spacegate-plugin Crate Docs rust-lib A plugin system implementation for spacegate-shell.
spacegate-model Crate Docs rust-lib Common data structures in spacegate project.
spacegate-config Crate Docs rust-lib Config listener interface and implementations.
spacegate bin An out-of-box executable based on spacegate-shell.
spacegate-admin bin Spacegate admin application backend service.
spacegate-admin-client NPM Version js-lib JavaScript/TypeScript sdk for spacegate-admin.
spacegate-admin-fe web Spacegate admin front end.

Project Structure

Crates

🔖 Releases

Release binary naming method: {crate}-{arch}{OS}{abi}-{version} download here

OS Arch abi Remark
linux x86_64,aarch64 gnu,musl If you need static linking please use musl