#![cfg(all(feature = "worker", target_arch = "wasm32"))]
use bytes::Bytes;
use http::Request as HttpRequest;
use http_body_util::BodyExt;
use worker::{Headers as WHeaders, Request as WRequest, Response as WResponse};
use crate::core::req_body::ReqBody;
use crate::core::request::Request as SRequest;
use crate::core::res_body::ResBody;
use crate::core::response::Response as SResponse;
use crate::handler::Handler;
use crate::route::Route;
pub struct WorkRoute {
pub route: Route,
}
impl WorkRoute {
pub fn new(route: Route) -> Self {
Self { route }
}
pub fn with_state<T: Send + Sync + Clone + 'static>(mut self, val: T) -> Self {
self.route = self.route.with_state(val);
self
}
#[deprecated(since = "2.16.0", note = "请使用 with_state 代替")]
pub fn with_configs(mut self, configs: crate::State) -> Self {
self.route.set_state(Some(configs));
self
}
pub async fn call(&self, req: WRequest) -> WResponse {
match self.handle(req).await {
Ok(resp) => resp,
Err(e) => WResponse::builder()
.with_status(500)
.fixed(format!("internal error: {e}").into_bytes()),
}
}
async fn handle(&self, req: WRequest) -> worker::Result<WResponse> {
let sreq = to_silent_request(req).await?;
let mut sres = match self.route.call(sreq).await {
Ok(r) => r,
Err(e) => {
let status = e.status();
let mut r = SResponse::empty();
r.set_status(status);
r.set_body(ResBody::from(e.to_string()));
r
}
};
to_worker_response(&mut sres).await
}
}
async fn to_silent_request(mut req: WRequest) -> worker::Result<SRequest> {
let method: http::Method = req
.method()
.as_ref()
.parse::<http::Method>()
.map_err(|e| worker::Error::RustError(e.to_string()))?;
let uri = req.url()?.as_str().to_string();
let mut base: HttpRequest<()> = HttpRequest::builder()
.method(method)
.uri(uri)
.body(())
.map_err(|e| worker::Error::RustError(format!("build request failed: {e}")))?;
let hmap: http::HeaderMap = req.headers().into();
*base.headers_mut() = hmap;
let body_bytes = req.bytes().await.unwrap_or_default();
let body = if body_bytes.is_empty() {
ReqBody::Empty
} else {
ReqBody::Once(Bytes::from(body_bytes))
};
let (parts, _) = base.into_parts();
Ok(SRequest::from_parts(parts, body))
}
async fn to_worker_response(res: &mut SResponse) -> worker::Result<WResponse> {
let status = res.status().as_u16();
let headers = WHeaders::from(res.headers().clone());
let body = res.take_body();
let bytes = match body {
ResBody::None => Vec::new(),
ResBody::Once(b) => b.to_vec(),
other => other
.collect()
.await
.map_err(|e| worker::Error::RustError(format!("collect body error: {e}")))?
.to_bytes()
.to_vec(),
};
let mut wres = WResponse::from_bytes(bytes)?;
wres = wres.with_status(status);
Ok(wres.with_headers(headers))
}