Skip to content

feat: introduce REST-over-gRPC transcoding#546

Open
geeknoid wants to merge 1 commit into
mainfrom
rest_over_grpc
Open

feat: introduce REST-over-gRPC transcoding#546
geeknoid wants to merge 1 commit into
mainfrom
rest_over_grpc

Conversation

@geeknoid

@geeknoid geeknoid commented Jul 5, 2026

Copy link
Copy Markdown
Member

Expose an existing gRPC API as a traditional REST/JSON API in the same
process, driven by google.api.http annotations. The gRPC service is
implemented once; the REST layer is generated at build time and transcodes
requests and responses with minimal runtime overhead. The generated router is
built on a standalone, zero-allocation static router (routerama) that is also
useful on its own.

Crates added:

  • routerama: dependency-free runtime for a compile-time static HTTP router —
    zero-allocation method + path matching returning the matched tag and captured
    path variables (with a SIMD segment scanner).
  • routerama_macros: the routes! procedural macro that generates a static
    router inline from a named route enum, with no build.rs required.
  • routerama_build: build-time code generator that lowers a route set into a
    resolve function (a nested match over path segments — a compile-time trie),
    reporting genuinely ambiguous routes as a compile_error!.
  • http_path_template: dependency-free parser for the google.api.http
    path-template grammar (literals, *, **, {field=sub} variables, :verb),
    with an optional extended grammar for intra-segment prefix/suffix parameters.
  • rest_over_grpc: framework-neutral transcoding crate spanning the runtime,
    the serving adapters, and the build-time code generator:
    • transcoding / handling: decode an HTTP request into a protobuf message,
      dispatch it to the gRPC handler, and encode the reply as JSON, mapping
      Code / Status to HTTP status codes.
    • serving (default, feature-gated): one-shot serve_http* helpers plus
      RestService / StreamingRestService adapters for the tower and
      layered ecosystems (hyper, axum, …). Request bodies are buffered with an
      optional with_max_body_bytes cap (413 Payload Too Large on overflow),
      and read failures surface as 400 Bad Request rather than an empty body.
    • streaming: server-streaming responses forwarded frame by frame as a JSON
      array, NDJSON, or SSE.
    • build / build-openapi: a build.rs code generator that turns
      google.api.http-annotated gRPC services (read from compiled descriptors)
      into a static REST router, service traits, a dispatcher, an optional tonic
      bridge, and an optional OpenAPI 3.1 specification.
  • rest_over_grpc_examples: worked examples organized by architecture layer,
    covering both the generated tonic bridge and a hand-written service that
    implements the generated trait directly.
  • rest_over_grpc_tests: end-to-end tests and benchmarks for the generated
    router and dispatcher.

Copilot AI review requested due to automatic review settings July 5, 2026 17:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a build-time generated REST/JSON façade for existing gRPC services driven by google.api.http annotations, adding a small path-template parser crate, a runtime transcoding layer, a build-time generator, and accompanying examples/benchmarks.

Changes:

  • Add http_path_template (path-template parser), rest_over_grpc (runtime transcoder/adapters), and rest_over_grpc_build (code generator).
  • Add worked examples (tonic bridge + custom/prost handler) and integration tests for value types, adapters, streaming, and OpenAPI output.
  • Add benchmark + correctness harness for the generated router/dispatcher and supporting workspace wiring (deps, spelling, clippy idents).

Reviewed changes

Copilot reviewed 107 out of 108 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
README.md Adds new primary-crate entries for REST-over-gRPC components.
CHANGELOG.md Links new crate changelogs from the workspace changelog index.
Cargo.toml Adds workspace dependencies for new crates and supporting libs (prost/tonic/etc.).
clippy.toml Allows additional doc-valid identifiers (e.g., “OpenAPI”).
.spelling Adds domain-specific terms used by the new crates/docs.
crates/http_path_template/Cargo.toml Defines the new http_path_template crate metadata.
crates/http_path_template/CHANGELOG.md Introduces the crate changelog for initial release.
crates/http_path_template/README.md Adds crate README content and examples.
crates/http_path_template/favicon.ico Adds crate branding asset (Git LFS).
crates/http_path_template/logo.png Adds crate branding asset (Git LFS).
crates/http_path_template/src/lib.rs Exposes the parser API and crate-level docs.
crates/http_path_template/src/error.rs Defines ParseError and predicates for parse failures.
crates/http_path_template/src/segment.rs Defines the parsed Segment AST.
crates/http_path_template/src/variable.rs Defines {field.path=subtemplate} variable representation.
crates/rest_over_grpc/Cargo.toml Defines the new rest_over_grpc runtime crate and feature flags.
crates/rest_over_grpc/CHANGELOG.md Introduces the crate changelog for initial release.
crates/rest_over_grpc/favicon.ico Adds crate branding asset (Git LFS).
crates/rest_over_grpc/logo.png Adds crate branding asset (Git LFS).
crates/rest_over_grpc/examples/layered_service.rs Example: serve transcoded REST via layered.
crates/rest_over_grpc/examples/tower_service.rs Example: serve transcoded REST via tower.
crates/rest_over_grpc/examples/transcode_http_handler.rs Example: call transcode_http directly without a Service.
crates/rest_over_grpc/src/axum_support.rs axum integration (IntoResponse) for neutral response types.
crates/rest_over_grpc/src/binding.rs Adds Binding type for captured path-variable bindings.
crates/rest_over_grpc/src/route_match.rs Adds RouteMatch type with inline binding storage optimization.
crates/rest_over_grpc/src/status.rs Adds neutral Status type with JSON-details support.
crates/rest_over_grpc/src/transcode/error.rs Adds TranscodeError and status mapping for transcoding failures.
crates/rest_over_grpc/src/transcode/field_deserializer.rs Adds internal deserializer used for body-field decoding.
crates/rest_over_grpc/src/transcode/percent.rs Adds minimal percent-decoding helpers for path/query bindings.
crates/rest_over_grpc/src/transcode/request_body_kind.rs Adds RequestBodyKind describing request-body mapping at runtime.
crates/rest_over_grpc/src/transcode/response_body_kind.rs Adds ResponseBodyKind describing response-body mapping at runtime.
crates/rest_over_grpc/tests/adapter.rs Integration tests for tower/layered HTTP adapters.
crates/rest_over_grpc/tests/axum_support.rs Integration tests for axum IntoResponse integration.
crates/rest_over_grpc/tests/streaming_adapter.rs Integration tests for streaming HTTP adapter and service wrapper.
crates/rest_over_grpc/tests/value_types.rs Integration tests for always-available value types (Code, Status, HttpResponse).
crates/rest_over_grpc_build/Cargo.toml Defines the new rest_over_grpc_build codegen crate and features.
crates/rest_over_grpc_build/CHANGELOG.md Introduces the crate changelog for initial release.
crates/rest_over_grpc_build/favicon.ico Adds crate branding asset (Git LFS).
crates/rest_over_grpc_build/logo.png Adds crate branding asset (Git LFS).
crates/rest_over_grpc_build/examples/generate_service.rs Example: generate service code from hand-built HttpRules.
crates/rest_over_grpc_build/src/binding.rs Models additional HTTP bindings and lowers them into routes.
crates/rest_over_grpc_build/src/descriptor_error.rs Adds descriptor decoding error type with predicates and Display.
crates/rest_over_grpc_build/src/descriptor_options.rs Adds options for decoding services/types from descriptor sets.
crates/rest_over_grpc_build/src/generator_builder.rs Adds builder for configuring generator options (Send bounds, tonic bridge, OpenAPI).
crates/rest_over_grpc_build/src/generator_output.rs Defines per-service generated output container.
crates/rest_over_grpc_build/src/http_method.rs Defines HttpMethod mapping and tokens for routing/codegen.
crates/rest_over_grpc_build/src/http_rule.rs Defines HttpRule model and lowering into Routes.
crates/rest_over_grpc_build/src/proto/google/api/annotations.proto Vendors google API annotations proto schema for consumers.
crates/rest_over_grpc_build/src/proto/google/api/http.proto Vendors google API http proto schema for consumers.
crates/rest_over_grpc_build/src/request_body.rs Models HttpRule.body as RequestBody with Display.
crates/rest_over_grpc_build/src/response_body.rs Models HttpRule.response_body as ResponseBody with Display.
crates/rest_over_grpc_build/src/route.rs Models lowered HTTP route components for router/dispatcher codegen.
crates/rest_over_grpc_build/src/service_method.rs Models a service method and its lowered routes for codegen.
crates/rest_over_grpc_bench/Cargo.toml Adds benchmarking/correctness crate for router/dispatcher behavior.
crates/rest_over_grpc_bench/bench_routes.rs Provides shared large route table for generated router + matchit comparison.
crates/rest_over_grpc_bench/benches/rog_dispatch_cg.rs Callgrind benchmark for end-to-end generated dispatcher.
crates/rest_over_grpc_bench/benches/rog_router_cg.rs Callgrind benchmark for generated router vs matchit.
crates/rest_over_grpc_bench/build.rs Generates routers from route tables at build time into OUT_DIR.
crates/rest_over_grpc_bench/src/lib.rs Includes generated routers and exposes resolve functions for tests/benches.
crates/rest_over_grpc_bench/tests/bench_router.rs Smoke tests verifying benchmark router resolves representative routes.
crates/rest_over_grpc_bench/tests/coverage.rs Routing correctness tests for tricky matching/backtracking cases.
crates/rest_over_grpc_custom_example/Cargo.toml Defines the custom/prost handler example crate (OpenAPI enabled).
crates/rest_over_grpc_custom_example/build.rs Builds prost+pbjson types and generates REST trait/dispatcher + OpenAPI.
crates/rest_over_grpc_custom_example/examples/client_streaming_upload.rs Example: compose non-transcoded streaming upload with transcoded JSON routes.
crates/rest_over_grpc_custom_example/examples/custom_body_handling.rs Example: custom body policy (caps/415/413) around generated dispatch.
crates/rest_over_grpc_custom_example/proto/google/api/annotations.proto Vendors google API annotations schema for the example.
crates/rest_over_grpc_custom_example/proto/google/api/http.proto Vendors google API http schema for the example.
crates/rest_over_grpc_custom_example/proto/library.proto Example proto annotated with google.api.http rules.
crates/rest_over_grpc_custom_example/src/lib.rs Implements generated REST service trait directly (no tonic bridge).
crates/rest_over_grpc_custom_example/tests/adapter.rs End-to-end tests driving generated dispatcher via HTTP adapter.
crates/rest_over_grpc_custom_example/tests/e2e.rs End-to-end transcoding tests (path/query/body, headers, details).
crates/rest_over_grpc_custom_example/tests/openapi.rs Validates generated OpenAPI 3.1 document content/structure.
crates/rest_over_grpc_example/Cargo.toml Defines the tonic-bridge example crate and build deps.
crates/rest_over_grpc_example/build.rs Generates tonic messages/server trait, pbjson serde, and REST bridge/dispatch.
crates/rest_over_grpc_example/examples/basic_dispatch.rs Example: call generated dispatch directly.
crates/rest_over_grpc_example/examples/custom_fallback.rs Example: try_dispatch for custom routing fallback behavior.
crates/rest_over_grpc_example/examples/streaming_response.rs Example: end-to-end streaming to wire via dispatch_streaming.
crates/rest_over_grpc_example/examples/tower_service.rs Example: serve tonic-bridged dispatcher through RestService (tower).
crates/rest_over_grpc_example/proto/google/api/annotations.proto Vendors google API annotations schema for the example.
crates/rest_over_grpc_example/proto/google/api/http.proto Vendors google API http schema for the example.
crates/rest_over_grpc_example/proto/greeter.proto Example proto (unary + server-streaming) annotated for REST transcoding.
crates/rest_over_grpc_example/src/lib.rs Implements tonic server trait and re-exports generated dispatcher.
crates/rest_over_grpc_example/tests/bridge.rs End-to-end tests verifying the tonic bridge dispatches and maps statuses.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/rest_over_grpc/src/transcode/error.rs
Comment thread crates/http_path_template/README.md
@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown

⚠️ Breaking Changes Detected

error: failed to retrieve local crate data from git revision

Caused by:
    0: failed to retrieve manifest file from git revision source
    1: possibly due to errors: [
         failed when reading /home/runner/work/oxidizer/oxidizer/target/semver-checks/git-origin_main/0f4bc2e85123fae041952c44976c56dbba3e69bc/scripts/crate-template/Cargo.toml: TOML parse error at line 9, column 26
         |
       9 | keywords = ["oxidizer", {{CRATE_KEYWORDS}}]
         |                          ^
       missing key for inline table element, expected key
       : TOML parse error at line 9, column 26
         |
       9 | keywords = ["oxidizer", {{CRATE_KEYWORDS}}]
         |                          ^
       missing key for inline table element, expected key
       ,
         failed to parse /home/runner/work/oxidizer/oxidizer/target/semver-checks/git-origin_main/0f4bc2e85123fae041952c44976c56dbba3e69bc/Cargo.toml: no `package` table,
       ]
    2: package `http_path_template` not found in /home/runner/work/oxidizer/oxidizer/target/semver-checks/git-origin_main/0f4bc2e85123fae041952c44976c56dbba3e69bc

Stack backtrace:
   0: anyhow::error::<impl anyhow::Error>::msg
   1: cargo_semver_checks::rustdoc_gen::RustdocFromProjectRoot::get_crate_source
   2: cargo_semver_checks::rustdoc_gen::StatefulRustdocGenerator<cargo_semver_checks::rustdoc_gen::CoupledState>::prepare_generator
   3: cargo_semver_checks::Check::check_release::{{closure}}
   4: cargo_semver_checks::Check::check_release
   5: cargo_semver_checks::exit_on_error
   6: cargo_semver_checks::main
   7: std::sys::backtrace::__rust_begin_short_backtrace
   8: main

