Skip to content

Commit

Permalink
feat(raiko): api versioning (#196)
Browse files Browse the repository at this point in the history
* chore: Move server.rs into server/mod.rs

* feat: Add API versioning

---------

Co-authored-by: Brecht Devos <Brechtp.Devos@gmail.com>
  • Loading branch information
petarvujovic98 and Brechtpd authored May 14, 2024
1 parent 105c0c6 commit 09e0005
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 95 deletions.
102 changes: 8 additions & 94 deletions host/src/server/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,98 +6,17 @@ use axum::{
response::Response,
Router,
};
use raiko_lib::input::GuestOutput;
use serde::Serialize;
use tower::ServiceBuilder;
use tower_http::{
compression::CompressionLayer,
cors::{self, CorsLayer},
set_header::SetResponseHeaderLayer,
trace::TraceLayer,
};
use utoipa::{OpenApi, ToSchema};
use utoipa_scalar::{Scalar, Servable};
use utoipa_swagger_ui::SwaggerUi;

use crate::ProverState;

mod health;
mod metrics;
mod proof;

#[derive(OpenApi)]
#[openapi(
info(
title = "Raiko Proverd Server API",
version = "1.0",
description = "Raiko Proverd Server API",
contact(
name = "API Support",
url = "https://community.taiko.xyz",
email = "info@taiko.xyz",
),
license(
name = "MIT",
url = "https://github.com/taikoxyz/raiko/blob/taiko/unstable/LICENSE"
),
),
components(
schemas(
crate::request::ProofRequestOpt,
crate::error::HostError,
crate::request::ProverSpecificOpts,
GuestOutputDoc,
ProofResponse,
)
),
tags(
(name = "Proving", description = "Routes that handle proving requests"),
(name = "Health", description = "Routes that report the server health status"),
(name = "Metrics", description = "Routes that give detailed insight into the server")
)
)]
/// The root API struct which is generated from the `OpenApi` derive macro.
pub struct Docs;

#[derive(Debug, Serialize, ToSchema)]
/// The response body of a proof request.
pub struct ProofResponse {
#[schema(value_type = Option<GuestOutputDoc>)]
/// The output of the prover.
output: Option<GuestOutput>,
/// The proof.
proof: Option<String>,
/// The quote.
quote: Option<String>,
}

#[derive(Debug, Serialize, ToSchema)]
pub enum GuestOutputDoc {
#[schema(example = json!({"header": [0, 0, 0, 0], "hash":"0x0...0"}))]
/// The output of the prover when the proof generation was successful.
Success {
/// Header bytes.
header: Vec<u8>,
/// Instance hash.
hash: String,
},
/// The output of the prover when the proof generation failed.
Failure,
}

#[must_use]
pub fn create_docs() -> utoipa::openapi::OpenApi {
[
health::create_docs(),
metrics::create_docs(),
proof::create_docs(),
]
.into_iter()
.fold(Docs::openapi(), |mut doc, sub_doc| {
doc.merge(sub_doc);
doc
})
}
mod v1;

pub fn create_router(concurrency_limit: usize) -> Router<ProverState> {
let cors = CorsLayer::new()
Expand All @@ -120,28 +39,23 @@ pub fn create_router(concurrency_limit: usize) -> Router<ProverState> {

let trace = TraceLayer::new_for_http();

let docs = create_docs();
let v1_api = v1::create_router(concurrency_limit);

Router::new()
// Only add the concurrency limit to the proof route. We want to still be able to call
// healthchecks and metrics to have insight into the system.
.nest(
"/proof",
proof::create_router()
.layer(ServiceBuilder::new().concurrency_limit(concurrency_limit)),
)
.nest("/health", health::create_router())
.nest("/metrics", metrics::create_router())
.nest("/v1", v1_api.clone())
.merge(v1_api)
.layer(middleware)
.layer(middleware::from_fn(check_max_body_size))
.layer(trace)
.merge(SwaggerUi::new("/swagger-ui").url("/api-docs/openapi.json", docs.clone()))
.merge(Scalar::with_url("/scalar", docs))
.fallback(|uri: Uri| async move {
(StatusCode::NOT_FOUND, format!("No handler found for {uri}"))
})
}

pub fn create_docs() -> utoipa::openapi::OpenApi {
v1::create_docs()
}

async fn check_max_body_size(req: Request, next: Next) -> Response {
const MAX_BODY_SIZE: u64 = 1 << 20;
let response_content_length = match req.body().size_hint().upper() {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{error::HostResult, ProverState};
path = "/metrics",
tag = "Metrics",
responses (
(status = 200, description = "The metrics have been captured successfuly"),
(status = 200, description = "The metrics have been captured successfully"),
),
)]
#[debug_handler(state = ProverState)]
Expand Down
105 changes: 105 additions & 0 deletions host/src/server/api/v1/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use axum::Router;
use raiko_lib::input::GuestOutput;
use serde::Serialize;
use tower::ServiceBuilder;
use utoipa::{OpenApi, ToSchema};
use utoipa_scalar::{Scalar, Servable};
use utoipa_swagger_ui::SwaggerUi;

use crate::ProverState;

mod health;
mod metrics;
mod proof;

#[derive(OpenApi)]
#[openapi(
info(
title = "Raiko Proverd Server API",
version = "1.0",
description = "Raiko Proverd Server API",
contact(
name = "API Support",
url = "https://community.taiko.xyz",
email = "info@taiko.xyz",
),
license(
name = "MIT",
url = "https://github.com/taikoxyz/raiko/blob/taiko/unstable/LICENSE"
),
),
components(
schemas(
crate::request::ProofRequestOpt,
crate::error::HostError,
crate::request::ProverSpecificOpts,
GuestOutputDoc,
ProofResponse,
)
),
tags(
(name = "Proving", description = "Routes that handle proving requests"),
(name = "Health", description = "Routes that report the server health status"),
(name = "Metrics", description = "Routes that give detailed insight into the server")
)
)]
/// The root API struct which is generated from the `OpenApi` derive macro.
pub struct Docs;

#[derive(Debug, Serialize, ToSchema)]
/// The response body of a proof request.
pub struct ProofResponse {
#[schema(value_type = Option<GuestOutputDoc>)]
/// The output of the prover.
output: Option<GuestOutput>,
/// The proof.
proof: Option<String>,
/// The quote.
quote: Option<String>,
}

#[derive(Debug, Serialize, ToSchema)]
#[allow(dead_code)]
pub enum GuestOutputDoc {
#[schema(example = json!({"header": [0, 0, 0, 0], "hash":"0x0...0"}))]
/// The output of the prover when the proof generation was successful.
Success {
/// Header bytes.
header: Vec<u8>,
/// Instance hash.
hash: String,
},
/// The output of the prover when the proof generation failed.
Failure,
}

#[must_use]
pub fn create_docs() -> utoipa::openapi::OpenApi {
[
health::create_docs(),
metrics::create_docs(),
proof::create_docs(),
]
.into_iter()
.fold(Docs::openapi(), |mut doc, sub_doc| {
doc.merge(sub_doc);
doc
})
}

pub fn create_router(concurrency_limit: usize) -> Router<ProverState> {
let docs = create_docs();

Router::new()
// Only add the concurrency limit to the proof route. We want to still be able to call
// healthchecks and metrics to have insight into the system.
.nest(
"/proof",
proof::create_router()
.layer(ServiceBuilder::new().concurrency_limit(concurrency_limit)),
)
.nest("/health", health::create_router())
.nest("/metrics", metrics::create_router())
.merge(SwaggerUi::new("/swagger-ui").url("/api-docs/openapi.json", docs.clone()))
.merge(Scalar::with_url("/scalar", docs))
}
File renamed without changes.
File renamed without changes.

0 comments on commit 09e0005

Please sign in to comment.