Verified Commit a0239fd6 authored by Ole Martin Ruud's avatar Ole Martin Ruud
Browse files

chore: update locked dependencies

parent 12be6449
This diff is collapsed.
......@@ -24,18 +24,19 @@ exactly = 1
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0.34"
envy = "0.4.1"
futures = "0.3.8"
hyper = "0.13.9"
serde = { version = "1.0.117", features = ["derive"] }
tera = "1.5.0"
tokio = { version = "0.2.20", features = ["macros", "signal"] }
tower-service = "0.3.0"
anyhow = "1.0.38"
envy = "0.4.2"
futures = "0.3.12"
serde = { version = "1.0.119", features = ["derive"] }
tera = "1.6.1"
tokio = { version = "1.0.2", features = ["macros", "signal", "rt-multi-thread"] }
tracing = "0.1.22"
tracing-futures = { version = "0.2.4", default-features = false, features = ["std-future", "std"] }
tracing-subscriber = { version = "0.2.15", default-features = false, features = ["env-filter", "tracing-log", "fmt", "ansi", "smallvec"] }
warp = { version = "0.2.5", default-features = false }
# warp = { version = "0.2.5", default-features = false }
# TODO swap back when version of warp with tokio version 1 is released
# https://github.com/seanmonstar/warp/pull/777/files
warp = { git = "https://github.com/seanmonstar/warp.git", rev = "ffefea08050ffe8022d3391f4bd5e5ab4e95d7c9", default-features = false }
lazy_static = "1.4.0"
reqwest = { version = "0.10.9", default-features = false, features = ["rustls-tls", "json"] }
serde_json = "1.0.59"
reqwest = { version = "0.11.0", default-features = false, features = ["rustls-tls", "json"] }
serde_json = "1.0.61"
......@@ -71,4 +71,5 @@ pub fn app(
.or(warp::path("favicon.ico").and(warp::fs::file("static/favicon.ico")))
.or(warp::path("static").and(warp::fs::dir("static")))
.recover(crate::reject::handler)
.with(warp::filters::trace::request())
}
......@@ -14,7 +14,8 @@ pub struct Config {
impl Config {
/// The prefix of all env variables
///
/// E.g. `port` turns into `<prefix>PORT`
/// `port` turns into `<prefix>PORT`, so e.g. with `ENV_PREFIX = "HOMEPAGE_"`, `port` turns
/// into `HOMEPAGE_PORT`.
const ENV_PREFIX: &'static str = "HOMEPAGE_";
pub fn try_new() -> Result<Self> {
......
use anyhow::{anyhow, Context, Result};
use hyper::{server::conn::AddrStream, Body, Request};
use anyhow::{Context, Result};
use reqwest::Client;
use std::convert::Infallible;
use std::net::SocketAddr;
use std::sync::Arc;
use tower_service::Service;
use tracing_futures::Instrument;
mod app;
mod config;
......@@ -30,6 +25,8 @@ async fn main() {
}
}
// We have a separate function for running to enable us to use ? for error handling.
async fn run() -> Result<()> {
// Parse config from environment variables
let config = config::Config::try_new().context("unable to get configuration")?;
......@@ -45,52 +42,14 @@ async fn run() -> Result<()> {
let http_client = Arc::new(Client::new());
// Make a hyper service wrapper with tracing enabled
let warp_svc = warp::service(app::app(&config, http_client));
let make_svc = hyper::service::make_service_fn(move |socket: &AddrStream| {
let remote_addr = socket.remote_addr();
let warp_svc = warp_svc.clone();
async move {
let svc = hyper::service::service_fn(move |req: Request<Body>| {
let mut warp_svc = warp_svc.clone();
let span = tracing::info_span!("request",
remote_addr = %remote_addr,
method = %req.method(),
uri = %req.uri(),
version = ?req.version()
);
async move {
tracing::info!("processing request");
let resp: Result<_, Infallible> = warp_svc.call(req).await;
let resp = resp.unwrap(); // Will never fail because `Infallible` above
let status = resp.status().as_u16();
tracing::info!(status = ?status, "processed request");
Ok::<_, Infallible>(resp)
}
.instrument(span)
});
Ok::<_, Infallible>(svc)
}
});
// Configure the address and port to host the server on
let addr: SocketAddr = SocketAddr::from(([0, 0, 0, 0], config.service_port));
tracing::info!(addr = %addr, "starting server");
// Run the hyper service
hyper::Server::try_bind(&addr)
.context(anyhow!("unable to bind to addr: {}", addr))?
.serve(make_svc)
.with_graceful_shutdown(async {
// Run the app
let (addr, server) = warp::serve(app::app(&config, http_client))
.try_bind_with_graceful_shutdown(([0, 0, 0, 0], config.service_port), async {
let _ = tokio::signal::ctrl_c().await;
})
.await
.context("server crashed")?;
.context("unable to start server")?;
tracing::info!(addr = %addr, "started server");
Ok(())
Ok(server.await)
}
......@@ -13,21 +13,22 @@ pub async fn handler(err: Rejection) -> Result<impl Reply, Infallible> {
let code;
let message;
tracing::info!(rejection = ?err, "handling rejection");
if err.is_not_found() {
code = StatusCode::NOT_FOUND;
message = "Not found";
} else if err.find::<InternalServerError>().is_some() {
tracing::warn!(error = ?err, "requested not found resource");
} else if let Some(err) = err.find::<InternalServerError>() {
code = StatusCode::INTERNAL_SERVER_ERROR;
message = "Internal server error";
} else if err.find::<warp::reject::MethodNotAllowed>().is_some() {
tracing::error!(error = ?err, "internal server error");
} else if let Some(err) = err.find::<warp::reject::MethodNotAllowed>() {
code = StatusCode::METHOD_NOT_ALLOWED;
message = "Method not allowed";
tracing::warn!(error = ?err, "method used not allowed");
} else {
tracing::error!(rejection = ?err, "unhandled rejection");
code = StatusCode::INTERNAL_SERVER_ERROR;
message = "Internal server error";
tracing::error!(error = ?err, "unhandled internal error");
}
Ok(warp::reply::with_status(message, code))
......
......@@ -2,6 +2,7 @@ use crate::reject::InternalServerError;
use std::borrow::Cow;
use tera::Tera;
use warp::{Rejection, Reply};
use tracing::Instrument;
lazy_static::lazy_static!(
static ref TERA: Tera = {
......@@ -21,17 +22,19 @@ pub struct WithTemplate {
pub async fn handler(
WithTemplate { name, context }: WithTemplate,
) -> Result<impl Reply, Rejection> {
let template_span = tracing::info_span!("template", name = %name);
// `render` might take some time to execute, so we launch it in a threadpool
tokio::task::spawn_blocking(move || {
let span = tracing::info_span!("template", name = %name);
let _enter = span.enter();
tracing::trace!("rendering");
TERA.render(&*name, &context).map_err(|e| {
tracing::trace!("rendering...");
let res = TERA.render(&*name, &context).map_err(|e| {
tracing::error!("unable to render template: {}", e);
warp::reject::custom(InternalServerError)
})
});
tracing::trace!("done");
res
})
.instrument(template_span)
.await
.map_err(|e| {
tracing::error!("unable to spawn blocking closure: {}", e);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment