use http::StatusCode;
use rskit_errors::{AppError, ErrorCode};
pub type HttpRequest<B = Vec<u8>> = http::Request<B>;
pub type HttpResponse<B = Vec<u8>> = http::Response<B>;
pub type HttpHeaders = http::HeaderMap;
pub type HttpStatusCode = http::StatusCode;
#[must_use]
pub fn status_to_error_code(status: StatusCode) -> ErrorCode {
match status.as_u16() {
400 => ErrorCode::InvalidInput,
401 => ErrorCode::Unauthorized,
403 => ErrorCode::Forbidden,
404 => ErrorCode::NotFound,
409 => ErrorCode::Conflict,
429 => ErrorCode::RateLimited,
408 => ErrorCode::Cancelled,
500 => ErrorCode::Internal,
502 => ErrorCode::ExternalService,
503 => ErrorCode::ServiceUnavailable,
504 => ErrorCode::Timeout,
_ if status.is_client_error() || status.is_server_error() => ErrorCode::ExternalService,
_ => ErrorCode::Internal,
}
}
#[must_use]
pub fn is_success_status(status: StatusCode) -> bool {
status.is_success()
}
#[must_use]
pub fn app_error_status(error: &AppError) -> StatusCode {
error.http_status()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn maps_http_status_to_error_code() {
assert_eq!(
status_to_error_code(StatusCode::BAD_REQUEST),
ErrorCode::InvalidInput
);
assert_eq!(
status_to_error_code(StatusCode::NOT_FOUND),
ErrorCode::NotFound
);
assert_eq!(
status_to_error_code(StatusCode::TOO_MANY_REQUESTS),
ErrorCode::RateLimited
);
assert_eq!(
status_to_error_code(StatusCode::BAD_GATEWAY),
ErrorCode::ExternalService
);
assert_eq!(
status_to_error_code(StatusCode::SERVICE_UNAVAILABLE),
ErrorCode::ServiceUnavailable
);
assert_eq!(
status_to_error_code(StatusCode::GATEWAY_TIMEOUT),
ErrorCode::Timeout
);
assert_eq!(
status_to_error_code(StatusCode::INTERNAL_SERVER_ERROR),
ErrorCode::Internal
);
}
#[test]
fn canonical_server_statuses_round_trip_through_error_code() {
for code in [
ErrorCode::ServiceUnavailable,
ErrorCode::Timeout,
ErrorCode::ExternalService,
ErrorCode::Internal,
] {
assert_eq!(status_to_error_code(code.http_status()), code);
}
}
#[test]
fn cancelled_status_round_trips_through_error_code() {
let status = ErrorCode::Cancelled.http_status();
assert_eq!(status_to_error_code(status), ErrorCode::Cancelled);
}
#[test]
fn exposes_protocol_types_without_framework_coupling() {
let request: HttpRequest = http::Request::builder()
.uri("/healthz")
.body(Vec::new())
.unwrap();
let response: HttpResponse = http::Response::builder()
.status(StatusCode::OK)
.body(Vec::new())
.unwrap();
assert_eq!(request.uri(), "/healthz");
assert!(is_success_status(response.status()));
}
}