this repo has no description
1use axum::{
2 extract::{Path, Query},
3 http::{HeaderMap, Method, StatusCode},
4 response::{IntoResponse, Response},
5 body::Bytes,
6};
7use reqwest::Client;
8use tracing::{info, error};
9use std::collections::HashMap;
10
11pub async fn proxy_handler(
12 Path(method): Path<String>,
13 method_verb: Method,
14 headers: HeaderMap,
15 Query(params): Query<HashMap<String, String>>,
16 body: Bytes,
17) -> Response {
18
19 let proxy_header = headers.get("atproto-proxy")
20 .and_then(|h| h.to_str().ok())
21 .map(|s| s.to_string());
22
23 let appview_url = match proxy_header {
24 Some(url) => url,
25 None => match std::env::var("APPVIEW_URL") {
26 Ok(url) => url,
27 Err(_) => return (StatusCode::BAD_GATEWAY, "No upstream AppView configured").into_response(),
28 },
29 };
30
31 let target_url = format!("{}/xrpc/{}", appview_url, method);
32
33 info!("Proxying {} request to {}", method_verb, target_url);
34
35 let client = Client::new();
36
37 let mut request_builder = client
38 .request(method_verb, &target_url)
39 .query(¶ms);
40
41 for (key, value) in headers.iter() {
42 if key != "host" && key != "content-length" {
43 request_builder = request_builder.header(key, value);
44 }
45 }
46
47 request_builder = request_builder.body(body);
48
49 match request_builder.send().await {
50 Ok(resp) => {
51 let status = resp.status();
52 let headers = resp.headers().clone();
53 let body = match resp.bytes().await {
54 Ok(b) => b,
55 Err(e) => {
56 error!("Error reading proxy response body: {:?}", e);
57 return (StatusCode::BAD_GATEWAY, "Error reading upstream response").into_response();
58 }
59 };
60
61 let mut response_builder = Response::builder().status(status);
62
63 for (key, value) in headers.iter() {
64 response_builder = response_builder.header(key, value);
65 }
66
67 match response_builder.body(axum::body::Body::from(body)) {
68 Ok(r) => r,
69 Err(e) => {
70 error!("Error building proxy response: {:?}", e);
71 (StatusCode::INTERNAL_SERVER_ERROR, "Internal Server Error").into_response()
72 }
73 }
74 },
75 Err(e) => {
76 error!("Error sending proxy request: {:?}", e);
77 if e.is_timeout() {
78 (StatusCode::GATEWAY_TIMEOUT, "Upstream Timeout").into_response()
79 } else {
80 (StatusCode::BAD_GATEWAY, "Upstream Error").into_response()
81 }
82 }
83 }
84}