@@ -3302,4 +3302,193 @@ paths:
33023302 "Response should include CORS header from global middleware"
33033303 ) ;
33043304 }
3305+
3306+ // ==================== Request Size Limit Tests ====================
3307+
3308+ #[ tokio:: test]
3309+ async fn test_request_size_limit_allows_small_body ( ) {
3310+ let gateway = TestGateway :: from_spec ( "../../tests/fixtures/request-size-limit.yaml" )
3311+ . await
3312+ . expect ( "failed to start gateway" ) ;
3313+
3314+ // Small body should be allowed (under 100 byte limit)
3315+ let resp = gateway
3316+ . request_builder ( reqwest:: Method :: POST , "/limited" )
3317+ . header ( "Content-Type" , "application/json" )
3318+ . body ( r#"{"msg":"hi"}"# )
3319+ . send ( )
3320+ . await
3321+ . unwrap ( ) ;
3322+
3323+ assert_eq ! ( resp. status( ) , 200 ) ;
3324+ let body: serde_json:: Value = resp. json ( ) . await . unwrap ( ) ;
3325+ assert_eq ! ( body[ "message" ] , "ok" ) ;
3326+ }
3327+
3328+ #[ tokio:: test]
3329+ async fn test_request_size_limit_blocks_large_body ( ) {
3330+ let gateway = TestGateway :: from_spec ( "../../tests/fixtures/request-size-limit.yaml" )
3331+ . await
3332+ . expect ( "failed to start gateway" ) ;
3333+
3334+ // Large body should be rejected (over 100 byte limit)
3335+ let large_body = r#"{"data":"this is a very long message that exceeds the configured limit of 100 bytes for this endpoint"}"# ;
3336+ let resp = gateway
3337+ . request_builder ( reqwest:: Method :: POST , "/limited" )
3338+ . header ( "Content-Type" , "application/json" )
3339+ . body ( large_body)
3340+ . send ( )
3341+ . await
3342+ . unwrap ( ) ;
3343+
3344+ assert_eq ! ( resp. status( ) , 413 ) ;
3345+ let body: serde_json:: Value = resp. json ( ) . await . unwrap ( ) ;
3346+ assert_eq ! ( body[ "type" ] , "urn:barbacane:error:payload-too-large" ) ;
3347+ assert_eq ! ( body[ "status" ] , 413 ) ;
3348+ }
3349+
3350+ #[ tokio:: test]
3351+ async fn test_request_size_limit_unlimited_endpoint ( ) {
3352+ let gateway = TestGateway :: from_spec ( "../../tests/fixtures/request-size-limit.yaml" )
3353+ . await
3354+ . expect ( "failed to start gateway" ) ;
3355+
3356+ // Unlimited endpoint should accept large bodies
3357+ let large_body = r#"{"data":"this is a very long message that would be rejected on the limited endpoint but should pass here"}"# ;
3358+ let resp = gateway
3359+ . request_builder ( reqwest:: Method :: POST , "/unlimited" )
3360+ . header ( "Content-Type" , "application/json" )
3361+ . body ( large_body)
3362+ . send ( )
3363+ . await
3364+ . unwrap ( ) ;
3365+
3366+ assert_eq ! ( resp. status( ) , 200 ) ;
3367+ let body: serde_json:: Value = resp. json ( ) . await . unwrap ( ) ;
3368+ assert_eq ! ( body[ "message" ] , "unlimited" ) ;
3369+ }
3370+
3371+ // ==================== IP Restriction Tests ====================
3372+
3373+ #[ tokio:: test]
3374+ async fn test_ip_restriction_allowlist_localhost ( ) {
3375+ let gateway = TestGateway :: from_spec ( "../../tests/fixtures/ip-restriction.yaml" )
3376+ . await
3377+ . expect ( "failed to start gateway" ) ;
3378+
3379+ // Localhost should be allowed
3380+ let resp = gateway
3381+ . request_builder ( reqwest:: Method :: GET , "/allowlist" )
3382+ . send ( )
3383+ . await
3384+ . unwrap ( ) ;
3385+
3386+ assert_eq ! ( resp. status( ) , 200 ) ;
3387+ let body: serde_json:: Value = resp. json ( ) . await . unwrap ( ) ;
3388+ assert_eq ! ( body[ "message" ] , "allowed" ) ;
3389+ }
3390+
3391+ #[ tokio:: test]
3392+ async fn test_ip_restriction_allowlist_denied_via_xff ( ) {
3393+ let gateway = TestGateway :: from_spec ( "../../tests/fixtures/ip-restriction.yaml" )
3394+ . await
3395+ . expect ( "failed to start gateway" ) ;
3396+
3397+ // Request with X-Forwarded-For from non-allowed IP should be denied
3398+ let resp = gateway
3399+ . request_builder ( reqwest:: Method :: GET , "/allowlist" )
3400+ . header ( "X-Forwarded-For" , "203.0.113.50" )
3401+ . send ( )
3402+ . await
3403+ . unwrap ( ) ;
3404+
3405+ assert_eq ! ( resp. status( ) , 403 ) ;
3406+ let body: serde_json:: Value = resp. json ( ) . await . unwrap ( ) ;
3407+ assert_eq ! ( body[ "type" ] , "urn:barbacane:error:ip-restricted" ) ;
3408+ }
3409+
3410+ #[ tokio:: test]
3411+ async fn test_ip_restriction_denylist_allowed ( ) {
3412+ let gateway = TestGateway :: from_spec ( "../../tests/fixtures/ip-restriction.yaml" )
3413+ . await
3414+ . expect ( "failed to start gateway" ) ;
3415+
3416+ // Request from localhost (not in denylist) should be allowed
3417+ let resp = gateway
3418+ . request_builder ( reqwest:: Method :: GET , "/denylist" )
3419+ . send ( )
3420+ . await
3421+ . unwrap ( ) ;
3422+
3423+ assert_eq ! ( resp. status( ) , 200 ) ;
3424+ }
3425+
3426+ #[ tokio:: test]
3427+ async fn test_ip_restriction_denylist_blocked ( ) {
3428+ let gateway = TestGateway :: from_spec ( "../../tests/fixtures/ip-restriction.yaml" )
3429+ . await
3430+ . expect ( "failed to start gateway" ) ;
3431+
3432+ // Request from denied CIDR range should be blocked
3433+ let resp = gateway
3434+ . request_builder ( reqwest:: Method :: GET , "/denylist" )
3435+ . header ( "X-Forwarded-For" , "10.1.2.3" )
3436+ . send ( )
3437+ . await
3438+ . unwrap ( ) ;
3439+
3440+ assert_eq ! ( resp. status( ) , 403 ) ;
3441+ }
3442+
3443+ #[ tokio:: test]
3444+ async fn test_ip_restriction_cidr_allowlist ( ) {
3445+ let gateway = TestGateway :: from_spec ( "../../tests/fixtures/ip-restriction.yaml" )
3446+ . await
3447+ . expect ( "failed to start gateway" ) ;
3448+
3449+ // 127.0.0.1 is in 127.0.0.0/8 CIDR range
3450+ let resp = gateway
3451+ . request_builder ( reqwest:: Method :: GET , "/cidr-allowlist" )
3452+ . send ( )
3453+ . await
3454+ . unwrap ( ) ;
3455+
3456+ assert_eq ! ( resp. status( ) , 200 ) ;
3457+ }
3458+
3459+ #[ tokio:: test]
3460+ async fn test_ip_restriction_custom_message ( ) {
3461+ let gateway = TestGateway :: from_spec ( "../../tests/fixtures/ip-restriction.yaml" )
3462+ . await
3463+ . expect ( "failed to start gateway" ) ;
3464+
3465+ // Request from non-allowed IP should get custom status and message
3466+ let resp = gateway
3467+ . request_builder ( reqwest:: Method :: GET , "/custom-message" )
3468+ . send ( )
3469+ . await
3470+ . unwrap ( ) ;
3471+
3472+ assert_eq ! ( resp. status( ) , 401 ) ;
3473+ let body: serde_json:: Value = resp. json ( ) . await . unwrap ( ) ;
3474+ assert ! ( body[ "detail" ] . as_str( ) . unwrap( ) . contains( "not authorized" ) ) ;
3475+ }
3476+
3477+ #[ tokio:: test]
3478+ async fn test_ip_restriction_public_endpoint ( ) {
3479+ let gateway = TestGateway :: from_spec ( "../../tests/fixtures/ip-restriction.yaml" )
3480+ . await
3481+ . expect ( "failed to start gateway" ) ;
3482+
3483+ // Public endpoint without IP restriction
3484+ let resp = gateway
3485+ . request_builder ( reqwest:: Method :: GET , "/public" )
3486+ . send ( )
3487+ . await
3488+ . unwrap ( ) ;
3489+
3490+ assert_eq ! ( resp. status( ) , 200 ) ;
3491+ let body: serde_json:: Value = resp. json ( ) . await . unwrap ( ) ;
3492+ assert_eq ! ( body[ "message" ] , "public" ) ;
3493+ }
33053494}
0 commit comments