mirror of
https://github.com/actix/examples
synced 2025-01-22 14:05:55 +01:00
94 lines
2.4 KiB
Rust
94 lines
2.4 KiB
Rust
use actix_web::{
|
|
body::MessageBody,
|
|
dev::{ServiceFactory, ServiceRequest, ServiceResponse},
|
|
get,
|
|
guard::{Guard, GuardContext},
|
|
middleware::DefaultHeaders,
|
|
web, App, Error, HttpServer, Responder,
|
|
};
|
|
|
|
mod v1 {
|
|
use super::*;
|
|
|
|
pub struct ApiGuard;
|
|
|
|
impl Guard for ApiGuard {
|
|
fn check(&self, ctx: &GuardContext<'_>) -> bool {
|
|
ctx.head()
|
|
.headers()
|
|
.get("Accept-Version")
|
|
.map_or(false, |hv| hv.as_bytes() == b"1")
|
|
}
|
|
}
|
|
|
|
#[get("/hello")]
|
|
pub async fn hello() -> impl Responder {
|
|
"Hello World from v1 API!"
|
|
}
|
|
}
|
|
|
|
mod v2 {
|
|
use super::*;
|
|
|
|
pub struct ApiGuard;
|
|
|
|
impl Guard for ApiGuard {
|
|
fn check(&self, ctx: &GuardContext<'_>) -> bool {
|
|
ctx.head()
|
|
.headers()
|
|
.get("Accept-Version")
|
|
.map_or(false, |hv| hv.as_bytes() == b"2")
|
|
}
|
|
}
|
|
|
|
#[get("/hello")]
|
|
pub async fn hello() -> impl Responder {
|
|
"Hello World from the awesome new v2 API!"
|
|
}
|
|
}
|
|
|
|
fn create_app() -> App<
|
|
impl ServiceFactory<
|
|
ServiceRequest,
|
|
Response = ServiceResponse<impl MessageBody>,
|
|
Config = (),
|
|
InitError = (),
|
|
Error = Error,
|
|
>,
|
|
> {
|
|
App::new()
|
|
.service(web::scope("/api").guard(v1::ApiGuard).service(v1::hello))
|
|
.service(web::scope("/api").guard(v2::ApiGuard).service(v2::hello))
|
|
// using this form of API version selection means that we need to send a Vary header so that
|
|
// caches won't try to serve the wrong response
|
|
.wrap(DefaultHeaders::new().add(("Vary", "Accept-Version")))
|
|
}
|
|
|
|
#[actix_web::main]
|
|
async fn main() -> std::io::Result<()> {
|
|
HttpServer::new(create_app)
|
|
.bind(("127.0.0.1", 8080))?
|
|
.run()
|
|
.await
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use actix_web::test::{self, TestRequest};
|
|
|
|
use super::*;
|
|
|
|
#[actix_web::test]
|
|
async fn api_versioning() {
|
|
let app = test::init_service(create_app()).await;
|
|
|
|
let req = TestRequest::with_uri("/api/hello").insert_header(("Accept-Version", "1"));
|
|
let res = test::call_and_read_body(&app, req.to_request()).await;
|
|
assert_eq!(res, "Hello World from v1 API!");
|
|
|
|
let req = TestRequest::with_uri("/api/hello").insert_header(("Accept-Version", "2"));
|
|
let res = test::call_and_read_body(&app, req.to_request()).await;
|
|
assert_eq!(res, "Hello World from the awesome new v2 API!");
|
|
}
|
|
}
|