|
| 1 | +use axum::{ |
| 2 | + body::Body, extract::FromRequest, extract::Multipart, extract::Request, response::Response, |
| 3 | +}; |
| 4 | +use http::StatusCode; |
| 5 | + |
| 6 | +// See: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#the_http_response_headers |
| 7 | +pub fn with_permissive_cors(r: http::response::Builder) -> http::response::Builder { |
| 8 | + r.header("Access-Control-Allow-Headers", "*") |
| 9 | + .header("Access-Control-Allow-Methods", "*") |
| 10 | + .header("Access-Control-Allow-Origin", "*") |
| 11 | +} |
| 12 | + |
| 13 | +pub async fn handler_with_cors(req: Request<Body>) -> Response<Body> { |
| 14 | + println!("{:?}", req); |
| 15 | + |
| 16 | + // Check if this is an OPTIONS request |
| 17 | + if req.method() == http::Method::OPTIONS { |
| 18 | + return with_permissive_cors(Response::builder()) |
| 19 | + .status(StatusCode::OK) |
| 20 | + .header("Content-Type", "text/plain") |
| 21 | + .body(Body::from("This is allowing most CORS requests")) |
| 22 | + .unwrap(); |
| 23 | + } |
| 24 | + |
| 25 | + // For POST requests, extract multipart data |
| 26 | + let (parts, body) = req.into_parts(); |
| 27 | + let body_stream = axum::body::Body::new(body); |
| 28 | + |
| 29 | + // Reconstruct the request for multipart extraction |
| 30 | + let request = Request::from_parts(parts, body_stream); |
| 31 | + |
| 32 | + // Use Axum's built-in multipart extractor |
| 33 | + match Multipart::from_request(request, &()).await { |
| 34 | + Ok(multipart) => process_multipart(multipart).await, |
| 35 | + Err(err) => with_permissive_cors(Response::builder()) |
| 36 | + .status(StatusCode::BAD_REQUEST) |
| 37 | + .body(Body::from(format!( |
| 38 | + "Failed to extract multipart data: {}", |
| 39 | + err |
| 40 | + ))) |
| 41 | + .unwrap(), |
| 42 | + } |
| 43 | +} |
| 44 | + |
| 45 | +// Process the multipart data, using Axum's multipart exmaple |
| 46 | +// See: https://github.com/tokio-rs/axum/blob/main/examples/multipart-form/src/main.rs |
| 47 | +async fn process_multipart(mut multipart: Multipart) -> Response<Body> { |
| 48 | + while let Some(field) = multipart.next_field().await.unwrap() { |
| 49 | + let name = field.name().unwrap().to_string(); |
| 50 | + let file_name = field.file_name().unwrap().to_string(); |
| 51 | + let content_type = field.content_type().unwrap().to_string(); |
| 52 | + let data = field.bytes().await.unwrap(); |
| 53 | + |
| 54 | + println!( |
| 55 | + "Length of `{name}` (`{file_name}`: `{content_type}`) is {} bytes", |
| 56 | + data.len() |
| 57 | + ); |
| 58 | + } |
| 59 | + |
| 60 | + with_permissive_cors(Response::builder()) |
| 61 | + .status(StatusCode::OK) |
| 62 | + .header("Content-Type", "text/plain") |
| 63 | + .body(Body::from("Multipart data processed successfully")) |
| 64 | + .unwrap() |
| 65 | +} |
0 commit comments