103 lines
3.5 KiB
Rust
103 lines
3.5 KiB
Rust
pub mod reqstatus;
|
|
|
|
use crate::bodystream::response;
|
|
use crate::err::Error;
|
|
use crate::ReqCtx;
|
|
use http::header;
|
|
use http::HeaderValue;
|
|
use http::Method;
|
|
use http::Request;
|
|
use http::StatusCode;
|
|
use http::Uri;
|
|
use httpclient::body_bytes;
|
|
use httpclient::body_empty;
|
|
use httpclient::body_stream;
|
|
use httpclient::connect_client;
|
|
use httpclient::read_body_bytes;
|
|
use httpclient::Requ;
|
|
use httpclient::StreamIncoming;
|
|
use httpclient::StreamResponse;
|
|
use netpod::log::*;
|
|
use netpod::query::api1::Api1Query;
|
|
use netpod::ProxyConfig;
|
|
use netpod::ACCEPT_ALL;
|
|
use netpod::X_DAQBUF_REQID;
|
|
|
|
pub struct PythonDataApi1Query {}
|
|
|
|
impl PythonDataApi1Query {
|
|
pub fn path() -> &'static str {
|
|
"/api/1/query"
|
|
}
|
|
|
|
pub fn handler(req: &Requ) -> Option<Self> {
|
|
if req.uri().path() == Self::path() {
|
|
Some(Self {})
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
pub async fn handle(&self, req: Requ, _ctx: &ReqCtx, proxy_config: &ProxyConfig) -> Result<StreamResponse, Error> {
|
|
if req.method() != Method::POST {
|
|
return Ok(response(StatusCode::METHOD_NOT_ALLOWED).body(body_empty())?);
|
|
}
|
|
let (head, body) = req.into_parts();
|
|
let _accept = head
|
|
.headers
|
|
.get(http::header::ACCEPT)
|
|
.map_or(Ok(ACCEPT_ALL), |k| k.to_str())
|
|
.map_err(|e| Error::with_msg_no_trace(format!("{e:?}")))?
|
|
.to_owned();
|
|
let body_data = read_body_bytes(body).await?;
|
|
if body_data.len() < 512 && body_data.first() == Some(&"{".as_bytes()[0]) {
|
|
info!("request body_data string: {}", String::from_utf8_lossy(&body_data));
|
|
}
|
|
let qu = match serde_json::from_slice::<Api1Query>(&body_data) {
|
|
Ok(qu) => qu,
|
|
Err(e) => {
|
|
error!("got body_data: {:?}", String::from_utf8_lossy(&body_data[..]));
|
|
error!("can not parse: {e}");
|
|
return Err(Error::with_msg_no_trace("can not parse query"));
|
|
}
|
|
};
|
|
info!("Proxy sees request: {qu:?}");
|
|
let back = {
|
|
let mut ret = None;
|
|
for b in &proxy_config.backends {
|
|
if b.name == "sf-databuffer" {
|
|
ret = Some(b);
|
|
break;
|
|
}
|
|
}
|
|
ret
|
|
};
|
|
if let Some(back) = back {
|
|
let url_str = format!("{}/api/1/query", back.url);
|
|
info!("try to ask {url_str}");
|
|
let uri: Uri = url_str.parse()?;
|
|
let req = Request::builder()
|
|
.method(Method::POST)
|
|
.header(header::HOST, uri.host().unwrap())
|
|
.uri(&uri)
|
|
.body(body_bytes(body_data))?;
|
|
let mut client = connect_client(&uri).await?;
|
|
let res = client.send_request(req).await?;
|
|
let (head, body) = res.into_parts();
|
|
if head.status != StatusCode::OK {
|
|
error!("backend returned error: {head:?}");
|
|
Ok(response(StatusCode::INTERNAL_SERVER_ERROR).body(body_empty())?)
|
|
} else {
|
|
info!("backend returned OK");
|
|
let riq_def = HeaderValue::from_static("(none)");
|
|
let riq = head.headers.get(X_DAQBUF_REQID).unwrap_or(&riq_def);
|
|
Ok(response(StatusCode::OK)
|
|
.header(X_DAQBUF_REQID, riq)
|
|
.body(body_stream(StreamIncoming::new(body)))?)
|
|
}
|
|
} else {
|
|
Ok(response(StatusCode::INTERNAL_SERVER_ERROR).body(body_empty())?)
|
|
}
|
|
}
|
|
}
|