httpd: Add `/raw` route

Signed-off-by: xphoniex <dj.2dixx@gmail.com>
This commit is contained in:
xphoniex 2023-02-23 06:16:37 +00:00
parent 2606372a14
commit 34b15f9f16
No known key found for this signature in database
GPG Key ID: 9FACFECE1E3B3994
9 changed files with 78 additions and 7 deletions

View File

@ -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;

View File

@ -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()

View File

@ -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";

View File

@ -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()

View File

@ -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 {

View File

@ -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>| {

59
radicle-httpd/src/raw.rs Normal file
View File

@ -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");
}
}

View File

@ -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()
}
}