Add pocketbase and other changes
This commit is contained in:
parent
a9717d570d
commit
229150b641
14 changed files with 1178 additions and 91 deletions
90
server-rs/src/routes/pb_proxy.rs
Normal file
90
server-rs/src/routes/pb_proxy.rs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use axum::body::Body;
|
||||
use axum::extract::Request;
|
||||
use axum::http::{HeaderName, StatusCode};
|
||||
use axum::response::{IntoResponse, Response};
|
||||
use tracing::warn;
|
||||
|
||||
use crate::state::AppState;
|
||||
|
||||
pub async fn proxy_to_pocketbase(state: Arc<AppState>, req: Request) -> impl IntoResponse {
|
||||
let pb_url = match &state.pocketbase_url {
|
||||
Some(url) => url.trim_end_matches('/'),
|
||||
None => {
|
||||
return Response::builder()
|
||||
.status(StatusCode::SERVICE_UNAVAILABLE)
|
||||
.body(Body::from("PocketBase not configured"))
|
||||
.unwrap();
|
||||
}
|
||||
};
|
||||
|
||||
let path = req.uri().path();
|
||||
let target_path = path.strip_prefix("/pb").unwrap_or(path);
|
||||
let query = req
|
||||
.uri()
|
||||
.query()
|
||||
.map(|qs| format!("?{qs}"))
|
||||
.unwrap_or_default();
|
||||
let url = format!("{pb_url}{target_path}{query}");
|
||||
|
||||
let method = req.method().clone();
|
||||
let mut builder = state.http_client.request(method, &url);
|
||||
|
||||
// Forward headers except host
|
||||
for (name, value) in req.headers() {
|
||||
if name != "host" {
|
||||
builder = builder.header(name.clone(), value.clone());
|
||||
}
|
||||
}
|
||||
|
||||
// Forward body
|
||||
let body_bytes = match axum::body::to_bytes(req.into_body(), 10 * 1024 * 1024).await {
|
||||
Ok(bytes) => bytes,
|
||||
Err(err) => {
|
||||
warn!("Failed to read request body: {err}");
|
||||
return Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body(Body::from("Failed to read request body"))
|
||||
.unwrap();
|
||||
}
|
||||
};
|
||||
builder = builder.body(body_bytes);
|
||||
|
||||
match builder.send().await {
|
||||
Ok(upstream) => {
|
||||
let status = upstream.status();
|
||||
let mut response = Response::builder().status(status);
|
||||
|
||||
for (name, value) in upstream.headers() {
|
||||
// Skip hop-by-hop headers
|
||||
if name == "transfer-encoding" {
|
||||
continue;
|
||||
}
|
||||
response = response.header(
|
||||
HeaderName::from_bytes(name.as_ref())
|
||||
.unwrap_or(HeaderName::from_static("x-invalid")),
|
||||
value.clone(),
|
||||
);
|
||||
}
|
||||
|
||||
match upstream.bytes().await {
|
||||
Ok(bytes) => response.body(Body::from(bytes)).unwrap(),
|
||||
Err(err) => {
|
||||
warn!("Failed to read upstream response: {err}");
|
||||
Response::builder()
|
||||
.status(StatusCode::BAD_GATEWAY)
|
||||
.body(Body::from("Failed to read upstream response"))
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
warn!("PocketBase proxy error: {err}");
|
||||
Response::builder()
|
||||
.status(StatusCode::BAD_GATEWAY)
|
||||
.body(Body::from("PocketBase unavailable"))
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue