Skip to content

Commit

Permalink
feat: First custom Stele errors
Browse files Browse the repository at this point in the history
I needed this to manually test the tracing. So I tidied it up and made
it the basis for more formally handling Stele-specific errors.
  • Loading branch information
tombh committed Dec 21, 2022
1 parent f538543 commit a9313f7
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 7 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ serde = "1.0"
tracing = "0.1.37"
tracing-subscriber = "0.3.16"
tracing-actix-web = "0.6.2"
derive_more = "0.99.17"

[dev-dependencies]
criterion = "0.3"
Expand Down
5 changes: 3 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,9 @@
// would benefit from explicit inlining.
clippy::missing_inline_in_public_items,
// I think marking `#[non_exhaustive]` is more for structs that are imported into other crates
clippy::exhaustive_structs
// I think marking `#[non_exhaustive]` is more for structs/enums that are imported into other crates
clippy::exhaustive_structs,
clippy::exhaustive_enums
)]

pub mod server;
Expand Down
1 change: 1 addition & 0 deletions src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
//!
//! Currently contains only a git microserver.
pub mod errors;
pub mod git;
pub mod tracing;
30 changes: 30 additions & 0 deletions src/server/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#![allow(
// derive_more doesn't respect these lints
clippy::pattern_type_mismatch,
clippy::use_self
)]

//! Stele-specific errors
use actix_web::{error, http::StatusCode, HttpResponse};
use derive_more::{Display, Error};

/// Collection of possible Stele errors
#[derive(Debug, Display, Error)]
pub enum SteleError {
/// Errors generated by the Git server
#[display(fmt = "A Git server occurred")]
GitError,
}

impl error::ResponseError for SteleError {
fn error_response(&self) -> HttpResponse {
HttpResponse::build(self.status_code()).body(self.to_string())
}

fn status_code(&self) -> StatusCode {
match *self {
Self::GitError => StatusCode::INTERNAL_SERVER_ERROR,
}
}
}
25 changes: 22 additions & 3 deletions src/server/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@
clippy::unused_async
)]

use crate::server::tracing::SteleRootSpanBuilder;
use crate::utils::git::{Repo, GIT_REQUEST_NOT_FOUND};
use crate::utils::http::get_contenttype;
use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};
use git2;
use lazy_static::lazy_static;
use regex::Regex;
use std::path::{Path, PathBuf};
use tracing_actix_web::TracingLogger;

use super::errors::SteleError;
use crate::server::tracing::SteleRootSpanBuilder;
use crate::utils::git::{Repo, GIT_REQUEST_NOT_FOUND};
use crate::utils::http::get_contenttype;

/// Global, read-only state passed into the actix app
struct AppState {
/// path to the Stele library
Expand All @@ -30,6 +32,21 @@ fn clean_path(path: &str) -> String {
RE.replace_all(path, "").to_string()
}

/// Root index path
#[get("/")]
async fn index() -> &'static str {
"Welcome to Stele"
}

/// Just for development purposes at the moment
#[get("{path}")]
async fn misc(path: web::Path<String>) -> actix_web::Result<&'static str, SteleError> {
match path.as_str() {
"error" => Err(SteleError::GitError),
_ => Ok("\u{2728}"),
}
}

/// Return the content in the stele library in the `{namespace}/{name}`
/// repo at the `commitish` commit at the `remainder` path.
/// Return 404 if any are not found or there are any errors.
Expand Down Expand Up @@ -99,6 +116,8 @@ pub async fn serve_git(
HttpServer::new(move || {
App::new()
.wrap(TracingLogger::<SteleRootSpanBuilder>::new())
.service(index)
.service(misc)
.service(get_blob)
.app_data(web::Data::new(AppState {
library_path: library_path.clone(),
Expand Down
4 changes: 2 additions & 2 deletions src/server/tracing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ struct RequestStart(Instant);

impl RootSpanBuilder for SteleRootSpanBuilder {
fn on_request_start(request: &ServiceRequest) -> tracing::Span {
// The `{}` block to tells the compiler to return ownership of `request`.
// The `{}` block tells the compiler to return ownership of `request`.
// NOTE:
// Because the `request` variable is included in the `*span!` macro, we're not likely to
// get linting feedback that the macro also mutably borrows `request`. Or at least I
Expand Down Expand Up @@ -53,7 +53,7 @@ impl RootSpanBuilder for SteleRootSpanBuilder {
// I couldn't find a way of triggering the case where `outcome` is
// `Result::Err(actix_web::Error)`. It doesn't seem to be when a route method returns an
// error, as I assume that's considered a handled error. So maybe `outcome` is only ever
// and error for an Actix-internal error? Either way, the root span and timings all work
// an error for an Actix-internal error? Either way, the root span and timings all work
// normally for known and handled request errors.
outcome.as_ref().map_or((), |response| {
if let Some(req_start) = response.request().extensions().get::<RequestStart>() {
Expand Down

0 comments on commit a9313f7

Please sign in to comment.