Something went wrong. Try again.
Chris’s PDS implementation
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126mod support;
use axum::{ body::{Body, to_bytes}, http::{Request, StatusCode, header},};use serde_json::Value;use support::TestApp;
#[tokio::test]async fn server_errors_do_not_disclose_internal_diagnostics() { use axum::response::IntoResponse as _; use cpds::error::Error;
for error in [ Error::Internal("private repository details".to_owned()), Error::Configuration("private configuration details".to_owned()), Error::Io(std::io::Error::other("private filesystem path")), Error::Database(rusqlite::Error::InvalidParameterName( "private SQL".to_owned(), )), Error::Upstream("private upstream URL".to_owned()), ] { let response = error.into_response(); assert!(response.status().is_server_error()); let body = to_bytes(response.into_body(), usize::MAX).await.unwrap(); let body: Value = serde_json::from_slice(&body).unwrap(); assert!(!body["message"].as_str().unwrap().contains("private")); }}
#[tokio::test]async fn unknown_xrpc_routes_and_wrong_methods_use_json_errors() { let app = TestApp::new();
let missing = app .send( Request::get("/xrpc/com.example.unknown") .body(Body::empty()) .unwrap(), ) .await; assert_error(missing, StatusCode::NOT_FOUND, "MethodNotFound").await;
let wrong_method = app .send( Request::put("/xrpc/com.atproto.server.describeServer") .body(Body::empty()) .unwrap(), ) .await; assert_eq!(wrong_method.headers()[header::ALLOW], "GET,HEAD"); assert_error( wrong_method, StatusCode::METHOD_NOT_ALLOWED, "MethodNotAllowed", ) .await;
let missing_page = app .send(Request::get("/missing").body(Body::empty()).unwrap()) .await; assert_error(missing_page, StatusCode::NOT_FOUND, "NotFound").await;}
#[tokio::test]async fn extractor_rejections_use_the_xrpc_error_contract() { let app = TestApp::new();
let malformed_json = app .send( Request::post("/xrpc/com.atproto.repo.createRecord") .header(header::CONTENT_TYPE, "application/json") .body(Body::from("{")) .unwrap(), ) .await; assert_error(malformed_json, StatusCode::BAD_REQUEST, "InvalidRequest").await;
let malformed_query = app .send( Request::get("/xrpc/com.atproto.repo.getRecord?repo=did%3Aweb%3Aalice.test") .body(Body::empty()) .unwrap(), ) .await; assert_error(malformed_query, StatusCode::BAD_REQUEST, "InvalidRequest").await;}
#[tokio::test]async fn representative_successes_keep_their_declared_content_types() { let app = TestApp::new();
let json = app .send( Request::get("/xrpc/com.atproto.server.describeServer") .body(Body::empty()) .unwrap(), ) .await; assert_eq!(json.status(), StatusCode::OK); assert_eq!(json.headers()[header::CONTENT_TYPE], "application/json");
let html = app .send(Request::get("/").body(Body::empty()).unwrap()) .await; assert_eq!(html.status(), StatusCode::OK); assert_eq!( html.headers()[header::CONTENT_TYPE], "text/html; charset=utf-8" );}
async fn assert_error(response: axum::response::Response, status: StatusCode, name: &str) { assert_eq!(response.status(), status); assert_eq!(response.headers()[header::CONTENT_TYPE], "application/json"); let body = to_bytes(response.into_body(), usize::MAX).await.unwrap(); let body: Value = serde_json::from_slice(&body).unwrap(); assert_eq!(body["error"], name); assert!( body["message"] .as_str() .is_some_and(|value| !value.is_empty()) );}