httpd: Add `/raw` route
Signed-off-by: xphoniex <dj.2dixx@gmail.com>
This commit is contained in:
parent
2606372a14
commit
34b15f9f16
|
|
@ -21,7 +21,6 @@ use radicle::identity::Id;
|
|||
use radicle::storage::{ReadRepository, ReadStorage};
|
||||
use radicle::Profile;
|
||||
|
||||
mod axum_extra;
|
||||
mod error;
|
||||
mod json;
|
||||
mod v1;
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ use radicle::cob::patch::Patches;
|
|||
use radicle::identity::Did;
|
||||
use radicle::storage::{ReadRepository, ReadStorage};
|
||||
|
||||
use crate::api::axum_extra::{Path, Query};
|
||||
use crate::api::error::Error;
|
||||
use crate::api::project::Info;
|
||||
use crate::api::Context;
|
||||
use crate::api::PaginationQuery;
|
||||
use crate::axum_extra::{Path, Query};
|
||||
|
||||
pub fn router(ctx: Context) -> Router {
|
||||
Router::new()
|
||||
|
|
|
|||
|
|
@ -17,13 +17,14 @@ use radicle::cob::patch::Patches;
|
|||
use radicle::cob::{thread, ActorId, Tag};
|
||||
use radicle::identity::Id;
|
||||
use radicle::node::NodeId;
|
||||
use radicle::storage::{git::paths, ReadRepository, ReadStorage};
|
||||
use radicle::storage::git::paths;
|
||||
use radicle::storage::{ReadRepository, ReadStorage};
|
||||
use radicle_surf::{Glob, Oid, Repository};
|
||||
|
||||
use crate::api::axum_extra::{Path, Query};
|
||||
use crate::api::error::Error;
|
||||
use crate::api::project::Info;
|
||||
use crate::api::{self, Context, PaginationQuery};
|
||||
use crate::axum_extra::{Path, Query};
|
||||
|
||||
const CACHE_1_HOUR: &str = "public, max-age=3600, must-revalidate";
|
||||
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ use serde::{Deserialize, Serialize};
|
|||
use time::OffsetDateTime;
|
||||
|
||||
use crate::api::auth::{self, AuthState, Session};
|
||||
use crate::api::axum_extra::Path;
|
||||
use crate::api::error::Error;
|
||||
use crate::api::json;
|
||||
use crate::api::Context;
|
||||
use crate::axum_extra::Path;
|
||||
|
||||
pub fn router(ctx: Context) -> Router {
|
||||
Router::new()
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@ pub enum Error {
|
|||
/// HeaderValue error.
|
||||
#[error(transparent)]
|
||||
InvalidHeaderValue(#[from] axum::http::header::InvalidHeaderValue),
|
||||
|
||||
/// Surf error.
|
||||
#[error(transparent)]
|
||||
Surf(#[from] radicle_surf::Error),
|
||||
}
|
||||
|
||||
impl Error {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,9 @@ use tower_http::trace::TraceLayer;
|
|||
use tracing::Span;
|
||||
|
||||
mod api;
|
||||
mod axum_extra;
|
||||
mod git;
|
||||
mod raw;
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
||||
|
|
@ -41,13 +43,15 @@ pub async fn run(options: Options) -> anyhow::Result<()> {
|
|||
|
||||
let ctx = api::Context::new(profile.clone());
|
||||
let api_router = api::router(ctx);
|
||||
let git_router = git::router(profile);
|
||||
let git_router = git::router(profile.clone());
|
||||
let raw_router = raw::router(profile);
|
||||
|
||||
tracing::info!("listening on http://{}", options.listen);
|
||||
|
||||
let app = Router::new()
|
||||
.merge(git_router)
|
||||
.nest("/api", api_router)
|
||||
.nest("/raw", raw_router)
|
||||
.layer(
|
||||
TraceLayer::new_for_http()
|
||||
.make_span_with(|request: &Request<Body>| {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use axum::extract::State;
|
||||
use axum::http::header;
|
||||
use axum::response::IntoResponse;
|
||||
use axum::routing::get;
|
||||
use axum::Router;
|
||||
use hyper::HeaderMap;
|
||||
|
||||
use radicle::prelude::Id;
|
||||
use radicle::profile::Profile;
|
||||
use radicle::storage::git::paths;
|
||||
use radicle_surf::{Oid, Repository};
|
||||
|
||||
use crate::axum_extra::Path;
|
||||
use crate::error::Error;
|
||||
|
||||
pub fn router(profile: Arc<Profile>) -> Router {
|
||||
Router::new()
|
||||
.route("/:project/:sha/*path", get(file_handler))
|
||||
.with_state(profile)
|
||||
}
|
||||
|
||||
async fn file_handler(
|
||||
Path((project, sha, path)): Path<(Id, Oid, String)>,
|
||||
State(profile): State<Arc<Profile>>,
|
||||
) -> impl IntoResponse {
|
||||
let storage = &profile.storage;
|
||||
let repo = Repository::open(paths::repository(storage, &project))?;
|
||||
let blob = repo.blob(sha, &path)?;
|
||||
|
||||
let mut response_headers = HeaderMap::new();
|
||||
response_headers.insert(header::CONTENT_TYPE, "text; charset=utf-8".parse().unwrap());
|
||||
|
||||
Ok::<_, Error>((response_headers, blob.content().to_owned()))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod routes {
|
||||
use axum::http::StatusCode;
|
||||
|
||||
use crate::test::{self, get, HEAD};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_file_handler() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let ctx = test::seed(tmp.path());
|
||||
let app = super::router(ctx.profile().to_owned());
|
||||
|
||||
let response = get(
|
||||
&app,
|
||||
format!("/rad:z4FucBZHZMCsxTyQE1dfE2YR59Qbp/{HEAD}/dir1/README"),
|
||||
)
|
||||
.await;
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
assert_eq!(response.body().await, "Hello World from dir1!\n");
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ use std::str::FromStr;
|
|||
use std::sync::Arc;
|
||||
use std::{env, fs};
|
||||
|
||||
use axum::body::Body;
|
||||
use axum::body::{Body, Bytes};
|
||||
use axum::http::{Method, Request};
|
||||
use axum::Router;
|
||||
use serde_json::Value;
|
||||
|
|
@ -235,4 +235,8 @@ impl Response {
|
|||
pub fn status(&self) -> axum::http::StatusCode {
|
||||
self.0.status()
|
||||
}
|
||||
|
||||
pub async fn body(self) -> Bytes {
|
||||
hyper::body::to_bytes(self.0.into_body()).await.unwrap()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue