Add json-framed encoding, docs, refactor
This commit is contained in:
39
crates/httpret/src/proxy/api4/backend.rs
Normal file
39
crates/httpret/src/proxy/api4/backend.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
use crate::bodystream::response;
|
||||
use crate::err::Error;
|
||||
use crate::requests::accepts_json_or_all;
|
||||
use http::Method;
|
||||
use http::StatusCode;
|
||||
use httpclient::body_empty;
|
||||
use httpclient::body_string;
|
||||
use httpclient::Requ;
|
||||
use httpclient::StreamResponse;
|
||||
use netpod::ProxyConfig;
|
||||
use netpod::ReqCtx;
|
||||
|
||||
pub struct BackendListHandler {}
|
||||
|
||||
impl BackendListHandler {
|
||||
pub fn handler(req: &Requ) -> Option<Self> {
|
||||
if req.uri().path() == "/api/4/backend/list" {
|
||||
Some(Self {})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn handle(&self, req: Requ, _ctx: &ReqCtx, _node_config: &ProxyConfig) -> Result<StreamResponse, Error> {
|
||||
if req.method() == Method::GET {
|
||||
if accepts_json_or_all(req.headers()) {
|
||||
let res = serde_json::json!({
|
||||
"backends_available": ["sf-databuffer"]
|
||||
});
|
||||
let body = serde_json::to_string(&res)?;
|
||||
Ok(response(StatusCode::OK).body(body_string(body))?)
|
||||
} else {
|
||||
Ok(response(StatusCode::BAD_REQUEST).body(body_empty())?)
|
||||
}
|
||||
} else {
|
||||
Ok(response(StatusCode::METHOD_NOT_ALLOWED).body(body_empty())?)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::bodystream::response;
|
||||
use crate::bodystream::response_err_msg;
|
||||
use crate::err::Error;
|
||||
use crate::proxy::get_query_host_for_backend;
|
||||
use crate::requests::accepts_cbor_frames;
|
||||
use crate::requests::accepts_cbor_framed;
|
||||
use crate::requests::accepts_json_framed;
|
||||
use crate::requests::accepts_json_or_all;
|
||||
use crate::ReqCtx;
|
||||
use http::header;
|
||||
@@ -22,7 +22,8 @@ use netpod::req_uri_to_url;
|
||||
use netpod::FromUrl;
|
||||
use netpod::HasBackend;
|
||||
use netpod::ProxyConfig;
|
||||
use netpod::APP_CBOR;
|
||||
use netpod::APP_CBOR_FRAMED;
|
||||
use netpod::APP_JSON_FRAMED;
|
||||
use query::api4::events::PlainEventsQuery;
|
||||
|
||||
pub struct EventsHandler {}
|
||||
@@ -44,14 +45,10 @@ impl EventsHandler {
|
||||
if req.method() != Method::GET {
|
||||
Ok(response(StatusCode::METHOD_NOT_ALLOWED).body(body_empty())?)
|
||||
} else {
|
||||
if accepts_cbor_frames(req.headers()) {
|
||||
// self.handle_cbor(req, ctx, proxy_config).await
|
||||
// Ok(crate::proxy::proxy_backend_query::<PlainEventsQuery>(req, ctx, proxy_config).await?)
|
||||
warn!("TODO enabe cbor endpoint");
|
||||
Ok(response_err_msg(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
format!("cbor endpoint currently disabled"),
|
||||
)?)
|
||||
if accepts_cbor_framed(req.headers()) {
|
||||
self.handle_framed(req, APP_CBOR_FRAMED, ctx, proxy_config).await
|
||||
} else if accepts_json_framed(req.headers()) {
|
||||
self.handle_framed(req, APP_JSON_FRAMED, ctx, proxy_config).await
|
||||
} else if accepts_json_or_all(req.headers()) {
|
||||
Ok(crate::proxy::proxy_backend_query::<PlainEventsQuery>(req, ctx, proxy_config).await?)
|
||||
} else {
|
||||
@@ -60,26 +57,33 @@ impl EventsHandler {
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_cbor(&self, req: Requ, ctx: &ReqCtx, proxy_config: &ProxyConfig) -> Result<StreamResponse, Error> {
|
||||
async fn handle_framed(
|
||||
&self,
|
||||
req: Requ,
|
||||
accept: &str,
|
||||
ctx: &ReqCtx,
|
||||
proxy_config: &ProxyConfig,
|
||||
) -> Result<StreamResponse, Error> {
|
||||
let (head, _body) = req.into_parts();
|
||||
let url = req_uri_to_url(&head.uri)?;
|
||||
let pairs = get_url_query_pairs(&url);
|
||||
let evq = PlainEventsQuery::from_pairs(&pairs)?;
|
||||
info!("{evq:?}");
|
||||
// Ok(response(StatusCode::INTERNAL_SERVER_ERROR).body(body_empty())?)
|
||||
|
||||
// get_random_query_host_for_backend
|
||||
debug!("{evq:?}");
|
||||
let query_host = get_query_host_for_backend(evq.backend(), proxy_config)?;
|
||||
|
||||
// TODO this ignores the fragment
|
||||
let url_str = format!("{}{}", query_host, head.uri.path_and_query().unwrap());
|
||||
info!("try to contact {url_str}");
|
||||
|
||||
let url_str = format!(
|
||||
"{}{}",
|
||||
query_host,
|
||||
head.uri
|
||||
.path_and_query()
|
||||
.ok_or_else(|| Error::with_msg_no_trace("uri contains no path"))?
|
||||
);
|
||||
debug!("try to contact {url_str}");
|
||||
let uri: Uri = url_str.parse()?;
|
||||
let host = uri.host().ok_or_else(|| Error::with_msg_no_trace("no host in url"))?;
|
||||
let req = Request::builder()
|
||||
.method(Method::GET)
|
||||
.header(header::HOST, uri.host().unwrap())
|
||||
.header(header::ACCEPT, APP_CBOR)
|
||||
.header(header::HOST, host)
|
||||
.header(header::ACCEPT, accept)
|
||||
.header(ctx.header_name(), ctx.header_value())
|
||||
.uri(&uri)
|
||||
.body(body_empty())?;
|
||||
@@ -87,10 +91,10 @@ impl EventsHandler {
|
||||
let res = client.send_request(req).await?;
|
||||
let (head, body) = res.into_parts();
|
||||
if head.status != StatusCode::OK {
|
||||
error!("backend returned error: {head:?}");
|
||||
warn!("backend returned error: {head:?}");
|
||||
Ok(response(StatusCode::INTERNAL_SERVER_ERROR).body(body_empty())?)
|
||||
} else {
|
||||
info!("backend returned OK");
|
||||
debug!("backend returned OK");
|
||||
Ok(response(StatusCode::OK).body(body_stream(StreamIncoming::new(body)))?)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user