mirror of
https://github.com/actix/examples
synced 2024-11-27 16:02:57 +01:00
Return HttpResponse from middleware.
This commit is contained in:
parent
2df944c5e5
commit
123cd8fa95
12
middleware/middleware-return-httpresponse/Cargo.toml
Normal file
12
middleware/middleware-return-httpresponse/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "middleware-return-httpresponse"
|
||||||
|
version = "1.0.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
actix-web = "4"
|
||||||
|
env_logger = "0.9"
|
||||||
|
futures-util = { version = "0.3.17", default-features = false, features = ["std"] }
|
||||||
|
log = "0.4"
|
||||||
|
pin-project = "1"
|
||||||
|
serde = { version = "*", features = ["derive"] }
|
35
middleware/middleware-return-httpresponse/README.md
Normal file
35
middleware/middleware-return-httpresponse/README.md
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
## Middleware : Return HttpResponse from Middleware
|
||||||
|
|
||||||
|
```rs
|
||||||
|
cd middleware-return-httpresponse
|
||||||
|
cargo run
|
||||||
|
# Started http server: 127.0.0.1:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
## What is this?
|
||||||
|
|
||||||
|
A Middleware example which returning HttpResponse.
|
||||||
|
|
||||||
|
## How to test
|
||||||
|
|
||||||
|
### success case
|
||||||
|
```sh
|
||||||
|
curl http://127.0.0.1:8080/ -H 'Authorization:ok' | json_pp -json_opt pretty,canonical
|
||||||
|
% Total % Received % Xferd Average Speed Time Time Time Current
|
||||||
|
Dload Upload Total Spent Left Speed
|
||||||
|
100 42 100 42 0 0 42000 0 --:--:-- --:--:-- --:--:-- 42000
|
||||||
|
{
|
||||||
|
"data" : "Hello this is success response!"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### failed case
|
||||||
|
```sh
|
||||||
|
curl http://127.0.0.1:8080/ | json_pp -json_opt pretty,canonical
|
||||||
|
% Total % Received % Xferd Average Speed Time Time Time Current
|
||||||
|
Dload Upload Total Spent Left Speed
|
||||||
|
100 102 100 102 0 0 99k 0 --:--:-- --:--:-- --:--:-- 99k
|
||||||
|
{
|
||||||
|
"data" : "Hello this is default error message! you need to set Authorization header to get thru this."
|
||||||
|
}
|
||||||
|
```
|
40
middleware/middleware-return-httpresponse/src/main.rs
Normal file
40
middleware/middleware-return-httpresponse/src/main.rs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
use actix_web::{web, App, HttpServer, HttpResponse};
|
||||||
|
|
||||||
|
mod simple;
|
||||||
|
|
||||||
|
// You can move this struct to a separate file.
|
||||||
|
// this struct below just for example.
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct HttpData {
|
||||||
|
pub data: String,
|
||||||
|
}
|
||||||
|
// this implementation is optional
|
||||||
|
impl Default for HttpData {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
data: "Hello this is success response!".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_web::main]
|
||||||
|
async fn main() -> std::io::Result<()> {
|
||||||
|
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
||||||
|
|
||||||
|
log::info!("starting HTTP server at http://localhost:8080");
|
||||||
|
|
||||||
|
HttpServer::new(|| {
|
||||||
|
App::new()
|
||||||
|
.wrap(simple::ReturnHttpResponse)
|
||||||
|
.service(
|
||||||
|
web::resource("/").to(|| async {
|
||||||
|
HttpResponse::Ok().json(HttpData::default())
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.bind(("127.0.0.1", 8080))?
|
||||||
|
.run()
|
||||||
|
.await
|
||||||
|
}
|
91
middleware/middleware-return-httpresponse/src/simple.rs
Normal file
91
middleware/middleware-return-httpresponse/src/simple.rs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
use std::{
|
||||||
|
future::{ready, Ready},
|
||||||
|
rc::Rc
|
||||||
|
};
|
||||||
|
|
||||||
|
use actix_web::{
|
||||||
|
dev::{self, Service, ServiceRequest, ServiceResponse, Transform},
|
||||||
|
Error,
|
||||||
|
http::{header, StatusCode}, HttpResponseBuilder
|
||||||
|
};
|
||||||
|
use futures_util::future::LocalBoxFuture;
|
||||||
|
|
||||||
|
|
||||||
|
// You can move this struct to a separate file.
|
||||||
|
// this struct below just for example.
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct HttpData {
|
||||||
|
pub data: String,
|
||||||
|
}
|
||||||
|
// this implementation is optional
|
||||||
|
impl Default for HttpData {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
data: "Hello this is default error message! you need to set Authorization header to get thru this.".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub struct ReturnHttpResponse;
|
||||||
|
|
||||||
|
impl<S: 'static> Transform<S, ServiceRequest> for ReturnHttpResponse
|
||||||
|
where
|
||||||
|
S: Service<ServiceRequest, Response = ServiceResponse, Error = Error>,
|
||||||
|
S::Future: 'static
|
||||||
|
{
|
||||||
|
type Response = ServiceResponse;
|
||||||
|
type Error = Error;
|
||||||
|
type InitError = ();
|
||||||
|
type Transform = AuthMiddleware<S>;
|
||||||
|
type Future = Ready<Result<Self::Transform, Self::InitError>>;
|
||||||
|
|
||||||
|
fn new_transform(&self, service: S) -> Self::Future {
|
||||||
|
ready(Ok(AuthMiddleware {
|
||||||
|
service: Rc::new(service),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AuthMiddleware<S> {
|
||||||
|
// This is special: We need this to avoid lifetime issues.
|
||||||
|
service: Rc<S>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> Service<ServiceRequest> for AuthMiddleware<S>
|
||||||
|
where
|
||||||
|
S: Service<ServiceRequest, Response = ServiceResponse, Error = Error> + 'static,
|
||||||
|
S::Future: 'static
|
||||||
|
{
|
||||||
|
type Response = ServiceResponse;
|
||||||
|
type Error = Error;
|
||||||
|
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
|
||||||
|
|
||||||
|
dev::forward_ready!(service);
|
||||||
|
|
||||||
|
fn call(&self, req: ServiceRequest) -> Self::Future {
|
||||||
|
let svc = self.service.clone();
|
||||||
|
|
||||||
|
Box::pin(async move {
|
||||||
|
|
||||||
|
let headers = req.headers();
|
||||||
|
let _ = match headers.get("Authorization") {
|
||||||
|
Some(e) => e,
|
||||||
|
None => {
|
||||||
|
let new_response = HttpResponseBuilder::new(StatusCode::BAD_REQUEST)
|
||||||
|
.insert_header((header::CONTENT_TYPE, "application/json"))
|
||||||
|
.json(HttpData::default());
|
||||||
|
return Ok(ServiceResponse::new(
|
||||||
|
req.request().to_owned(), /* or req.request().clone() */
|
||||||
|
new_response
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let res = svc.call(req).await?;
|
||||||
|
Ok(res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user