Skip to content

Commit

Permalink
Use helper functions for error codes in bridge
Browse files Browse the repository at this point in the history
  • Loading branch information
CBenoit committed Jul 28, 2021
1 parent abe9b1b commit 79d6090
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 41 deletions.
76 changes: 36 additions & 40 deletions devolutions-gateway/src/http/controllers/http_bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl HttpBridgeController {
let date = jwt::JwtDate::new_with_leeway(i64::try_from(numeric_date).unwrap(), 60);
let validator = jwt::JwtValidator::strict(&date);

let jws = jwt::JwtSig::decode(token_str, key, &validator).map_err(|e| (StatusCode::FORBIDDEN, e))?;
let jws = jwt::JwtSig::decode(token_str, key, &validator).map_err(HttpErrorStatus::forbidden)?;

Ok(jws.claims)
}
Expand All @@ -59,56 +59,52 @@ impl HttpBridgeController {
// FIXME: when updating reqwest 0.10 → 0.11 and hyper 0.13 → 0.14:
// Use https://docs.rs/reqwest/0.11.4/reqwest/struct.Body.html#impl-From%3CBody%3E
// to get a streaming reqwest Request instead of loading the whole body in memory.
let req: saphir::request::Request<saphir::body::Bytes> = req
.load_body()
.await
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e))?;
let req = req.load_body().await.map_err(HttpErrorStatus::internal)?;
let req: saphir::request::Request<reqwest::Body> = req.map(reqwest::Body::from);
let mut req: http::Request<reqwest::Body> = http::Request::from(req);

// === Filter and validate request to forward === //

let headers = req.headers_mut();

// Gateway Bridge Claims
let token_hdr = headers
.remove(GATEWAY_BRIDGE_TOKEN_HDR_NAME)
.ok_or((StatusCode::BAD_REQUEST, "Gateway-Bridge-Token header is missing"))?;
let token_str = token_hdr.to_str().map_err(|e| (StatusCode::BAD_REQUEST, e))?;
let claims = self.h_decode_claims(token_str)?;

// Update request destination
let uri = http::Uri::try_from(claims.target.as_str()).map_err(|e| (StatusCode::BAD_REQUEST, e))?;
*req.uri_mut() = uri;

// Forward
slog_scope::debug!("Forward HTTP request to {}", req.uri());
let req = reqwest::Request::try_from(req).map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e))?;
let mut rsp = self
.client
.execute(req)
.await
.map_err(|e| (StatusCode::BAD_GATEWAY, e))?;
let mut rsp = {
// Gateway Bridge Claims
let headers = req.headers_mut();
let token_hdr = headers
.remove(GATEWAY_BRIDGE_TOKEN_HDR_NAME)
.ok_or((StatusCode::BAD_REQUEST, "Gateway-Bridge-Token header is missing"))?;
let token_str = token_hdr.to_str().map_err(HttpErrorStatus::bad_request)?;
let claims = self.h_decode_claims(token_str)?;

// Update request destination
let uri = http::Uri::try_from(claims.target.as_str()).map_err(HttpErrorStatus::bad_request)?;
*req.uri_mut() = uri;

// Forward
slog_scope::debug!("Forward HTTP request to {}", req.uri());
let req = reqwest::Request::try_from(req).map_err(HttpErrorStatus::internal)?;
self.client.execute(req).await.map_err(HttpErrorStatus::bad_gateway)?
};

// === Create HTTP response using target response === //

let mut rsp_builder = Builder::new();

// Status code
rsp_builder = rsp_builder.status(rsp.status());

// Headers
let headers = rsp_builder.headers_mut().unwrap();
rsp.headers_mut().drain().for_each(|(name, value)| {
if let Some(name) = name {
headers.insert(name, value);
{
// Status code
rsp_builder = rsp_builder.status(rsp.status());

// Headers
let headers = rsp_builder.headers_mut().unwrap();
rsp.headers_mut().drain().for_each(|(name, value)| {
if let Some(name) = name {
headers.insert(name, value);
}
});

// Body
match rsp.bytes().await {
Ok(body) => rsp_builder = rsp_builder.body(body),
Err(e) => slog_scope::warn!("Couldn’t get bytes from response body: {}", e),
}
});

// Body
match rsp.bytes().await {
Ok(body) => rsp_builder = rsp_builder.body(body),
Err(e) => slog_scope::warn!("Couldn’t get bytes from response body: {}", e),
}

Ok(rsp_builder)
Expand Down
22 changes: 21 additions & 1 deletion devolutions-gateway/src/http/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,31 @@ impl HttpErrorStatus {
source: Box::new(source),
}
}

#[track_caller]
fn forbidden<T: Display + Send + 'static>(source: T) -> Self {
Self::new(StatusCode::FORBIDDEN, source)
}

#[track_caller]
fn internal<T: Display + Send + 'static>(source: T) -> Self {
Self::new(StatusCode::INTERNAL_SERVER_ERROR, source)
}

#[track_caller]
fn bad_request<T: Display + Send + 'static>(source: T) -> Self {
Self::new(StatusCode::BAD_REQUEST, source)
}

#[track_caller]
fn bad_gateway<T: Display + Send + 'static>(source: T) -> Self {
Self::new(StatusCode::BAD_GATEWAY, source)
}
}

impl Responder for HttpErrorStatus {
fn respond_with_builder(self, builder: Builder, _: &HttpContext) -> Builder {
slog_scope::error!("status {} at {} [source: {}]", self.code, self.loc, self.source);
slog_scope::error!("{} at {} [{}]", self.code, self.loc, self.source);
builder.status(self.code)
}
}

0 comments on commit 79d6090

Please sign in to comment.