# Vulcain **Repository Path**: mirrors/Vulcain ## Basic Information - **Project Name**: Vulcain - **Description**: Vulcain 使用 HTTP/2 服务器推送来创建一个快速和方便使用的客户端驱动的 REST API - **Primary Language**: Unknown - **License**: AGPL-3.0 - **Default Branch**: main - **Homepage**: https://www.oschina.net/p/vulcain - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2019-11-07 - **Last Updated**: 2026-02-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README

Vulcain: Use HTTP/2 Server Push to create fast and idiomatic client-driven REST APIs

Vulcain is a brand new protocol using Preload hints and the `103 Early Hints` status code to create fast and idiomatic **client-driven REST** APIs. An open source gateway server (a module for the [Caddy web server](https://caddyserver.com)), which you can put on top of **any existing web API** to instantly turn it into a Vulcain-compatible API is also provided! It supports [hypermedia APIs](https://restfulapi.net/hateoas/) (e.g. any API created with [API Platform](https://api-platform.com)) but also any "legacy" API by documenting its relations [using OpenAPI](docs/gateway/openapi.md). [![Plant Tree](https://img.shields.io/badge/dynamic/json?color=brightgreen&label=Plant%20Tree&query=%24.total&url=https%3A%2F%2Fpublic.offset.earth%2Fusers%2Ftreeware%2Ftrees)](https://plant.treeware.earth/dunglas/vulcain) [![PkgGoDev](https://pkg.go.dev/badge/github.com/dunglas/vulcain/gateway)](https://pkg.go.dev/github.com/dunglas/vulcain) [![Build Status](https://github.com/dunglas/vulcain/workflows/CI/badge.svg)](https://github.com/dunglas/vulcain/actions) [![codecov](https://codecov.io/gh/dunglas/vulcain/branch/master/graph/badge.svg)](https://codecov.io/gh/dunglas/vulcain) [![Go Report Card](https://goreportcard.com/badge/github.com/dunglas/vulcain)](https://goreportcard.com/report/github.com/dunglas/vulcain) [tabs] ### Preload ![Vulcain Schema](schemas/vulcain_doc_main_200.png) ### Preload + Early Hints ![Vulcain Schema](schemas/vulcain_doc_main_early_hints.png) ### Server push ![Vulcain Schema](schemas/vulcain_doc_main_server_push.png) [/tabs] Grab What You Need... Burn The REST! * [Introduction](#introduction) * [Pushing Relations](#pushing-relations) * [Filtering Resources](#filtering-resources) * [Gateway Server](docs/gateway/) * [Caddy Web Server Module](docs/gateway/caddy.md) * [Mapping a Non-Hypermedia API using OpenAPI](docs/gateway/openapi.md) * [Legacy Standalone Server](docs/gateway/install.md) * [Legacy Configuration](docs/gateway/config.md) * [Comparison with GraphQL and Other API Formats](docs/graphql.md) * [Using GraphQL as Query Language for Vulcain](docs/graphql.md#using-graphql-as-query-language-for-vulcain) * [Demo API](CONTRIBUTING.md) * [Cache Considerations](docs/cache.md) * [Formal Specification](spec/vulcain.md) * [Getting Help](docs/help.md) The protocol has been published as [an Internet Draft](https://datatracker.ietf.org/doc/draft-dunglas-vulcain/) that [is maintained in this repository](spec/vulcain.md). A reference, production-grade, implementation [**gateway server**](docs/gateway/caddy.md) is also available in this repository. It's free software (AGPL) written in Go. A Docker image is provided. ## Introduction Over the years, several formats have been created to fix performance bottlenecks impacting web APIs: [over fetching, under fetching](https://stackoverflow.com/a/44568365/1352334), [the n+1 problem](https://restfulapi.net/rest-api-n-1-problem/)... [Current solutions for these problems (GraphQL, JSON:API's embedded resources and sparse fieldsets, ...)](docs/graphql.md) are smart [network hacks](https://apisyouwonthate.com/blog/lets-stop-building-apis-around-a-network-hack) for HTTP/1. But these hacks come with (too) many drawbacks when it comes to HTTP cache, logs and even security. Fortunately, thanks to the new features introduced in HTTP/2, it's now possible to create true REST APIs fixing these problems with ease and class! Here comes Vulcain! See also [the comparison between Vulcain and GraphQL and other API formats](docs/graphql.md). ## Pushing Relations [tabs] ### Preload ![Preload Schema](schemas/vulcain_doc_preload_200.png) ### Preload + Early Hints ![Preload Schema](schemas/vulcain_doc_preload_early_hints.png) ### Server push ![Preload Schema](schemas/vulcain_doc_preload_server_push.png) [/tabs] Considering the following resources: `/books` ```json { "member": [ "/books/1", "/books/2" ] } ``` `/books/1` ```json { "title": "1984", "author": "/authors/1" } ``` `/books/2` ```json { "title": "Homage to Catalonia", "author": "/authors/1" } ``` `/authors/1` ```json { "givenName": "George", "familyName": "Orwell" } ``` The `Preload` HTTP header introduced by Vulcain can be used to ask the server to immediately push resources related to the requested one using 103 Early Hints or HTTP/2 Server Push: ```http GET /books/ HTTP/2 Preload: "/member/*/author" ``` In addition to `/books`, a Vulcain server will push the `/books/1`, `/books/2` and `/authors/1` resources! Example in JavaScript: ```javascript const bookResp = await fetch("/books/1", { headers: { Preload: `"/author"` } }); const bookJSON = await bookResp.json(); // Returns immediately, the resource has been pushed and is already in the push cache const authorResp = await fetch(bookJSON.author); // ... ``` [Full example, including collections](fixtures/static/main.js), see also [use GraphQL as query language for Vulcain](docs/graphql.md#using-graphql-as-query-language-for-vulcain). Thanks to [HTTP/2+ multiplexing](https://stackoverflow.com/a/36519379/1352334), pushed responses will be sent in parallel. When the client will follow the links and issue a new HTTP request (for instance using `fetch()`), the corresponding response will already be in cache, and will be used instantly! For non-hypermedia APIs (when the identifier of the related resource is a simple string or int), [use an OpenAPI specification to configure links between resources](docs/gateway/openapi.md). Tip: the easiest way to create a hypermedia API is to use [the API Platform framework](https://api-platform.com) (by the same author as Vulcain). When possible, we recommend using [Early Hints](https://tools.ietf.org/html/rfc8297) (the 103 HTTP status code) to push the relations. Vulcain allows to gracefully fallback to [`preload` links](https://www.w3.org/TR/preload/) in the headers of the final response or to [HTTP/2 Server Push](https://tools.ietf.org/html/rfc7540#section-10.1) when the 103 status code isn't supported. ### Query Parameter Alternatively to HTTP headers, the `preload` query parameter can be used: [tabs] #### Preload ![Preload Query Schema](schemas/vulcain_doc_preload_query_200.png) #### Preload + Early Hints ![Preload Query Schema](schemas/vulcain_doc_preload_query_early_hints.png) #### Server push ![Preload Query Schema](schemas/vulcain_doc_preload_query_server_push.png) [/tabs] ## Filtering Resources [tabs] ### Preload ![Filter Schema](schemas/vulcain_doc_filter_200.png) ### Preload + Early Hints ![Filter Schema](schemas/vulcain_doc_filter_early_hints.png) ### Server push ![Filter Schema](schemas/vulcain_doc_filter_server_push.png) [/tabs] The `Fields` HTTP header allows the client to ask the server to return only the specified fields of the requested resource, and of the preloaded related resources. Multiple `Fields` HTTP headers can be passed. All fields matching at least one of these headers will be returned. Other fields of the resource will be omitted. Considering the following resources: `/books/1` ```json { "title": "1984", "genre": "novel", "author": "/authors/1" } ``` `/authors/1` ```json { "givenName": "George", "familyName": "Orwell" } ``` And the following HTTP request: ```http GET /books/1 HTTP/2 Preload: "/author" Fields: "/author/familyName", "/genre" ``` A Vulcain server will return a response containing the following JSON document: ```json { "genre": "novel", "author": "/authors/1" } ``` It will also push the following filtered `/authors/1` resource: ```json { "familyName": "Orwell" } ``` ### Query Parameter Alternatively to HTTP headers, the `fields` query parameter can be used to filter resources: [tabs] #### Preload ![Fields Schema](schemas/vulcain_doc_filter_query_200.png) #### Preload + early hints ![Fields Schema](schemas/vulcain_doc_filter_query_early_hints.png) #### Server push ![Fields Schema](schemas/vulcain_doc_filter_query_server_push.png) [/tabs] ## See Also * [Mapping a non-hypermedia API using OpenAPI](docs/gateway/openapi.md) * [Cache considerations](docs/cache.md) * [Using GraphQL with Vulcain](docs/graphql.md#using-graphql-as-query-language-for-vulcain) * [Using other selectors such as XPath and CSS selectors for non-JSON documents](spec/vulcain.md#selectors) (only JSON Pointer [is currently supported](https://github.com/dunglas/vulcain/issues/3) by the Gateway Server) ## License and Copyright tl;dr: * proprietary software **can** implement the Vulcain specification * proprietary software **can** be used behind the Vulcain Gateway Server without having to share their sources * modifications made to the Vulcain Gateway Server **must** be shared * alternatively, a commercial license is available for the Vulcain Gateway Server [The specification](spec/vulcain.md) is available under [the IETF copyright policy](https://trustee.ietf.org/copyright-faq.html). The Vulcain **specification** can be implemented by any software, including proprietary software. The Vulcain Gateway Server is licensed under [AGPL-3.0](LICENSE). This license implies that if you modify the Vulcain Gateway Server, you must share those modifications. However, the AGPL-3.0 license applies only to the gateway server itself, **not to software used behind the gateway**. For companies not wanting, or not able to use AGPL-3.0 licensed software, commercial licenses are also available. [Contact us for more information](mailto:kevin+vulcain@dunglas.dev). ## Treeware This package is [Treeware](https://treeware.earth). If you use it in production, then we ask that you [**buy the world a tree**](https://plant.treeware.earth/dunglas/vulcain) to thank us for our work. By contributing to the Treeware forest you’ll be creating employment for local families and restoring wildlife habitats. ## Credits Created by [Kévin Dunglas](https://dunglas.dev). Sponsored by [Les-Tilleuls.coop](https://les-tilleuls.coop). Some ideas and code used in Vulcain's reference implementation have been taken from [Hades](https://github.com/gabesullice/hades) by [Gabe Sullice](https://github.com/gabesullice), an HTTP/2 reverse proxy for JSON:API backend. See also [the prior arts](docs/prior-art.md).