mirror of
https://github.com/facebook/sapling.git
synced 2024-10-06 23:07:18 +03:00
edenapi_server: factor out handler boilerplate
Summary: Factor out logic that will be common to many handlers into new functions in the `util` module. Reviewed By: krallin Differential Revision: D21489469 fbshipit-source-id: 9aff4e5182748ab0a0bedd6038852692b8e721a7
This commit is contained in:
parent
3ac2032c07
commit
48a0b33093
@ -10,12 +10,9 @@ use bytes::Bytes;
|
||||
use futures::{stream::FuturesUnordered, TryStreamExt};
|
||||
use gotham::state::{FromState, State};
|
||||
use gotham_derive::{StateData, StaticResponseExtender};
|
||||
use http::HeaderMap;
|
||||
use hyper::Body;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
use gotham_ext::{body_ext::BodyExt, error::HttpError, response::BytesBody};
|
||||
use gotham_ext::{error::HttpError, response::BytesBody};
|
||||
use mercurial_types::HgNodeHash;
|
||||
use mononoke_api::hg::{HgDataContext, HgDataId, HgRepoContext};
|
||||
use types::{
|
||||
@ -26,7 +23,7 @@ use types::{
|
||||
use crate::context::ServerContext;
|
||||
use crate::middleware::RequestContext;
|
||||
|
||||
use super::util::cbor_mime;
|
||||
use super::util::{cbor_mime, get_repo, get_request_body};
|
||||
|
||||
#[derive(Debug, Deserialize, StateData, StaticResponseExtender)]
|
||||
pub struct DataParams {
|
||||
@ -38,25 +35,11 @@ pub async fn data<ID: HgDataId>(state: &mut State) -> Result<BytesBody<Bytes>, H
|
||||
let sctx = ServerContext::borrow_from(state);
|
||||
let params = DataParams::borrow_from(state);
|
||||
|
||||
let repo = sctx
|
||||
.mononoke_api()
|
||||
.repo(rctx.core_context().clone(), ¶ms.repo)
|
||||
.await
|
||||
.map_err(HttpError::e403)?
|
||||
.ok_or_else(|| HttpError::e404(anyhow!("repo does not exist: {:?}", ¶ms.repo)))?;
|
||||
let repo = get_repo(&sctx, &rctx, ¶ms.repo).await?;
|
||||
let body = get_request_body(state).await?;
|
||||
|
||||
let hg_repo = repo.hg();
|
||||
|
||||
let body = Body::take_from(state);
|
||||
let headers = HeaderMap::try_borrow_from(state);
|
||||
let payload: Bytes = body
|
||||
.try_concat_body_opt(headers)
|
||||
.map_err(HttpError::e400)?
|
||||
.await
|
||||
.map_err(HttpError::e400)?;
|
||||
|
||||
let request = serde_cbor::from_slice(&payload).map_err(HttpError::e400)?;
|
||||
let response = get_all_entries::<ID>(&hg_repo, request).await?;
|
||||
let request = serde_cbor::from_slice(&body).map_err(HttpError::e400)?;
|
||||
let response = get_all_entries::<ID>(&repo, request).await?;
|
||||
let bytes: Bytes = serde_cbor::to_vec(&response)
|
||||
.map_err(HttpError::e500)?
|
||||
.into();
|
||||
@ -66,12 +49,12 @@ pub async fn data<ID: HgDataId>(state: &mut State) -> Result<BytesBody<Bytes>, H
|
||||
|
||||
/// Fetch data for all of the requested keys concurrently.
|
||||
async fn get_all_entries<ID: HgDataId>(
|
||||
hg_repo: &HgRepoContext,
|
||||
repo: &HgRepoContext,
|
||||
request: DataRequest,
|
||||
) -> Result<DataResponse, HttpError> {
|
||||
let fetches = FuturesUnordered::new();
|
||||
for key in request.keys {
|
||||
fetches.push(get_data_entry::<ID>(hg_repo.clone(), key));
|
||||
fetches.push(get_data_entry::<ID>(repo.clone(), key));
|
||||
}
|
||||
let entries = fetches.try_collect::<Vec<_>>().await?;
|
||||
|
||||
@ -82,13 +65,13 @@ async fn get_all_entries<ID: HgDataId>(
|
||||
/// Note that this function consumes the repo context in order
|
||||
/// to construct a file/tree context for the requested blob.
|
||||
async fn get_data_entry<ID: HgDataId>(
|
||||
hg_repo: HgRepoContext,
|
||||
repo: HgRepoContext,
|
||||
key: Key,
|
||||
) -> Result<DataEntry, HttpError> {
|
||||
let id = ID::from_node_hash(HgNodeHash::from(key.hgid));
|
||||
|
||||
let ctx = id
|
||||
.context(hg_repo)
|
||||
.context(repo)
|
||||
.await
|
||||
.map_err(HttpError::e500)?
|
||||
.ok_or_else(|| HttpError::e404(anyhow!("key not found: {:?}", &key)))?;
|
||||
|
@ -5,11 +5,45 @@
|
||||
* GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
use anyhow::anyhow;
|
||||
use bytes::Bytes;
|
||||
use gotham::state::{FromState, State};
|
||||
use http::HeaderMap;
|
||||
use hyper::Body;
|
||||
use mime::Mime;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use gotham_ext::{body_ext::BodyExt, error::HttpError};
|
||||
use mononoke_api::hg::HgRepoContext;
|
||||
|
||||
use crate::context::ServerContext;
|
||||
use crate::middleware::RequestContext;
|
||||
|
||||
static CBOR_MIME: Lazy<Mime> = Lazy::new(|| "application/cbor".parse().unwrap());
|
||||
|
||||
pub fn cbor_mime() -> Mime {
|
||||
CBOR_MIME.clone()
|
||||
}
|
||||
|
||||
pub async fn get_repo(
|
||||
sctx: &ServerContext,
|
||||
rctx: &RequestContext,
|
||||
name: impl AsRef<str>,
|
||||
) -> Result<HgRepoContext, HttpError> {
|
||||
let name = name.as_ref();
|
||||
sctx.mononoke_api()
|
||||
.repo(rctx.core_context().clone(), name)
|
||||
.await
|
||||
.map_err(HttpError::e403)?
|
||||
.map(|repo| repo.hg())
|
||||
.ok_or_else(|| HttpError::e404(anyhow!("repo does not exist: {:?}", name)))
|
||||
}
|
||||
|
||||
pub async fn get_request_body(state: &mut State) -> Result<Bytes, HttpError> {
|
||||
let body = Body::take_from(state);
|
||||
let headers = HeaderMap::try_borrow_from(state);
|
||||
body.try_concat_body_opt(headers)
|
||||
.map_err(HttpError::e400)?
|
||||
.await
|
||||
.map_err(HttpError::e400)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user