If the breaking changes are intentional then everything is fine - this message is merely informative.

Remember to apply a version number bump with the correct severity when publishing a version with breaking changes (1.x.x -> 2.x.x or 0.1.x -> 0.2.x).

@codecov

codecov Bot commented Jul 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.94333% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 99.7%. Comparing base (5fd5568) to head (f8e31b6).

Files with missing lines Patch % Lines
crates/http_path_template/src/grammar.rs 70.0% 3 Missing ⚠️

❌ Your project check has failed because the head coverage (99.7%) is below the target coverage (100.0%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files
@@           Coverage Diff            @@
##             main    #546     +/-   ##
========================================
- Coverage   100.0%   99.7%   -0.3%     
========================================
  Files         356     401     +45     
  Lines       27388   34141   +6753     
========================================
+ Hits        27388   34065   +6677     
- Misses          0      76     +76     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI review requested due to automatic review settings July 6, 2026 00:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

Copilot AI review requested due to automatic review settings July 6, 2026 01:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

Copilot AI review requested due to automatic review settings July 6, 2026 01:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

Copilot AI review requested due to automatic review settings July 6, 2026 02:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

Copilot AI review requested due to automatic review settings July 6, 2026 04:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

Copilot AI review requested due to automatic review settings July 9, 2026 02:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

Copilot AI review requested due to automatic review settings July 9, 2026 05:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

Copilot AI review requested due to automatic review settings July 9, 2026 05:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

Copilot AI review requested due to automatic review settings July 9, 2026 10:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

Comment thread crates/http_path_template/src/lib.rs
Comment thread crates/http_path_template/src/lib.rs
Comment thread crates/http_path_template/src/lib.rs
Comment thread crates/http_path_template/src/lib.rs Outdated
/// );
/// ```
#[derive(Debug)]
pub struct ParseError {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not ohno? This appears to be hand-rolling part of ohno functionality for no obvious reason. We have an error library, let's use it.


//! Generating a REST service from `google.api.http` rules.
//!
//! Builds [`HttpRule`]s (normally read straight from proto annotations by

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am confused by this example. Why is it saying how things are done "normally"? Is this an "abnormal" example? To an uninformed reader the context of this example is hard to identity: "generating a REST service from 'google.api.http' rules" feels like a "normal" thing to do but this statement suggests to me I am doing it "abnormally" somehow. More clarity on what is special in this example would be desirable.

// Render the generated Rust for display; a build script would instead
// write the code to files under `OUT_DIR` with `Generator::write`.
for service in generated {
let mut code = service.r#trait().clone();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having to write r#trait() suggests some rather suboptimal naming. Might be better to avoid reserved keywords in public APIs.


//! Serving REST/JSON through the `layered` adapter.
//!
//! The repository's `layered::Service` is an `async fn`-with-`&self` alternative

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"The repository's" is cumbersome wording. Let's speak of the layered package, not of "the repository" - packages can move between repositories and readers might not always have context to understand what "the repository" refers to.


#[tokio::main(flavor = "current_thread")]
async fn main() {
// `layered::Service` needs no `Clone` and takes `&self`, so the service is

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unclear what the impact of this comment is. Why are we document things that are not? Same for the comment a few lines below.

It almost sounds as if this was made as a "comparison" but no comparand is in sight.

Comment thread crates/rest_over_grpc/src/lib.rs
//! // request and encoding the reply. Returns a `TranscodeResponse` (a buffered
//! // unary reply or a server-streaming frame stream); `None` when no route
//! // matches.
//! async fn try_transcode(&self, method: &str, target: &str,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about the stringiness here (over URI parts or similar), but maybe that comes from having to be compatible with a range of crates?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, this is the only lingua franca there is at this level of the stack.

//! composed alongside the transcoded JSON routes. See
//! `rest_over_grpc_examples`'s `examples/handling/client_streaming_upload.rs`.
//!
//! - **The request body is buffered as one JSON `&[u8]`.** The generated

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit, it's not the &[u8] that does buffering, but rather what it's exposed as?

// Licensed under the MIT License.

//! The serving layer: bridges the `http` / `http-body` ecosystem to the neutral
//! transcoder signature. Gated on the `serving` feature (on by default, and

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what the docrs attributes are for, this shouldn't be documented as text.

@@ -0,0 +1,84 @@
// Copyright 2024 Google LLC

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the idea that every user has to place exactly these files besides their project for the main annotations to work?

@@ -0,0 +1,124 @@
// Copyright (c) Microsoft Corporation.

@ralfbiedert ralfbiedert Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not very fond of most examples. There is a lot going on in both the library and the examples, and it's hard to know where to even start looking, everything is sort of related to everything else somehow, concept wise. Basic transcode is small enough to start wrapping my head around things, but even then I have to dive into LibraryServce, the generated "/tonic_bridge/library.rs" ...

Like is there a way to have basic examples of fundamental concepts only, say, 1/3 as large?

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

Expose an existing gRPC API as a traditional REST/JSON API in the same
process, driven by `google.api.http` annotations. The gRPC service is
implemented once; the REST layer is generated at build time and transcodes
requests and responses with minimal runtime overhead. The generated router is
built on a standalone, zero-allocation static router (`routerama`) that is also
useful on its own.

Crates added:

- `routerama`: dependency-free runtime for a compile-time static HTTP router —
  zero-allocation method + path matching returning the matched tag and captured
  path variables (with a SIMD segment scanner).
- `routerama_macros`: the `routes!` procedural macro that generates a static
  router inline from a named route enum, with no `build.rs` required.
- `routerama_build`: build-time code generator that lowers a route set into a
  `resolve` function (a nested `match` over path segments — a compile-time trie),
  reporting genuinely ambiguous routes as a `compile_error!`.
- `http_path_template`: dependency-free parser for the `google.api.http`
  path-template grammar (literals, `*`, `**`, `{field=sub}` variables, `:verb`),
  with an optional extended grammar for intra-segment prefix/suffix parameters.
- `rest_over_grpc`: framework-neutral transcoding crate spanning the runtime,
  the serving adapters, and the build-time code generator:
  - `transcoding` / `handling`: decode an HTTP request into a protobuf message,
    dispatch it to the gRPC handler, and encode the reply as JSON, mapping
    `Code` / `Status` to HTTP status codes.
  - `serving` (default, feature-gated): one-shot `serve_http*` helpers plus a
    `RestService` adapter for the `tower` and `layered` ecosystems (hyper, axum,
    …), serving both unary and server-streaming RPCs through one response type.
    Request bodies are buffered with an optional `with_max_body_bytes` cap
    (`413 Payload Too Large` on overflow), and read failures surface as
    `400 Bad Request` rather than an empty body.
  - Server-streaming responses are forwarded frame by frame as a JSON array,
    NDJSON, or SSE (negotiated from `Accept`); a unary reply is buffered, both
    through the same serving path.
  - `build` / `build-openapi`: a `build.rs` code generator that turns
    `google.api.http`-annotated gRPC services (read from compiled descriptors)
    into a static REST router, service traits, a dispatcher, an optional `tonic`
    bridge, and an optional OpenAPI 3.1 specification.
- `rest_over_grpc_examples`: worked examples organized by architecture layer,
  covering both the generated `tonic` bridge and a hand-written service that
  implements the generated trait directly.
- `rest_over_grpc_tests`: end-to-end tests and benchmarks for the generated
  router and dispatcher.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants