Skip to main content

StatusCode

Struct StatusCode 

Source
pub struct StatusCode(/* private fields */);
Expand description

HTTP status code.

Implementations§

Source§

impl StatusCode

Source

pub const CONTINUE: StatusCode

100 Continue

Source

pub const SWITCHING_PROTOCOLS: StatusCode

101 Switching Protocols

Source

pub const OK: StatusCode

200 OK

Source

pub const CREATED: StatusCode

201 Created

Source

pub const ACCEPTED: StatusCode

202 Accepted

Source

pub const NO_CONTENT: StatusCode

204 No Content

Source

pub const PARTIAL_CONTENT: StatusCode

206 Partial Content

Source

pub const MOVED_PERMANENTLY: StatusCode

301 Moved Permanently

Source

pub const FOUND: StatusCode

302 Found

Source

pub const SEE_OTHER: StatusCode

303 See Other

Source

pub const NOT_MODIFIED: StatusCode

304 Not Modified

Source

pub const TEMPORARY_REDIRECT: StatusCode

307 Temporary Redirect

Source

pub const PERMANENT_REDIRECT: StatusCode

308 Permanent Redirect

Source

pub const BAD_REQUEST: StatusCode

400 Bad Request

Source

pub const UNAUTHORIZED: StatusCode

401 Unauthorized

Source

pub const FORBIDDEN: StatusCode

403 Forbidden

Source

pub const NOT_FOUND: StatusCode

404 Not Found

Source

pub const METHOD_NOT_ALLOWED: StatusCode

405 Method Not Allowed

Source

pub const NOT_ACCEPTABLE: StatusCode

406 Not Acceptable

Source

pub const PRECONDITION_FAILED: StatusCode

412 Precondition Failed

Source

pub const PAYLOAD_TOO_LARGE: StatusCode

413 Payload Too Large

Source

pub const UNSUPPORTED_MEDIA_TYPE: StatusCode

415 Unsupported Media Type

Source

pub const RANGE_NOT_SATISFIABLE: StatusCode

416 Range Not Satisfiable

Source

pub const UNPROCESSABLE_ENTITY: StatusCode

422 Unprocessable Entity

Source

pub const TOO_MANY_REQUESTS: StatusCode

429 Too Many Requests

Source

pub const CLIENT_CLOSED_REQUEST: StatusCode

499 Client Closed Request

Source

pub const INTERNAL_SERVER_ERROR: StatusCode

500 Internal Server Error

Source

pub const SERVICE_UNAVAILABLE: StatusCode

503 Service Unavailable

Source

pub const GATEWAY_TIMEOUT: StatusCode

504 Gateway Timeout

Source

pub const fn from_u16(code: u16) -> StatusCode

Create a status code from a u16.

Source

pub const fn as_u16(self) -> u16

Get the numeric value.

Examples found in repository?
examples/hello_world.rs (line 99)
61fn main() {
62    println!("fastapi_rust Hello World Example");
63    println!("================================\n");
64
65    // Build the application
66    //
67    // App::builder() creates a new application builder that lets you:
68    // - Add routes for different HTTP methods
69    // - Configure middleware
70    // - Set application state
71    // - Define exception handlers
72    let app = App::builder()
73        // Register a GET handler for the root path "/"
74        //
75        // This is equivalent to:
76        //   @app.get("/")
77        //   def hello():
78        //       return "Hello, World!"
79        // in Python FastAPI
80        .get("/", hello_handler)
81        // Build the final immutable App
82        .build();
83
84    println!("App created with {} route(s)\n", app.route_count());
85
86    // Create a test client to make requests to our app
87    //
88    // TestClient wraps any Handler (including App) and provides
89    // a convenient API for making HTTP requests in tests.
90    let client = TestClient::new(app);
91
92    // Make a GET request to "/"
93    println!("Making request: GET /");
94    let response = client.get("/").send();
95
96    // Check the response
97    println!(
98        "GET / -> {} {}",
99        response.status().as_u16(),
100        response.status().canonical_reason()
101    );
102    println!("Response: {}\n", response.text());
103
104    // Verify success
105    if !check_eq(response.status().as_u16(), 200, "GET / should return 200") {
106        return;
107    }
108    if !check_eq(response.text(), "Hello, World!", "GET / should return body") {
109        return;
110    }
111
112    // Try a path that doesn't exist - should get 404
113    println!("Making request: GET /not-found");
114    let response = client.get("/not-found").send();
115    println!(
116        "GET /not-found -> {} {}",
117        response.status().as_u16(),
118        response.status().canonical_reason()
119    );
120    if !check_eq(
121        response.status().as_u16(),
122        404,
123        "Unknown routes should return 404",
124    ) {
125        return;
126    }
127
128    println!("\nAll assertions passed!");
129}
More examples
Hide additional examples
examples/getting_started.rs (line 50)
34fn main() {
35    println!("Getting Started Guide - Code Validation\n");
36
37    // === Basic App Example ===
38    println!("1. Basic app with two routes:");
39    let app = App::builder()
40        .get("/", hello)
41        .get("/health", health)
42        .build();
43
44    println!("   Routes: {}", app.route_count());
45    let client = TestClient::new(app);
46
47    let response = client.get("/").send();
48    println!(
49        "   GET / -> {} ({})",
50        response.status().as_u16(),
51        response.text()
52    );
53    if !check_eq(response.status().as_u16(), 200, "GET / should return 200") {
54        return;
55    }
56    if !check_eq(response.text(), "Hello, World!", "GET / should return body") {
57        return;
58    }
59
60    let response = client.get("/health").send();
61    println!(
62        "   GET /health -> {} ({})",
63        response.status().as_u16(),
64        response.text()
65    );
66    if !check_eq(
67        response.status().as_u16(),
68        200,
69        "GET /health should return 200",
70    ) {
71        return;
72    }
73
74    // === App with Middleware ===
75    println!("\n2. App with middleware:");
76    let app = App::builder()
77        .middleware(RequestIdMiddleware::new())
78        .middleware(SecurityHeaders::new())
79        .get("/", hello)
80        .build();
81
82    let client = TestClient::new(app);
83    let response = client.get("/").send();
84    println!("   GET / -> {}", response.status().as_u16());
85    if !check_eq(
86        response.status().as_u16(),
87        200,
88        "GET / with middleware should return 200",
89    ) {
90        return;
91    }
92
93    // === App with Configuration ===
94    println!("\n3. App with configuration:");
95    let config = AppConfig::new()
96        .name("My API")
97        .version("1.0.0")
98        .debug(true)
99        .max_body_size(10 * 1024 * 1024)
100        .request_timeout_ms(30_000);
101
102    let app = App::builder().config(config).get("/", hello).build();
103
104    println!("   App name: {}", app.config().name);
105    println!("   Version: {}", app.config().version);
106    if !check_eq(
107        app.config().name.as_str(),
108        "My API",
109        "Config name should match",
110    ) {
111        return;
112    }
113    if !check_eq(
114        app.config().version.as_str(),
115        "1.0.0",
116        "Config version should match",
117    ) {
118        return;
119    }
120
121    // === 404 for unknown routes ===
122    println!("\n4. 404 for unknown routes:");
123    let app = App::builder().get("/", hello).build();
124
125    let client = TestClient::new(app);
126    let response = client.get("/nonexistent").send();
127    println!("   GET /nonexistent -> {}", response.status().as_u16());
128    if !check_eq(
129        response.status().as_u16(),
130        404,
131        "Unknown routes should return 404",
132    ) {
133        return;
134    }
135
136    println!("\nAll getting started examples validated successfully!");
137}
examples/crud_api.rs (line 304)
271fn main() {
272    // Initialize the global store
273    let mut guard = STORE
274        .lock()
275        .unwrap_or_else(std::sync::PoisonError::into_inner);
276    *guard = Some(UserDb {
277        users: HashMap::new(),
278        next_id: 1,
279    });
280
281    println!("fastapi_rust CRUD API Example");
282    println!("=============================\n");
283
284    let app = App::builder()
285        .post("/users", create_user)
286        .get("/users", list_users)
287        .get("/users/{id}", get_user)
288        .put("/users/{id}", update_user)
289        .delete("/users/{id}", delete_user)
290        .build();
291
292    println!("App created with {} route(s)\n", app.route_count());
293    let client = TestClient::new(app);
294
295    // 1. Create users
296    println!("1. Create users");
297    let resp = client
298        .post("/users")
299        .header("content-type", "application/json")
300        .body(r#"{"name": "Alice", "email": "alice@example.com"}"#)
301        .send();
302    println!(
303        "   POST /users -> {} {}",
304        resp.status().as_u16(),
305        resp.text()
306    );
307    if !check_eq(resp.status().as_u16(), 201, "Create user should return 201") {
308        return;
309    }
310
311    let resp = client
312        .post("/users")
313        .header("content-type", "application/json")
314        .body(r#"{"name": "Bob", "email": "bob@example.com"}"#)
315        .send();
316    println!(
317        "   POST /users -> {} {}",
318        resp.status().as_u16(),
319        resp.text()
320    );
321    if !check_eq(resp.status().as_u16(), 201, "Create user should return 201") {
322        return;
323    }
324
325    // 2. List users
326    println!("\n2. List all users");
327    let resp = client.get("/users").send();
328    println!(
329        "   GET /users -> {} {}",
330        resp.status().as_u16(),
331        resp.text()
332    );
333    if !check_eq(resp.status().as_u16(), 200, "List users should return 200") {
334        return;
335    }
336
337    // 3. Get user by ID
338    println!("\n3. Get user by ID");
339    let resp = client.get("/users/1").send();
340    println!(
341        "   GET /users/1 -> {} {}",
342        resp.status().as_u16(),
343        resp.text()
344    );
345    if !check_eq(resp.status().as_u16(), 200, "Get user should return 200") {
346        return;
347    }
348
349    // 4. Get nonexistent user
350    println!("\n4. Get nonexistent user");
351    let resp = client.get("/users/999").send();
352    println!(
353        "   GET /users/999 -> {} {}",
354        resp.status().as_u16(),
355        resp.text()
356    );
357    if !check_eq(
358        resp.status().as_u16(),
359        404,
360        "Missing user should return 404",
361    ) {
362        return;
363    }
364
365    // 5. Update user
366    println!("\n5. Update user");
367    let resp = client
368        .put("/users/1")
369        .header("content-type", "application/json")
370        .body(r#"{"name": "Alice Smith", "email": "alice.smith@example.com"}"#)
371        .send();
372    println!(
373        "   PUT /users/1 -> {} {}",
374        resp.status().as_u16(),
375        resp.text()
376    );
377    if !check_eq(resp.status().as_u16(), 200, "Update user should return 200") {
378        return;
379    }
380
381    // 6. Validation: empty name
382    println!("\n6. Validation error (empty name)");
383    let resp = client
384        .post("/users")
385        .header("content-type", "application/json")
386        .body(r#"{"name": "", "email": "bad@example.com"}"#)
387        .send();
388    println!(
389        "   POST /users -> {} {}",
390        resp.status().as_u16(),
391        resp.text()
392    );
393    if !check_eq(resp.status().as_u16(), 400, "Empty name should return 400") {
394        return;
395    }
396
397    // 7. Validation: invalid email
398    println!("\n7. Validation error (invalid email)");
399    let resp = client
400        .post("/users")
401        .header("content-type", "application/json")
402        .body(r#"{"name": "Charlie", "email": "not-an-email"}"#)
403        .send();
404    println!(
405        "   POST /users -> {} {}",
406        resp.status().as_u16(),
407        resp.text()
408    );
409    if !check_eq(
410        resp.status().as_u16(),
411        400,
412        "Invalid email should return 400",
413    ) {
414        return;
415    }
416
417    // 8. Wrong Content-Type
418    println!("\n8. Wrong Content-Type");
419    let resp = client
420        .post("/users")
421        .header("content-type", "text/plain")
422        .body(r#"{"name": "Dan", "email": "dan@example.com"}"#)
423        .send();
424    println!(
425        "   POST /users -> {} {}",
426        resp.status().as_u16(),
427        resp.text()
428    );
429    if !check_eq(
430        resp.status().as_u16(),
431        415,
432        "Wrong Content-Type should return 415",
433    ) {
434        return;
435    }
436
437    // 9. Delete user
438    println!("\n9. Delete user");
439    let resp = client.delete("/users/2").send();
440    println!("   DELETE /users/2 -> {}", resp.status().as_u16());
441    if !check_eq(resp.status().as_u16(), 204, "Delete user should return 204") {
442        return;
443    }
444
445    // 10. Verify deletion
446    println!("\n10. Verify deletion");
447    let resp = client.get("/users/2").send();
448    println!(
449        "   GET /users/2 -> {} {}",
450        resp.status().as_u16(),
451        resp.text()
452    );
453    if !check_eq(
454        resp.status().as_u16(),
455        404,
456        "Deleted user should return 404",
457    ) {
458        return;
459    }
460
461    let resp = client.get("/users").send();
462    println!(
463        "   GET /users -> {} {}",
464        resp.status().as_u16(),
465        resp.text()
466    );
467    if !check_eq(resp.status().as_u16(), 200, "List users should return 200") {
468        return;
469    }
470
471    println!("\nAll CRUD operations passed!");
472}
examples/auth_example.rs (line 293)
267fn main() {
268    println!("fastapi_rust Authentication Example");
269    println!("====================================\n");
270
271    // Build the application with public and protected routes
272    let app = App::builder()
273        // Public endpoints - accessible to everyone
274        .get("/public", public_handler)
275        // Login endpoint - returns a token
276        .post("/login", login_handler)
277        // Protected endpoint - requires valid bearer token
278        .get("/protected", protected_handler)
279        .build();
280
281    println!("App created with {} route(s)\n", app.route_count());
282
283    // Create a test client
284    let client = TestClient::new(app);
285
286    // =========================================================================
287    // Test 1: Public endpoint - no auth required
288    // =========================================================================
289    println!("1. Public endpoint - no auth required");
290    let response = client.get("/public").send();
291    println!(
292        "   GET /public -> {} {}",
293        response.status().as_u16(),
294        response.status().canonical_reason()
295    );
296    if !check_eq(
297        response.status().as_u16(),
298        200,
299        "GET /public should return 200",
300    ) {
301        return;
302    }
303    if !check(
304        response.text().contains("public endpoint"),
305        "GET /public should include the public endpoint body",
306    ) {
307        return;
308    }
309
310    // =========================================================================
311    // Test 2: Protected endpoint - without token (should get 401)
312    // =========================================================================
313    println!("\n2. Protected endpoint - without token");
314    let response = client.get("/protected").send();
315    println!(
316        "   GET /protected -> {} {}",
317        response.status().as_u16(),
318        response.status().canonical_reason()
319    );
320    if !check_eq(
321        response.status().as_u16(),
322        401,
323        "Protected endpoint should return 401 without token",
324    ) {
325        return;
326    }
327
328    // Check for WWW-Authenticate header
329    let has_www_auth = response
330        .headers()
331        .iter()
332        .any(|(name, value)| name == "www-authenticate" && value == b"Bearer");
333    if !check(
334        has_www_auth,
335        "401 response should include WWW-Authenticate: Bearer header",
336    ) {
337        return;
338    }
339
340    // =========================================================================
341    // Test 3: Login endpoint - get a token
342    // =========================================================================
343    println!("\n3. Login endpoint - get a token");
344    let response = client
345        .post("/login")
346        .header("content-type", "application/json")
347        .body(r#"{"username":"test","password":"test123"}"#)
348        .send();
349    println!(
350        "   POST /login -> {} {}",
351        response.status().as_u16(),
352        response.status().canonical_reason()
353    );
354    if !check_eq(
355        response.status().as_u16(),
356        200,
357        "POST /login should return 200",
358    ) {
359        return;
360    }
361
362    // Parse the response to get the token
363    let body_text = response.text();
364    let body: serde_json::Value = match serde_json::from_str(body_text) {
365        Ok(body) => body,
366        Err(err) => {
367            eprintln!("Failed to parse login response JSON: {err}");
368            return;
369        }
370    };
371    let Some(bearer_value) = body.get("access_token").and_then(|value| value.as_str()) else {
372        eprintln!("Login response missing access_token");
373        return;
374    };
375    println!("   Bearer value: {bearer_value}");
376    if !check_eq(
377        bearer_value,
378        DEMO_BEARER_VALUE,
379        "Login should return the expected bearer value",
380    ) {
381        return;
382    }
383
384    // =========================================================================
385    // Test 4: Protected endpoint - with valid token (should get 200)
386    // =========================================================================
387    println!("\n4. Protected endpoint - with valid token");
388    let response = client
389        .get("/protected")
390        .header("authorization", format!("Bearer {DEMO_BEARER_VALUE}"))
391        .send();
392    println!(
393        "   GET /protected (Authorization: Bearer {}) -> {} {}",
394        DEMO_BEARER_VALUE,
395        response.status().as_u16(),
396        response.status().canonical_reason()
397    );
398    if !check_eq(
399        response.status().as_u16(),
400        200,
401        "Protected endpoint should return 200 with valid token",
402    ) {
403        return;
404    }
405    if !check(
406        response.text().contains("protected resource"),
407        "Protected endpoint should include protected resource body",
408    ) {
409        return;
410    }
411
412    // =========================================================================
413    // Test 5: Protected endpoint - with invalid token (should get 403)
414    // =========================================================================
415    println!("\n5. Protected endpoint - with invalid token");
416    let response = client
417        .get("/protected")
418        .header("authorization", "Bearer wrong_token")
419        .send();
420    println!(
421        "   GET /protected (Authorization: Bearer wrong_token) -> {} {}",
422        response.status().as_u16(),
423        response.status().canonical_reason()
424    );
425    if !check_eq(
426        response.status().as_u16(),
427        403,
428        "Protected endpoint should return 403 with invalid token",
429    ) {
430        return;
431    }
432
433    // =========================================================================
434    // Test 6: Protected endpoint - with wrong auth scheme (should get 401)
435    // =========================================================================
436    println!("\n6. Protected endpoint - with wrong auth scheme");
437    let response = client
438        .get("/protected")
439        .header("authorization", "Basic dXNlcjpwYXNz")
440        .send();
441    println!(
442        "   GET /protected (Authorization: Basic ...) -> {} {}",
443        response.status().as_u16(),
444        response.status().canonical_reason()
445    );
446    if !check_eq(
447        response.status().as_u16(),
448        401,
449        "Protected endpoint should return 401 with wrong auth scheme",
450    ) {
451        return;
452    }
453
454    // =========================================================================
455    // Test 7: Login with wrong Content-Type (should get 415)
456    // =========================================================================
457    println!("\n7. Login with wrong Content-Type");
458    let response = client
459        .post("/login")
460        .header("content-type", "text/plain")
461        .body("demo=true")
462        .send();
463    println!(
464        "   POST /login (Content-Type: text/plain) -> {} {}",
465        response.status().as_u16(),
466        response.status().canonical_reason()
467    );
468    if !check_eq(
469        response.status().as_u16(),
470        415,
471        "Login should return 415 with wrong Content-Type",
472    ) {
473        return;
474    }
475
476    // =========================================================================
477    // Test 8: Token case sensitivity (lowercase 'bearer')
478    // =========================================================================
479    println!("\n8. Token case sensitivity (lowercase 'bearer')");
480    let response = client
481        .get("/protected")
482        .header("authorization", format!("bearer {DEMO_BEARER_VALUE}"))
483        .send();
484    println!(
485        "   GET /protected (Authorization: bearer {}) -> {} {}",
486        DEMO_BEARER_VALUE,
487        response.status().as_u16(),
488        response.status().canonical_reason()
489    );
490    if !check_eq(
491        response.status().as_u16(),
492        200,
493        "Bearer scheme should be case-insensitive (lowercase accepted)",
494    ) {
495        return;
496    }
497
498    println!("\nAll authentication tests passed!");
499}
Source

pub const fn allows_body(self) -> bool

Check if status code allows a body.

Source

pub const fn canonical_reason(self) -> &'static str

Get the canonical reason phrase.

Examples found in repository?
examples/hello_world.rs (line 100)
61fn main() {
62    println!("fastapi_rust Hello World Example");
63    println!("================================\n");
64
65    // Build the application
66    //
67    // App::builder() creates a new application builder that lets you:
68    // - Add routes for different HTTP methods
69    // - Configure middleware
70    // - Set application state
71    // - Define exception handlers
72    let app = App::builder()
73        // Register a GET handler for the root path "/"
74        //
75        // This is equivalent to:
76        //   @app.get("/")
77        //   def hello():
78        //       return "Hello, World!"
79        // in Python FastAPI
80        .get("/", hello_handler)
81        // Build the final immutable App
82        .build();
83
84    println!("App created with {} route(s)\n", app.route_count());
85
86    // Create a test client to make requests to our app
87    //
88    // TestClient wraps any Handler (including App) and provides
89    // a convenient API for making HTTP requests in tests.
90    let client = TestClient::new(app);
91
92    // Make a GET request to "/"
93    println!("Making request: GET /");
94    let response = client.get("/").send();
95
96    // Check the response
97    println!(
98        "GET / -> {} {}",
99        response.status().as_u16(),
100        response.status().canonical_reason()
101    );
102    println!("Response: {}\n", response.text());
103
104    // Verify success
105    if !check_eq(response.status().as_u16(), 200, "GET / should return 200") {
106        return;
107    }
108    if !check_eq(response.text(), "Hello, World!", "GET / should return body") {
109        return;
110    }
111
112    // Try a path that doesn't exist - should get 404
113    println!("Making request: GET /not-found");
114    let response = client.get("/not-found").send();
115    println!(
116        "GET /not-found -> {} {}",
117        response.status().as_u16(),
118        response.status().canonical_reason()
119    );
120    if !check_eq(
121        response.status().as_u16(),
122        404,
123        "Unknown routes should return 404",
124    ) {
125        return;
126    }
127
128    println!("\nAll assertions passed!");
129}
More examples
Hide additional examples
examples/auth_example.rs (line 294)
267fn main() {
268    println!("fastapi_rust Authentication Example");
269    println!("====================================\n");
270
271    // Build the application with public and protected routes
272    let app = App::builder()
273        // Public endpoints - accessible to everyone
274        .get("/public", public_handler)
275        // Login endpoint - returns a token
276        .post("/login", login_handler)
277        // Protected endpoint - requires valid bearer token
278        .get("/protected", protected_handler)
279        .build();
280
281    println!("App created with {} route(s)\n", app.route_count());
282
283    // Create a test client
284    let client = TestClient::new(app);
285
286    // =========================================================================
287    // Test 1: Public endpoint - no auth required
288    // =========================================================================
289    println!("1. Public endpoint - no auth required");
290    let response = client.get("/public").send();
291    println!(
292        "   GET /public -> {} {}",
293        response.status().as_u16(),
294        response.status().canonical_reason()
295    );
296    if !check_eq(
297        response.status().as_u16(),
298        200,
299        "GET /public should return 200",
300    ) {
301        return;
302    }
303    if !check(
304        response.text().contains("public endpoint"),
305        "GET /public should include the public endpoint body",
306    ) {
307        return;
308    }
309
310    // =========================================================================
311    // Test 2: Protected endpoint - without token (should get 401)
312    // =========================================================================
313    println!("\n2. Protected endpoint - without token");
314    let response = client.get("/protected").send();
315    println!(
316        "   GET /protected -> {} {}",
317        response.status().as_u16(),
318        response.status().canonical_reason()
319    );
320    if !check_eq(
321        response.status().as_u16(),
322        401,
323        "Protected endpoint should return 401 without token",
324    ) {
325        return;
326    }
327
328    // Check for WWW-Authenticate header
329    let has_www_auth = response
330        .headers()
331        .iter()
332        .any(|(name, value)| name == "www-authenticate" && value == b"Bearer");
333    if !check(
334        has_www_auth,
335        "401 response should include WWW-Authenticate: Bearer header",
336    ) {
337        return;
338    }
339
340    // =========================================================================
341    // Test 3: Login endpoint - get a token
342    // =========================================================================
343    println!("\n3. Login endpoint - get a token");
344    let response = client
345        .post("/login")
346        .header("content-type", "application/json")
347        .body(r#"{"username":"test","password":"test123"}"#)
348        .send();
349    println!(
350        "   POST /login -> {} {}",
351        response.status().as_u16(),
352        response.status().canonical_reason()
353    );
354    if !check_eq(
355        response.status().as_u16(),
356        200,
357        "POST /login should return 200",
358    ) {
359        return;
360    }
361
362    // Parse the response to get the token
363    let body_text = response.text();
364    let body: serde_json::Value = match serde_json::from_str(body_text) {
365        Ok(body) => body,
366        Err(err) => {
367            eprintln!("Failed to parse login response JSON: {err}");
368            return;
369        }
370    };
371    let Some(bearer_value) = body.get("access_token").and_then(|value| value.as_str()) else {
372        eprintln!("Login response missing access_token");
373        return;
374    };
375    println!("   Bearer value: {bearer_value}");
376    if !check_eq(
377        bearer_value,
378        DEMO_BEARER_VALUE,
379        "Login should return the expected bearer value",
380    ) {
381        return;
382    }
383
384    // =========================================================================
385    // Test 4: Protected endpoint - with valid token (should get 200)
386    // =========================================================================
387    println!("\n4. Protected endpoint - with valid token");
388    let response = client
389        .get("/protected")
390        .header("authorization", format!("Bearer {DEMO_BEARER_VALUE}"))
391        .send();
392    println!(
393        "   GET /protected (Authorization: Bearer {}) -> {} {}",
394        DEMO_BEARER_VALUE,
395        response.status().as_u16(),
396        response.status().canonical_reason()
397    );
398    if !check_eq(
399        response.status().as_u16(),
400        200,
401        "Protected endpoint should return 200 with valid token",
402    ) {
403        return;
404    }
405    if !check(
406        response.text().contains("protected resource"),
407        "Protected endpoint should include protected resource body",
408    ) {
409        return;
410    }
411
412    // =========================================================================
413    // Test 5: Protected endpoint - with invalid token (should get 403)
414    // =========================================================================
415    println!("\n5. Protected endpoint - with invalid token");
416    let response = client
417        .get("/protected")
418        .header("authorization", "Bearer wrong_token")
419        .send();
420    println!(
421        "   GET /protected (Authorization: Bearer wrong_token) -> {} {}",
422        response.status().as_u16(),
423        response.status().canonical_reason()
424    );
425    if !check_eq(
426        response.status().as_u16(),
427        403,
428        "Protected endpoint should return 403 with invalid token",
429    ) {
430        return;
431    }
432
433    // =========================================================================
434    // Test 6: Protected endpoint - with wrong auth scheme (should get 401)
435    // =========================================================================
436    println!("\n6. Protected endpoint - with wrong auth scheme");
437    let response = client
438        .get("/protected")
439        .header("authorization", "Basic dXNlcjpwYXNz")
440        .send();
441    println!(
442        "   GET /protected (Authorization: Basic ...) -> {} {}",
443        response.status().as_u16(),
444        response.status().canonical_reason()
445    );
446    if !check_eq(
447        response.status().as_u16(),
448        401,
449        "Protected endpoint should return 401 with wrong auth scheme",
450    ) {
451        return;
452    }
453
454    // =========================================================================
455    // Test 7: Login with wrong Content-Type (should get 415)
456    // =========================================================================
457    println!("\n7. Login with wrong Content-Type");
458    let response = client
459        .post("/login")
460        .header("content-type", "text/plain")
461        .body("demo=true")
462        .send();
463    println!(
464        "   POST /login (Content-Type: text/plain) -> {} {}",
465        response.status().as_u16(),
466        response.status().canonical_reason()
467    );
468    if !check_eq(
469        response.status().as_u16(),
470        415,
471        "Login should return 415 with wrong Content-Type",
472    ) {
473        return;
474    }
475
476    // =========================================================================
477    // Test 8: Token case sensitivity (lowercase 'bearer')
478    // =========================================================================
479    println!("\n8. Token case sensitivity (lowercase 'bearer')");
480    let response = client
481        .get("/protected")
482        .header("authorization", format!("bearer {DEMO_BEARER_VALUE}"))
483        .send();
484    println!(
485        "   GET /protected (Authorization: bearer {}) -> {} {}",
486        DEMO_BEARER_VALUE,
487        response.status().as_u16(),
488        response.status().canonical_reason()
489    );
490    if !check_eq(
491        response.status().as_u16(),
492        200,
493        "Bearer scheme should be case-insensitive (lowercase accepted)",
494    ) {
495        return;
496    }
497
498    println!("\nAll authentication tests passed!");
499}

Trait Implementations§

Source§

impl Clone for StatusCode

Source§

fn clone(&self) -> StatusCode

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for StatusCode

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Hash for StatusCode

Source§

fn hash<__H>(&self, state: &mut __H)
where __H: Hasher,

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl IntoStatusU16 for StatusCode

Source§

impl PartialEq for StatusCode

Source§

fn eq(&self, other: &StatusCode) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for StatusCode

Source§

impl Eq for StatusCode

Source§

impl StructuralPartialEq for StatusCode

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, _span: NoopSpan) -> Self

Instruments this future with a span (no-op when disabled).
Source§

fn in_current_span(self) -> Self

Instruments this future with the current span (no-op when disabled).
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ResponseProduces<T> for T