Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix cleanup in Netty handler after a request timeout #4156

Merged
merged 2 commits into from
Nov 12, 2024

Fix post-cancellation cleanup in synchronous netty server

fde3511
Select commit
Loading
Failed to load commit list.
Sign in for the full log view
Merged

Fix cleanup in Netty handler after a request timeout #4156

Fix post-cancellation cleanup in synchronous netty server
fde3511
Select commit
Loading
Failed to load commit list.
GitHub Actions / Test report for 3-JVM-21 succeeded Nov 12, 2024 in 0s

420 passed, 0 failed and 0 skipped

Tests passed successfully

Report Passed Failed Skipped Time
server/netty-server/sync/target/jvm-3/test-reports/TEST-sttp.tapir.server.netty.sync.NettySyncServerTest.xml 224✅ 13s
server/nima-server/target/jvm-3/test-reports/TEST-sttp.tapir.server.nima.NimaServerTest.xml 196✅ 5s

✅ server/netty-server/sync/target/jvm-3/test-reports/TEST-sttp.tapir.server.netty.sync.NettySyncServerTest.xml

224 tests were completed in 13s with 224 passed, 0 failed and 0 skipped.

Test suite Passed Failed Skipped Time
sttp.tapir.server.netty.sync.NettySyncServerTest 224✅ 13s

✅ sttp.tapir.server.netty.sync.NettySyncServerTest

✅ ServerEndpoint(securityin: /auth auth(api key, via {header X-Api-Key}), in: -, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: /auth auth(api key, via {header X-Api-Key}), in: ?amount, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: /auth auth(api key, via ?api-key), in: -, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: /auth auth(Basic http, via {header Authorization}), in: -, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: /auth auth(Bearer http, via {header Authorization}), in: -, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: /auth auth(Basic http, via {header Authorization}), in: -, errout: -, out: {body as text/plain (UTF-8)}) In security Option[UsernamePassword] should let in basic auth as well as request without auth
✅ ServerEndpoint(securityin: /auth auth(Basic http, via {header Authorization}) auth(Bearer http, via {header Authorization}), in: -, errout: -, out: {body as text/plain (UTF-8)}) In security (Option[UsernamePassword], Option[String]) should pass bearer auth, basic auth, and also request without auth
✅ ServerEndpoint(securityin: /secret /[id] auth(Basic http, via {header Authorization}), in: POST ?q, errout: -, out: -) correct basic
✅ ServerEndpoint(securityin: /secret /[id] auth(Bearer http, via {header Authorization}), in: POST ?q, errout: -, out: -) correct bearer
✅ ServerEndpoint(securityin: /secret /[id] auth(Bearer http, via {header Authorization}), in: POST ?q, errout: -, out: -) correct lower case bearer
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via ?token), in: POST ?q, errout: -, out: -) correct apiKey in query param
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header x-api-key}), in: POST ?q, errout: -, out: -) correct apiKey in header
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header token-old}) auth(api key, via {header token-new}), in: POST ?q, errout: -, out: -) correct old token in header
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header token-old}) auth(api key, via {header token-new}), in: POST ?q, errout: -, out: -) correct new token in header
✅ ServerEndpoint(securityin: /secret /[id] auth(Basic http, via {header Authorization}), in: POST ?q, errout: -, out: -) missing basic
✅ ServerEndpoint(securityin: /secret /[id] auth(Bearer http, via {header Authorization}), in: POST ?q, errout: -, out: -) missing bearer
✅ ServerEndpoint(securityin: /secret /[id] auth(Bearer http, via {header Authorization}), in: POST ?q, errout: -, out: -) missing lower case bearer
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via ?token), in: POST ?q, errout: -, out: -) missing apiKey in query param
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header x-api-key}), in: POST ?q, errout: -, out: -) missing apiKey in header
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header token-old}) auth(api key, via {header token-new}), in: POST ?q, errout: -, out: -) missing old token in header
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header token-old}) auth(api key, via {header token-new}), in: POST ?q, errout: -, out: -) missing new token in header
✅ ServerEndpoint(securityin: /secret /[id] auth(Basic http, via {header Authorization}), in: POST ?q, errout: -, out: -) missing basic with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(Bearer http, via {header Authorization}), in: POST ?q, errout: -, out: -) missing bearer with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(Bearer http, via {header Authorization}), in: POST ?q, errout: -, out: -) missing lower case bearer with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via ?token), in: POST ?q, errout: -, out: -) missing apiKey in query param with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header x-api-key}), in: POST ?q, errout: -, out: -) missing apiKey in header with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header token-old}) auth(api key, via {header token-new}), in: POST ?q, errout: -, out: -) missing old token in header with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header token-old}) auth(api key, via {header token-new}), in: POST ?q, errout: -, out: -) missing new token in header with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(Basic http, via {header Authorization}), in: POST ?q, errout: -, out: -) invalid request basic
✅ ServerEndpoint(securityin: /secret /[id] auth(Bearer http, via {header Authorization}), in: POST ?q, errout: -, out: -) invalid request bearer
✅ ServerEndpoint(securityin: /secret /[id] auth(Bearer http, via {header Authorization}), in: POST ?q, errout: -, out: -) invalid request lower case bearer
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via ?token), in: POST ?q, errout: -, out: -) invalid request apiKey in query param
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header x-api-key}), in: POST ?q, errout: -, out: -) invalid request apiKey in header
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header token-old}) auth(api key, via {header token-new}), in: POST ?q, errout: -, out: -) invalid request old token in header
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header token-old}) auth(api key, via {header token-new}), in: POST ?q, errout: -, out: -) invalid request new token in header
✅ ServerEndpoint(securityin: /secret /[id] auth(Basic http, via {header Authorization}), in: POST ?q, errout: -, out: -) invalid request basic with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(Bearer http, via {header Authorization}), in: POST ?q, errout: -, out: -) invalid request bearer with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(Bearer http, via {header Authorization}), in: POST ?q, errout: -, out: -) invalid request lower case bearer with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via ?token), in: POST ?q, errout: -, out: -) invalid request apiKey in query param with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header x-api-key}), in: POST ?q, errout: -, out: -) invalid request apiKey in header with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header token-old}) auth(api key, via {header token-new}), in: POST ?q, errout: -, out: -) invalid request old token in header with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header token-old}) auth(api key, via {header token-new}), in: POST ?q, errout: -, out: -) invalid request new token in header with endpoint hiding
✅ ServerEndpoint(securityin: -, in: ?fruit, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: -, in: ?fruit, errout: -, out: {body as text/plain (UTF-8)}) with URL encoding
✅ ServerEndpoint[infallible](securityin: -, in: ?fruit, errout: void, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: -, in: ?fruit ?amount, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: -, in: {header X-Role}, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: -, in: /fruit /[] /amount /[], errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: -, in: /fruit /[] /amount /[], errout: -, out: {body as text/plain (UTF-8)}) with URL encoding
✅ ServerEndpoint(securityin: -, in: GET /api /[], errout: -, out: -) Empty path should not be passed to path capture decoding
✅ ServerEndpoint(securityin: -, in: /in /[] /[], errout: -, out: {header a} {header b}) capturing two path parameters with the same specification
✅ ServerEndpoint(securityin: -, in: POST /api /echo {body as text/plain (UTF-8)}, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: -, in: POST /api /echo {body as text/plain (UTF-8)}, errout: -, out: {body as text/plain (UTF-8)}) with get method
✅ ServerEndpoint(securityin: -, in: {header SomeHeader} /[], errout: -, out: {header IntHeader} {body as text/plain (UTF-8)}) Header input before path capture input
✅ ServerEndpoint[echo json](securityin: -, in: POST /api /echo {body as application/json (UTF-8)}, errout: -, out: {body as application/json (UTF-8)})
✅ ServerEndpoint[echo json](securityin: -, in: POST /api /echo {body as application/json (UTF-8)}, errout: -, out: {body as application/json (UTF-8)}) with accept header
✅ ServerEndpoint[echo json](securityin: -, in: POST /api /echo {body as application/json (UTF-8)}, errout: -, out: {body as application/json (UTF-8)}) content type
✅ ServerEndpoint[echo byte array](securityin: -, in: POST /api /echo {body as application/octet-stream}, errout: -, out: {body as application/octet-stream})
✅ ServerEndpoint[echo byte buffer](securityin: -, in: POST /api /echo {body as application/octet-stream}, errout: -, out: {body as application/octet-stream})
✅ ServerEndpoint(securityin: -, in: /api /unit, errout: -, out: {body as application/json (UTF-8)}) unit json mapper
✅ ServerEndpoint(securityin: -, in: /api, errout: -, out: {body as text/plain (UTF-8)}) default status mapper
✅ ServerEndpoint(securityin: -, in: /api, errout: {body as text/plain (UTF-8)}, out: -) default error status mapper
✅ ServerEndpoint(securityin: -, in: POST /api /echo {body as application/x-www-form-urlencoded (UTF-8)}, errout: -, out: {body as application/x-www-form-urlencoded (UTF-8)})
✅ ServerEndpoint(securityin: -, in: GET /api /echo /params ?*, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: -, in: GET /[pathParam] ?*, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: -, in: GET /api /echo /params ?*, errout: -, out: {body as text/plain (UTF-8)}) should support value-less query param
✅ ServerEndpoint(securityin: -, in: GET /api /echo /headers {multiple headers}, errout: -, out: {multiple headers})
✅ ServerEndpoint(securityin: -, in: GET /*, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: -, in: GET /*, errout: -, out: {body as text/plain (UTF-8)}) paths should match empty path
✅ ServerEndpoint(securityin: -, in: ?fruit, errout: -, out: {body as text/plain (UTF-8)}) invalid query parameter
✅ ServerEndpoint(securityin: -, in: GET /api /echo /param-to-header ?qq, errout: -, out: {header hh})
✅ ServerEndpoint(securityin: -, in: GET /api /echo /headers {header Cookie}, errout: -, out: {header Set-Cookie})
✅ ServerEndpoint(securityin: -, in: /cookies-test GET, errout: -, out: {header Set-Cookie}) should not fold multiple Set-Cookie headers
✅ ServerEndpoint(securityin: -, in: GET / ?q, errout: -, out: {header Set-Cookie} {body as text/plain (UTF-8)}) should be invulnerable to response splitting from unsanitized headers
✅ ServerEndpoint(securityin: -, in: GET /api /echo /headers {header Set-Cookie}, errout: -, out: {header Set-Cookie})
✅ ServerEndpoint(securityin: -, in: /api /echo {body as text/plain (UTF-8)}, errout: -, out: {body as text/plain (UTF-8)} {header Content-Type}) dynamic content type
✅ ServerEndpoint(securityin: -, in: /api /echo {header Content-Type}, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: -, in: POST /api /echo {header Content-Type: application/json}, errout: -, out: -) mismatch content-type
✅ ServerEndpoint(securityin: -, in: POST /api /echo {header Content-Type: application/json}, errout: -, out: -) missing content-type
✅ ServerEndpoint(securityin: -, in: POST /api /echo {header Content-Type}, errout: -, out: -) mismatch content-type
✅ ServerEndpoint(securityin: -, in: POST /api /echo {header Content-Type}, errout: -, out: -) missing content-type
✅ ServerEndpoint(securityin: -, in: /api /echo, errout: -, out: {body as text/html (UTF-8)})
✅ ServerEndpoint(securityin: -, in: -, errout: -, out: status code (308) {header Location})
✅ ServerEndpoint(securityin: -, in: -, errout: -, out: {header Location: Poland})
✅ ServerEndpoint(securityin: -, in: POST /api /echo {body as application/json (UTF-8)}, errout: -, out: {body as application/json (UTF-8)})
✅ ServerEndpoint(securityin: -, in: ?fruit, errout: -, out: status code - possible codes (Map())) custom status code
✅ ServerEndpoint(securityin: -, in: {data from request}, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: -, in: ?fruit, errout: -, out: status code - possible codes (Map()))
✅ ServerEndpoint[Query with default](securityin: -, in: ?p1, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: -, in: /api {header Content-Type: multipart/form-data}, errout: -, out: {body as text/plain (UTF-8)}) fixed multipart/form-data header input should ignore boundary directive
✅ ServerEndpoint(securityin: -, in: ?kind, errout: -, out: {header Content-Type})
✅ ServerEndpoint(securityin: -, in: ?kind, errout: -, out: {header Content-Type} {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: -, in: POST /api /echo {body as application/json (UTF-8)}, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: -, in: GET ?flag, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: -, in: ?fruit, errout: -, out: {body as text/plain (UTF-8)}) should contain the content-length header
✅ ServerEndpoint(securityin: -, in: -, errout: -, out: -) GET empty endpoint
✅ ServerEndpoint(securityin: -, in: -, errout: -, out: -) POST empty endpoint
✅ ServerEndpoint(securityin: -, in: -, errout: -, out: {body as text/plain (UTF-8)} {header Content-Type: text/csv}) Fixed content-type header
✅ ServerEndpoint(securityin: -, in: GET, errout: -, out: -) GET a GET endpoint
✅ ServerEndpoint(securityin: -, in: GET, errout: -, out: -) POST a GET endpoint
✅ ServerEndpoint(securityin: -, in: -, errout: -, out: -) no path should match anything
✅ ServerEndpoint(securityin: -, in: GET /, errout: -, out: -) root path should not match non-root path
✅ ServerEndpoint(securityin: -, in: GET /, errout: -, out: -) root path should match empty path
✅ ServerEndpoint(securityin: -, in: GET /, errout: -, out: -) root path should match root path
✅ ServerEndpoint(securityin: -, in: GET /api, errout: -, out: -) single path should match single path
✅ ServerEndpoint(securityin: -, in: GET /api, errout: -, out: -) single path should match single/ path
✅ ServerEndpoint(securityin: -, in: GET /api /[] /and /*, errout: -, out: {header IntPath} {body as text/plain (UTF-8)}) Capturing paths after path capture
✅ ServerEndpoint(securityin: -, in: GET /api /[] /and /*, errout: -, out: {header IntPath} {body as text/plain (UTF-8)}) Capturing paths after path capture (when empty)
✅ ServerEndpoint(securityin: -, in: GET /api, errout: -, out: -) single path should not match root path
✅ ServerEndpoint(securityin: -, in: GET /api, errout: -, out: -) single path should not match larger path
✅ ServerEndpoint(securityin: /auth, in: /settings, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: /auth, in: -, errout: -, out: {body as text/plain (UTF-8)})
✅ two endpoints with increasingly specific path inputs: should match path exactly
✅ two endpoints with increasingly specific path inputs (w/ path capture): should match path exactly
✅ two endpoints with decreasingly specific path inputs: should match path exactly
✅ two endpoints with a body defined as the first input: should only consume body when the path matches
✅ two endpoints with query defined as the first input, path segments as second input: should try the second endpoint if the path doesn't match
✅ two endpoints with increasingly specific path inputs, first with a required query parameter: should match path exactly
✅ two endpoints with validation: should not try the second one if validation fails
✅ endpoint with a security input and regular path input shouldn't shadow other endpoints
✅ two endpoints, same path prefix, one without trailing slashes, second accepting trailing slashes
✅ try other paths on decode failure if onDecodeFailureNextEndpoint
✅ two endpoints with different methods, first one with path parsing
✅ two endpoints with fixed path & path capture as the middle component
✅ two endpoints with fixed path & path capture as the middle component, different methods
✅ ServerEndpoint(securityin: -, in: GET /customer /[customer_id] /orders /[order_id], errout: -, out: -) Returns 400 if path 'shape' matches, but failed to parse a path parameter, using a custom decode failure handler
✅ ServerEndpoint(securityin: -, in: GET /customer /[customer_id] /orders /[order_id], errout: -, out: -) Returns 404 if path 'shape' doesn't match
✅ ServerEndpoint(securityin: -, in: GET /customer /[customer_id], errout: -, out: -) Returns 400 if path 'shape' matches, but failed to parse a path parameter
✅ Tries next endpoint if path 'shape' matches, but validation fails, using .onDecodeFailureNextEndpoint
✅ ServerEndpoint(securityin: ?x, in: ?y, errout: -, out: {body as text/plain (UTF-8)}) server security logic - one input
✅ ServerEndpoint(securityin: ?x ?y, in: ?z ?u, errout: -, out: {body as text/plain (UTF-8)}) server security logic - multiple inputs
✅ ServerEndpoint[echo input stream](securityin: -, in: POST /api /echo {body as application/octet-stream}, errout: -, out: {body as application/octet-stream})
✅ ServerEndpoint[input string output stream with header](securityin: -, in: POST /api /echo {body as text/plain (UTF-8)}, errout: -, out: {body as application/octet-stream} {header Content-Length})
✅ ServerEndpoint(securityin: -, in: POST /api /echo {body as text/plain (UTF-8)}, errout: -, out: {body as text/plain (UTF-8)}) checks payload limit and returns 413 on exceeded max content length (request)
✅ ServerEndpoint[echo byte array](securityin: -, in: POST /api /echo {body as application/octet-stream}, errout: -, out: {body as application/octet-stream}) checks payload limit and returns 413 on exceeded max content length (request)
✅ ServerEndpoint[echo file](securityin: -, in: POST /api /echo {body as application/octet-stream}, errout: -, out: {body as application/octet-stream}) checks payload limit and returns 413 on exceeded max content length (request)
✅ ServerEndpoint[echo input stream](securityin: -, in: POST /api /echo {body as application/octet-stream}, errout: -, out: {body as application/octet-stream}) checks payload limit and returns 413 on exceeded max content length (request)
✅ ServerEndpoint[echo byte buffer](securityin: -, in: POST /api /echo {body as application/octet-stream}, errout: -, out: {body as application/octet-stream}) checks payload limit and returns 413 on exceeded max content length (request)
✅ ServerEndpoint(securityin: -, in: POST /api /echo {body as text/plain (UTF-8)}, errout: -, out: {body as text/plain (UTF-8)}) checks payload limit and returns OK on content length  below or equal max (request)
✅ ServerEndpoint[echo input stream](securityin: -, in: POST /api /echo {body as application/octet-stream}, errout: -, out: {body as application/octet-stream}) checks payload limit and returns OK on content length  below or equal max (request)
✅ ServerEndpoint[echo byte array](securityin: -, in: POST /api /echo {body as application/octet-stream}, errout: -, out: {body as application/octet-stream}) checks payload limit and returns OK on content length  below or equal max (request)
✅ ServerEndpoint[echo file](securityin: -, in: POST /api /echo {body as application/octet-stream}, errout: -, out: {body as application/octet-stream}) checks payload limit and returns OK on content length  below or equal max (request)
✅ ServerEndpoint[echo byte buffer](securityin: -, in: POST /api /echo {body as application/octet-stream}, errout: -, out: {body as application/octet-stream}) checks payload limit and returns OK on content length  below or equal max (request)
✅ ServerEndpoint(securityin: -, in: -, errout: -, out: -) handle exceptions
✅ recover errors from exceptions
✅ ServerEndpoint(securityin: -, in: GET /content-negotiation /organization {header Accept}, errout: -, out: one of(status code (200) {body as application/json (UTF-8)}|status code (200) {body as application/xml (UTF-8)}|status code (200) {body as text/html (UTF-8)}|status code (200) {body as text/html (ISO-8859-1)}))
✅ ServerEndpoint(securityin: -, in: GET /content-negotiation /organization, errout: -, out: one of(status code (200) {body as application/json (UTF-8)}|status code (200) {body as application/xml (UTF-8)})) takes first content type when no accepts header
✅ ServerEndpoint(securityin: -, in: GET /content-negotiation /organization, errout: -, out: one of(status code (200) {body as application/xml (UTF-8)}|status code (200) {body as application/json (UTF-8)})) takes first content type when no accepts header
✅ ServerEndpoint(securityin: -, in: GET /, errout: -, out: -) accepts header without output body
✅ ServerEndpoint[echo byte array](securityin: -, in: POST /api /echo {body as application/octet-stream}, errout: -, out: {body as application/octet-stream}) not take into account the accept charset header when the body media type doesn't specify one
✅ ServerEndpoint(securityin: -, in: GET /content-negotiation /organization-parameters, errout: -, out: one of({body as application/json (UTF-8)}|{body as application/json; name=unknown (UTF-8)})) matches content type on accept parameters
✅ ServerEndpoint(securityin: -, in: GET /content-negotiation /multipart-mixed multipart/mixed -> {body as text/plain (UTF-8)}, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint[echo file](securityin: -, in: POST /api /echo {body as application/octet-stream}, errout: -, out: {body as application/octet-stream})
✅ ServerEndpoint[mapped query](securityin: -, in: ?fruit, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint[mapped path](securityin: -, in: /fruit /[], errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint[mapped path path](securityin: -, in: /fruit /[] /amount /[], errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint[query and mapped path path](securityin: -, in: /fruit /[] /amount /[] ?color, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint[out mapped](securityin: -, in: ?fruit, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint[out mapped](securityin: -, in: ?fruit, errout: -, out: {body as text/plain (UTF-8)} {header X-Role})
✅ ServerEndpoint(securityin: -, in: {header A: 1} {header X}, errout: -, out: {header B: 2} {header Y})
✅ ServerEndpoint(securityin: -, in: ?a ?b ?x ?y, errout: -, out: {header A} {header B} {header X} {header Y})
✅ ServerEndpoint(securityin: -, in: ?p1 ?p2 ?p3, errout: -, out: {header P1} {header P2} {header P3})
✅ ServerEndpoint[mapped to unit](securityin: -, in: ?p1 ?p2, errout: -, out: {header P1} {header P2})
✅ ServerEndpoint[metrics](securityin: -, in: POST /api /echo {body as application/json (UTF-8)}, errout: -, out: {body as application/json (UTF-8)})
✅ ServerEndpoint[metrics](securityin: -, in: POST /api /echo {body as application/octet-stream}, errout: -, out: {body as application/octet-stream})
✅ ServerEndpoint[metrics](securityin: -, in: GET /, errout: -, out: -)
✅ ServerEndpoint[metrics on exception](securityin: -, in: GET /, errout: -, out: -)
✅ ServerEndpoint(securityin: -, in: ?fruit, errout: -, out: one of(status code (202) {body as text/plain (UTF-8)}|status code (200) {body as text/plain (UTF-8)}))
✅ ServerEndpoint(securityin: -, in: /mapping ?num, errout: -, out: one of(status code (202) {body as text/plain (UTF-8)}|status code (200) {body as text/plain (UTF-8)}))
✅ ServerEndpoint(securityin: -, in: ?fruit, errout: -, out: one of(status code (202)|status code (200) {body as text/plain (UTF-8)}))
✅ ServerEndpoint(securityin: -, in: GET /entity /[type], errout: -, out: one of(status code (201) {body as application/json (UTF-8)}|{body as application/json (UTF-8)}))
✅ ServerEndpoint(securityin: -, in: ?fruit, errout: -, out: one of(status code (204)|status code (202) {body as application/json (UTF-8)}|status code (200) {body as application/json (UTF-8)}))
✅ ServerEndpoint(securityin: -, in: ?fruit, errout: {body as application/json (UTF-8)}, out: -)
✅ ServerEndpoint(securityin: {header token}, in: ?y, errout: {body as application/json (UTF-8)}, out: {body as text/plain (UTF-8)}) security error outputs extended with additional variants in main logic
✅ ServerEndpoint(securityin: -, in: /status ?statusOut, errout: -, out: one of(status code (404)|status code (400) {body as application/json (UTF-8)}))
✅ ServerEndpoint(securityin: -, in: /test, errout: one of(status code (409) {body as application/json (UTF-8)}|status code (404) {body as application/json (UTF-8)}|status code (500) {body as application/json (UTF-8)}), out: {body as text/plain (UTF-8)}) .errorOutVariantsPrepend variant takes precedence over devault .errorOut variant
✅ ServerEndpoint(securityin: -, in: /test, errout: one of(status code (400) {body as application/json (UTF-8)}|one of(status code (409) {body as application/json (UTF-8)}|status code (404) {body as application/json (UTF-8)}|status code (500) {body as application/json (UTF-8)})), out: {body as text/plain (UTF-8)}) multiple .errorOutVariantsPrepend variants are executed in right order (a stack)
✅ ServerEndpoint(securityin: -, in: /mapping ?num, errout: -, out: one of(status code (202)|status code (200)))
✅ given a list of endpoints, should return 405 for unsupported methods
✅ given a list of endpoints with different paths, should return 405 for unsupported methods
✅ given a list of endpoints and a customized reject handler, should return a custom response for unsupported methods
✅ ServerEndpoint(securityin: -, in: /path, errout: -, out: -) should return 404 for an unknown endpoint
✅ ServerEndpoint(securityin: -, in: GET /path, errout: -, out: -) should return 404 for an unsupported method, when a single endpoint is interpreted
✅ ServerEndpoint(securityin: -, in: ?fruit(~apple|banana), errout: -, out: -) support query validation with tagged type
✅ ServerEndpoint(securityin: -, in: ?amount(>=0), errout: -, out: -) support query validation
✅ ServerEndpoint(securityin: -, in: {body as application/json (UTF-8)}(fruit->(length>=4),amount->(>=1)), errout: -, out: -) support jsonBody validation with wrapped type
✅ ServerEndpoint(securityin: -, in: ?amount(>=1), errout: -, out: -) support query validation with wrapper type
✅ ServerEndpoint(securityin: -, in: {body as application/json (UTF-8)}(fruits->(size>=1,elements(fruit->(length>=4),amount->(>=1)))), errout: -, out: -) support jsonBody validation with list of wrapped type
✅ ServerEndpoint(securityin: -, in: POST one of({body as application/json (UTF-8)}|{body as application/xml (UTF-8)}|{body as text/plain (UTF-8)}), errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: -, in: POST one of({body as application/json (UTF-8)}|text/* -> {body as text/plain (UTF-8)}), errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: -, in: POST {body as text/plain (UTF-8)}, errout: -, out: one of({body as application/json (UTF-8)}|{body as application/xml (UTF-8)}|{body as text/plain (UTF-8)}))
✅ ServerEndpoint(securityin: -, in: OPTIONS /path, errout: -, out: {body as text/plain (UTF-8)}) CORS with default config; valid preflight request
✅ ServerEndpoint(securityin: -, in: OPTIONS /path, errout: -, out: -) CORS with specific allowed origin, method, headers, allowed credentials and max age; preflight request with matching origin, method and headers
✅ ServerEndpoint(securityin: -, in: OPTIONS /path, errout: -, out: -) CORS with multiple allowed origins, method, headers, allowed credentials and max age; preflight request with matching origin, method and headers
✅ ServerEndpoint(securityin: -, in: OPTIONS /path, errout: -, out: -) CORS with specific allowed origin; preflight request with unsupported origin
✅ ServerEndpoint(securityin: -, in: OPTIONS /path, errout: -, out: -) CORS with multiple allowed origins; preflight request with unsupported origin
✅ ServerEndpoint(securityin: -, in: OPTIONS /path, errout: -, out: -) CORS with specific allowed method; preflight request with unsupported method
✅ ServerEndpoint(securityin: -, in: OPTIONS /path, errout: -, out: -) CORS with specific allowed headers; preflight request with unsupported header
✅ ServerEndpoint(securityin: -, in: OPTIONS /path, errout: -, out: -) CORS with reflected allowed headers; preflight request
✅ ServerEndpoint(securityin: -, in: OPTIONS /path, errout: -, out: -) CORS with custom response code for preflight requests; valid preflight request
✅ ServerEndpoint(securityin: -, in: OPTIONS /path, errout: -, out: -) CORS with default config; preflight request without Origin (non-CORS)
✅ ServerEndpoint(securityin: -, in: GET /path, errout: -, out: {body as text/plain (UTF-8)}) CORS with default config; valid CORS request
✅ ServerEndpoint(securityin: -, in: GET /path, errout: -, out: {body as text/plain (UTF-8)}) CORS with custom allowed origin, allowed credentials and exposed headers; valid CORS request
✅ ServerEndpoint(securityin: -, in: GET /path, errout: -, out: {body as text/plain (UTF-8)}) CORS with all headers exposed; valid CORS request
✅ returns tapir-generated 404 when defaultHandlers(notFoundWhenRejected = true) is used
✅ Log events with provided functions, skipping certain endpoints
✅ ServerEndpoint(securityin: -, in: -, errout: -, out: {body as text/plain (UTF-8)}) Server waits for long-running request to complete within timeout
✅ ServerEndpoint(securityin: -, in: -, errout: -, out: {body as text/plain (UTF-8)}) Server rejects requests with 503 during shutdown
✅ ServerEndpoint(securityin: -, in: -, errout: -, out: {body as web socket}) string client-terminated echo
✅ ServerEndpoint(securityin: -, in: /elsewhere, errout: -, out: {body as text/plain (UTF-8)}) WS handshake to a non-existing endpoint
✅ ServerEndpoint[metrics](securityin: -, in: -, errout: -, out: {body as web socket})
✅ ServerEndpoint(securityin: -, in: -, errout: -, out: {body as web socket}) json client-terminated echo
✅ ServerEndpoint(securityin: -, in: -, errout: -, out: {body as web socket}) string server-terminated echo
✅ ServerEndpoint(securityin: -, in: -, errout: -, out: {body as web socket}) pong on ping
✅ ServerEndpoint(securityin: -, in: -, errout: -, out: {body as web socket}) empty client stream
✅ ServerEndpoint(securityin: -, in: ?securityToken, errout: {body as text/plain (UTF-8)}, out: {body as web socket}) switch to WS after a normal HTTP request
✅ ServerEndpoint(securityin: -, in: ?securityToken, errout: {body as text/plain (UTF-8)}, out: {body as web socket}) reject WS handshake, then accept a corrected one
✅ ServerEndpoint(securityin: -, in: -, errout: -, out: {body as web socket}) auto ping
✅ ServerEndpoint(securityin: -, in: -, errout: -, out: {body as web socket}) failing pipe
✅ ServerEndpoint(securityin: -, in: -, errout: -, out: {body as web socket}) not pong on ping if disabled
✅ ServerEndpoint(securityin: -, in: -, errout: -, out: {body as web socket}) not ignore pong
✅ ServerEndpoint(securityin: -, in: -, errout: -, out: {body as web socket}) concatenate fragmented text frames
✅ ServerEndpoint(securityin: -, in: -, errout: -, out: {body as web socket}) concatenate fragmented binary frames
✅ properly update metrics when a request times out

✅ server/nima-server/target/jvm-3/test-reports/TEST-sttp.tapir.server.nima.NimaServerTest.xml

196 tests were completed in 5s with 196 passed, 0 failed and 0 skipped.

Test suite Passed Failed Skipped Time
sttp.tapir.server.nima.NimaServerTest 196✅ 5s

✅ sttp.tapir.server.nima.NimaServerTest

✅ Endpoint(securityin: -, in: ?fruit, errout: -, out: {body as text/plain (UTF-8)})
✅ Endpoint(securityin: -, in: ?fruit, errout: -, out: {body as text/plain (UTF-8)}) with URL encoding
✅ Endpoint[infallible](securityin: -, in: ?fruit, errout: void, out: {body as text/plain (UTF-8)})
✅ Endpoint(securityin: -, in: ?fruit ?amount, errout: -, out: {body as text/plain (UTF-8)})
✅ Endpoint(securityin: -, in: {header X-Role}, errout: -, out: {body as text/plain (UTF-8)})
✅ Endpoint(securityin: -, in: /fruit /[] /amount /[], errout: -, out: {body as text/plain (UTF-8)})
✅ Endpoint(securityin: -, in: /fruit /[] /amount /[], errout: -, out: {body as text/plain (UTF-8)}) with URL encoding
✅ Endpoint(securityin: -, in: GET /api /[], errout: -, out: -) Empty path should not be passed to path capture decoding
✅ Endpoint(securityin: -, in: /in /[] /[], errout: -, out: {header a} {header b}) capturing two path parameters with the same specification
✅ Endpoint(securityin: -, in: POST /api /echo {body as text/plain (UTF-8)}, errout: -, out: {body as text/plain (UTF-8)})
✅ Endpoint(securityin: -, in: POST /api /echo {body as text/plain (UTF-8)}, errout: -, out: {body as text/plain (UTF-8)}) with get method
✅ Endpoint(securityin: -, in: {header SomeHeader} /[], errout: -, out: {header IntHeader} {body as text/plain (UTF-8)}) Header input before path capture input
✅ Endpoint[echo json](securityin: -, in: POST /api /echo {body as application/json (UTF-8)}, errout: -, out: {body as application/json (UTF-8)})
✅ Endpoint[echo json](securityin: -, in: POST /api /echo {body as application/json (UTF-8)}, errout: -, out: {body as application/json (UTF-8)}) with accept header
✅ Endpoint[echo json](securityin: -, in: POST /api /echo {body as application/json (UTF-8)}, errout: -, out: {body as application/json (UTF-8)}) content type
✅ Endpoint[echo byte array](securityin: -, in: POST /api /echo {body as application/octet-stream}, errout: -, out: {body as application/octet-stream})
✅ Endpoint[echo byte buffer](securityin: -, in: POST /api /echo {body as application/octet-stream}, errout: -, out: {body as application/octet-stream})
✅ Endpoint(securityin: -, in: /api /unit, errout: -, out: {body as application/json (UTF-8)}) unit json mapper
✅ Endpoint(securityin: -, in: /api, errout: -, out: {body as text/plain (UTF-8)}) default status mapper
✅ Endpoint(securityin: -, in: /api, errout: {body as text/plain (UTF-8)}, out: -) default error status mapper
✅ Endpoint(securityin: -, in: POST /api /echo {body as application/x-www-form-urlencoded (UTF-8)}, errout: -, out: {body as application/x-www-form-urlencoded (UTF-8)})
✅ Endpoint(securityin: -, in: GET /api /echo /params ?*, errout: -, out: {body as text/plain (UTF-8)})
✅ Endpoint(securityin: -, in: GET /[pathParam] ?*, errout: -, out: {body as text/plain (UTF-8)})
✅ Endpoint(securityin: -, in: GET /api /echo /params ?*, errout: -, out: {body as text/plain (UTF-8)}) should support value-less query param
✅ Endpoint(securityin: -, in: GET /api /echo /headers {multiple headers}, errout: -, out: {multiple headers})
✅ Endpoint(securityin: -, in: GET /*, errout: -, out: {body as text/plain (UTF-8)})
✅ Endpoint(securityin: -, in: GET /*, errout: -, out: {body as text/plain (UTF-8)}) paths should match empty path
✅ Endpoint(securityin: -, in: ?fruit, errout: -, out: {body as text/plain (UTF-8)}) invalid query parameter
✅ Endpoint(securityin: -, in: GET /api /echo /param-to-header ?qq, errout: -, out: {header hh})
✅ Endpoint(securityin: -, in: GET /api /echo /headers {header Cookie}, errout: -, out: {header Set-Cookie})
✅ ServerEndpoint(securityin: -, in: /cookies-test GET, errout: -, out: {header Set-Cookie}) should not fold multiple Set-Cookie headers
✅ Endpoint(securityin: -, in: GET / ?q, errout: -, out: {header Set-Cookie} {body as text/plain (UTF-8)}) should be invulnerable to response splitting from unsanitized headers
✅ Endpoint(securityin: -, in: GET /api /echo /headers {header Set-Cookie}, errout: -, out: {header Set-Cookie})
✅ Endpoint(securityin: -, in: /api /echo {body as text/plain (UTF-8)}, errout: -, out: {body as text/plain (UTF-8)} {header Content-Type}) dynamic content type
✅ Endpoint(securityin: -, in: /api /echo {header Content-Type}, errout: -, out: {body as text/plain (UTF-8)})
✅ Endpoint(securityin: -, in: POST /api /echo {header Content-Type: application/json}, errout: -, out: -) mismatch content-type
✅ Endpoint(securityin: -, in: POST /api /echo {header Content-Type: application/json}, errout: -, out: -) missing content-type
✅ Endpoint(securityin: -, in: POST /api /echo {header Content-Type}, errout: -, out: -) mismatch content-type
✅ Endpoint(securityin: -, in: POST /api /echo {header Content-Type}, errout: -, out: -) missing content-type
✅ Endpoint(securityin: -, in: /api /echo, errout: -, out: {body as text/html (UTF-8)})
✅ Endpoint(securityin: -, in: -, errout: -, out: status code (308) {header Location})
✅ Endpoint(securityin: -, in: -, errout: -, out: {header Location: Poland})
✅ Endpoint(securityin: -, in: POST /api /echo {body as application/json (UTF-8)}, errout: -, out: {body as application/json (UTF-8)})
✅ Endpoint(securityin: -, in: ?fruit, errout: -, out: status code - possible codes (Map())) custom status code
✅ Endpoint(securityin: -, in: {data from request}, errout: -, out: {body as text/plain (UTF-8)})
✅ Endpoint(securityin: -, in: ?fruit, errout: -, out: status code - possible codes (Map()))
✅ Endpoint[Query with default](securityin: -, in: ?p1, errout: -, out: {body as text/plain (UTF-8)})
✅ Endpoint(securityin: -, in: /api {header Content-Type: multipart/form-data}, errout: -, out: {body as text/plain (UTF-8)}) fixed multipart/form-data header input should ignore boundary directive
✅ Endpoint(securityin: -, in: ?kind, errout: -, out: {header Content-Type})
✅ Endpoint(securityin: -, in: ?kind, errout: -, out: {header Content-Type} {body as text/plain (UTF-8)})
✅ Endpoint(securityin: -, in: POST /api /echo {body as application/json (UTF-8)}, errout: -, out: {body as text/plain (UTF-8)})
✅ Endpoint(securityin: -, in: GET ?flag, errout: -, out: {body as text/plain (UTF-8)})
✅ Endpoint(securityin: -, in: ?fruit, errout: -, out: {body as text/plain (UTF-8)}) should contain the content-length header
✅ Endpoint(securityin: -, in: -, errout: -, out: -) GET empty endpoint
✅ Endpoint(securityin: -, in: -, errout: -, out: -) POST empty endpoint
✅ Endpoint(securityin: -, in: -, errout: -, out: {body as text/plain (UTF-8)} {header Content-Type: text/csv}) Fixed content-type header
✅ Endpoint(securityin: -, in: GET, errout: -, out: -) GET a GET endpoint
✅ Endpoint(securityin: -, in: GET, errout: -, out: -) POST a GET endpoint
✅ Endpoint(securityin: -, in: -, errout: -, out: -) no path should match anything
✅ Endpoint(securityin: -, in: GET /, errout: -, out: -) root path should not match non-root path
✅ Endpoint(securityin: -, in: GET /, errout: -, out: -) root path should match empty path
✅ Endpoint(securityin: -, in: GET /, errout: -, out: -) root path should match root path
✅ Endpoint(securityin: -, in: GET /api, errout: -, out: -) single path should match single path
✅ Endpoint(securityin: -, in: GET /api, errout: -, out: -) single path should match single/ path
✅ Endpoint(securityin: -, in: GET /api /[] /and /*, errout: -, out: {header IntPath} {body as text/plain (UTF-8)}) Capturing paths after path capture
✅ Endpoint(securityin: -, in: GET /api /[] /and /*, errout: -, out: {header IntPath} {body as text/plain (UTF-8)}) Capturing paths after path capture (when empty)
✅ Endpoint(securityin: -, in: GET /api, errout: -, out: -) single path should not match root path
✅ Endpoint(securityin: -, in: GET /api, errout: -, out: -) single path should not match larger path
✅ ServerEndpoint(securityin: /auth, in: /settings, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: /auth, in: -, errout: -, out: {body as text/plain (UTF-8)})
✅ two endpoints with increasingly specific path inputs: should match path exactly
✅ two endpoints with increasingly specific path inputs (w/ path capture): should match path exactly
✅ two endpoints with decreasingly specific path inputs: should match path exactly
✅ two endpoints with a body defined as the first input: should only consume body when the path matches
✅ two endpoints with query defined as the first input, path segments as second input: should try the second endpoint if the path doesn't match
✅ two endpoints with increasingly specific path inputs, first with a required query parameter: should match path exactly
✅ two endpoints with validation: should not try the second one if validation fails
✅ endpoint with a security input and regular path input shouldn't shadow other endpoints
✅ two endpoints, same path prefix, one without trailing slashes, second accepting trailing slashes
✅ try other paths on decode failure if onDecodeFailureNextEndpoint
✅ two endpoints with different methods, first one with path parsing
✅ two endpoints with fixed path & path capture as the middle component
✅ two endpoints with fixed path & path capture as the middle component, different methods
✅ Endpoint(securityin: -, in: GET /customer /[customer_id] /orders /[order_id], errout: -, out: -) Returns 400 if path 'shape' matches, but failed to parse a path parameter, using a custom decode failure handler
✅ Endpoint(securityin: -, in: GET /customer /[customer_id] /orders /[order_id], errout: -, out: -) Returns 404 if path 'shape' doesn't match
✅ Endpoint(securityin: -, in: GET /customer /[customer_id], errout: -, out: -) Returns 400 if path 'shape' matches, but failed to parse a path parameter
✅ Tries next endpoint if path 'shape' matches, but validation fails, using .onDecodeFailureNextEndpoint
✅ ServerEndpoint(securityin: ?x, in: ?y, errout: -, out: {body as text/plain (UTF-8)}) server security logic - one input
✅ ServerEndpoint(securityin: ?x ?y, in: ?z ?u, errout: -, out: {body as text/plain (UTF-8)}) server security logic - multiple inputs
✅ Endpoint[echo input stream](securityin: -, in: POST /api /echo {body as application/octet-stream}, errout: -, out: {body as application/octet-stream})
✅ Endpoint[input string output stream with header](securityin: -, in: POST /api /echo {body as text/plain (UTF-8)}, errout: -, out: {body as application/octet-stream} {header Content-Length})
✅ Endpoint(securityin: -, in: -, errout: -, out: -) handle exceptions
✅ recover errors from exceptions
✅ ServerEndpoint(securityin: /auth auth(api key, via {header X-Api-Key}), in: -, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: /auth auth(api key, via {header X-Api-Key}), in: ?amount, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: /auth auth(api key, via ?api-key), in: -, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: /auth auth(Basic http, via {header Authorization}), in: -, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: /auth auth(Bearer http, via {header Authorization}), in: -, errout: -, out: {body as text/plain (UTF-8)})
✅ ServerEndpoint(securityin: /auth auth(Basic http, via {header Authorization}), in: -, errout: -, out: {body as text/plain (UTF-8)}) In security Option[UsernamePassword] should let in basic auth as well as request without auth
✅ ServerEndpoint(securityin: /auth auth(Basic http, via {header Authorization}) auth(Bearer http, via {header Authorization}), in: -, errout: -, out: {body as text/plain (UTF-8)}) In security (Option[UsernamePassword], Option[String]) should pass bearer auth, basic auth, and also request without auth
✅ ServerEndpoint(securityin: /secret /[id] auth(Basic http, via {header Authorization}), in: POST ?q, errout: -, out: -) correct basic
✅ ServerEndpoint(securityin: /secret /[id] auth(Bearer http, via {header Authorization}), in: POST ?q, errout: -, out: -) correct bearer
✅ ServerEndpoint(securityin: /secret /[id] auth(Bearer http, via {header Authorization}), in: POST ?q, errout: -, out: -) correct lower case bearer
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via ?token), in: POST ?q, errout: -, out: -) correct apiKey in query param
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header x-api-key}), in: POST ?q, errout: -, out: -) correct apiKey in header
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header token-old}) auth(api key, via {header token-new}), in: POST ?q, errout: -, out: -) correct old token in header
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header token-old}) auth(api key, via {header token-new}), in: POST ?q, errout: -, out: -) correct new token in header
✅ ServerEndpoint(securityin: /secret /[id] auth(Basic http, via {header Authorization}), in: POST ?q, errout: -, out: -) missing basic
✅ ServerEndpoint(securityin: /secret /[id] auth(Bearer http, via {header Authorization}), in: POST ?q, errout: -, out: -) missing bearer
✅ ServerEndpoint(securityin: /secret /[id] auth(Bearer http, via {header Authorization}), in: POST ?q, errout: -, out: -) missing lower case bearer
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via ?token), in: POST ?q, errout: -, out: -) missing apiKey in query param
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header x-api-key}), in: POST ?q, errout: -, out: -) missing apiKey in header
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header token-old}) auth(api key, via {header token-new}), in: POST ?q, errout: -, out: -) missing old token in header
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header token-old}) auth(api key, via {header token-new}), in: POST ?q, errout: -, out: -) missing new token in header
✅ ServerEndpoint(securityin: /secret /[id] auth(Basic http, via {header Authorization}), in: POST ?q, errout: -, out: -) missing basic with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(Bearer http, via {header Authorization}), in: POST ?q, errout: -, out: -) missing bearer with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(Bearer http, via {header Authorization}), in: POST ?q, errout: -, out: -) missing lower case bearer with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via ?token), in: POST ?q, errout: -, out: -) missing apiKey in query param with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header x-api-key}), in: POST ?q, errout: -, out: -) missing apiKey in header with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header token-old}) auth(api key, via {header token-new}), in: POST ?q, errout: -, out: -) missing old token in header with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header token-old}) auth(api key, via {header token-new}), in: POST ?q, errout: -, out: -) missing new token in header with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(Basic http, via {header Authorization}), in: POST ?q, errout: -, out: -) invalid request basic
✅ ServerEndpoint(securityin: /secret /[id] auth(Bearer http, via {header Authorization}), in: POST ?q, errout: -, out: -) invalid request bearer
✅ ServerEndpoint(securityin: /secret /[id] auth(Bearer http, via {header Authorization}), in: POST ?q, errout: -, out: -) invalid request lower case bearer
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via ?token), in: POST ?q, errout: -, out: -) invalid request apiKey in query param
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header x-api-key}), in: POST ?q, errout: -, out: -) invalid request apiKey in header
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header token-old}) auth(api key, via {header token-new}), in: POST ?q, errout: -, out: -) invalid request old token in header
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header token-old}) auth(api key, via {header token-new}), in: POST ?q, errout: -, out: -) invalid request new token in header
✅ ServerEndpoint(securityin: /secret /[id] auth(Basic http, via {header Authorization}), in: POST ?q, errout: -, out: -) invalid request basic with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(Bearer http, via {header Authorization}), in: POST ?q, errout: -, out: -) invalid request bearer with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(Bearer http, via {header Authorization}), in: POST ?q, errout: -, out: -) invalid request lower case bearer with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via ?token), in: POST ?q, errout: -, out: -) invalid request apiKey in query param with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header x-api-key}), in: POST ?q, errout: -, out: -) invalid request apiKey in header with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header token-old}) auth(api key, via {header token-new}), in: POST ?q, errout: -, out: -) invalid request old token in header with endpoint hiding
✅ ServerEndpoint(securityin: /secret /[id] auth(api key, via {header token-old}) auth(api key, via {header token-new}), in: POST ?q, errout: -, out: -) invalid request new token in header with endpoint hiding
✅ Endpoint(securityin: -, in: GET /content-negotiation /organization {header Accept}, errout: -, out: one of(status code (200) {body as application/json (UTF-8)}|status code (200) {body as application/xml (UTF-8)}|status code (200) {body as text/html (UTF-8)}|status code (200) {body as text/html (ISO-8859-1)}))
✅ Endpoint(securityin: -, in: GET /content-negotiation /organization, errout: -, out: one of(status code (200) {body as application/json (UTF-8)}|status code (200) {body as application/xml (UTF-8)})) takes first content type when no accepts header
✅ Endpoint(securityin: -, in: GET /content-negotiation /organization, errout: -, out: one of(status code (200) {body as application/xml (UTF-8)}|status code (200) {body as application/json (UTF-8)})) takes first content type when no accepts header
✅ Endpoint(securityin: -, in: GET /, errout: -, out: -) accepts header without output body
✅ Endpoint[echo byte array](securityin: -, in: POST /api /echo {body as application/octet-stream}, errout: -, out: {body as application/octet-stream}) not take into account the accept charset header when the body media type doesn't specify one
✅ Endpoint(securityin: -, in: GET /content-negotiation /organization-parameters, errout: -, out: one of({body as application/json (UTF-8)}|{body as application/json; name=unknown (UTF-8)})) matches content type on accept parameters
✅ Endpoint(securityin: -, in: GET /content-negotiation /multipart-mixed multipart/mixed -> {body as text/plain (UTF-8)}, errout: -, out: {body as text/plain (UTF-8)})
✅ Endpoint[echo file](securityin: -, in: POST /api /echo {body as application/octet-stream}, errout: -, out: {body as application/octet-stream})
✅ Endpoint[mapped query](securityin: -, in: ?fruit, errout: -, out: {body as text/plain (UTF-8)})
✅ Endpoint[mapped path](securityin: -, in: /fruit /[], errout: -, out: {body as text/plain (UTF-8)})
✅ Endpoint[mapped path path](securityin: -, in: /fruit /[] /amount /[], errout: -, out: {body as text/plain (UTF-8)})
✅ Endpoint[query and mapped path path](securityin: -, in: /fruit /[] /amount /[] ?color, errout: -, out: {body as text/plain (UTF-8)})
✅ Endpoint[out mapped](securityin: -, in: ?fruit, errout: -, out: {body as text/plain (UTF-8)})
✅ Endpoint[out mapped](securityin: -, in: ?fruit, errout: -, out: {body as text/plain (UTF-8)} {header X-Role})
✅ Endpoint(securityin: -, in: {header A: 1} {header X}, errout: -, out: {header B: 2} {header Y})
✅ Endpoint(securityin: -, in: ?a ?b ?x ?y, errout: -, out: {header A} {header B} {header X} {header Y})
✅ Endpoint(securityin: -, in: ?p1 ?p2 ?p3, errout: -, out: {header P1} {header P2} {header P3})
✅ Endpoint[mapped to unit](securityin: -, in: ?p1 ?p2, errout: -, out: {header P1} {header P2})
✅ Endpoint[metrics](securityin: -, in: POST /api /echo {body as application/json (UTF-8)}, errout: -, out: {body as application/json (UTF-8)})
✅ Endpoint[metrics](securityin: -, in: POST /api /echo {body as application/octet-stream}, errout: -, out: {body as application/octet-stream})
✅ Endpoint[metrics](securityin: -, in: GET /, errout: -, out: -)
✅ Endpoint[metrics on exception](securityin: -, in: GET /, errout: -, out: -)
✅ Endpoint(securityin: -, in: ?fruit, errout: -, out: one of(status code (202) {body as text/plain (UTF-8)}|status code (200) {body as text/plain (UTF-8)}))
✅ Endpoint(securityin: -, in: /mapping ?num, errout: -, out: one of(status code (202) {body as text/plain (UTF-8)}|status code (200) {body as text/plain (UTF-8)}))
✅ Endpoint(securityin: -, in: ?fruit, errout: -, out: one of(status code (202)|status code (200) {body as text/plain (UTF-8)}))
✅ Endpoint(securityin: -, in: GET /entity /[type], errout: -, out: one of(status code (201) {body as application/json (UTF-8)}|{body as application/json (UTF-8)}))
✅ Endpoint(securityin: -, in: ?fruit, errout: -, out: one of(status code (204)|status code (202) {body as application/json (UTF-8)}|status code (200) {body as application/json (UTF-8)}))
✅ Endpoint(securityin: -, in: ?fruit, errout: {body as application/json (UTF-8)}, out: -)
✅ ServerEndpoint(securityin: {header token}, in: ?y, errout: {body as application/json (UTF-8)}, out: {body as text/plain (UTF-8)}) security error outputs extended with additional variants in main logic
✅ Endpoint(securityin: -, in: /status ?statusOut, errout: -, out: one of(status code (404)|status code (400) {body as application/json (UTF-8)}))
✅ ServerEndpoint(securityin: -, in: /test, errout: one of(status code (409) {body as application/json (UTF-8)}|status code (404) {body as application/json (UTF-8)}|status code (500) {body as application/json (UTF-8)}), out: {body as text/plain (UTF-8)}) .errorOutVariantsPrepend variant takes precedence over devault .errorOut variant
✅ ServerEndpoint(securityin: -, in: /test, errout: one of(status code (400) {body as application/json (UTF-8)}|one of(status code (409) {body as application/json (UTF-8)}|status code (404) {body as application/json (UTF-8)}|status code (500) {body as application/json (UTF-8)})), out: {body as text/plain (UTF-8)}) multiple .errorOutVariantsPrepend variants are executed in right order (a stack)
✅ Endpoint(securityin: -, in: /mapping ?num, errout: -, out: one of(status code (202)|status code (200)))
✅ given a list of endpoints, should return 405 for unsupported methods
✅ given a list of endpoints with different paths, should return 405 for unsupported methods
✅ given a list of endpoints and a customized reject handler, should return a custom response for unsupported methods
✅ Endpoint(securityin: -, in: /path, errout: -, out: -) should return 404 for an unknown endpoint
✅ Endpoint(securityin: -, in: GET /path, errout: -, out: -) should return 404 for an unsupported method, when a single endpoint is interpreted
✅ Endpoint(securityin: -, in: ?fruit(~apple|banana), errout: -, out: -) support query validation with tagged type
✅ Endpoint(securityin: -, in: ?amount(>=0), errout: -, out: -) support query validation
✅ Endpoint(securityin: -, in: {body as application/json (UTF-8)}(fruit->(length>=4),amount->(>=1)), errout: -, out: -) support jsonBody validation with wrapped type
✅ Endpoint(securityin: -, in: ?amount(>=1), errout: -, out: -) support query validation with wrapper type
✅ Endpoint(securityin: -, in: {body as application/json (UTF-8)}(fruits->(size>=1,elements(fruit->(length>=4),amount->(>=1)))), errout: -, out: -) support jsonBody validation with list of wrapped type
✅ Endpoint(securityin: -, in: POST one of({body as application/json (UTF-8)}|{body as application/xml (UTF-8)}|{body as text/plain (UTF-8)}), errout: -, out: {body as text/plain (UTF-8)})
✅ Endpoint(securityin: -, in: POST one of({body as application/json (UTF-8)}|text/* -> {body as text/plain (UTF-8)}), errout: -, out: {body as text/plain (UTF-8)})
✅ Endpoint(securityin: -, in: POST {body as text/plain (UTF-8)}, errout: -, out: one of({body as application/json (UTF-8)}|{body as application/xml (UTF-8)}|{body as text/plain (UTF-8)}))
✅ Endpoint(securityin: -, in: OPTIONS /path, errout: -, out: {body as text/plain (UTF-8)}) CORS with default config; valid preflight request
✅ Endpoint(securityin: -, in: OPTIONS /path, errout: -, out: -) CORS with specific allowed origin, method, headers, allowed credentials and max age; preflight request with matching origin, method and headers
✅ Endpoint(securityin: -, in: OPTIONS /path, errout: -, out: -) CORS with multiple allowed origins, method, headers, allowed credentials and max age; preflight request with matching origin, method and headers
✅ Endpoint(securityin: -, in: OPTIONS /path, errout: -, out: -) CORS with specific allowed origin; preflight request with unsupported origin
✅ Endpoint(securityin: -, in: OPTIONS /path, errout: -, out: -) CORS with multiple allowed origins; preflight request with unsupported origin
✅ Endpoint(securityin: -, in: OPTIONS /path, errout: -, out: -) CORS with specific allowed method; preflight request with unsupported method
✅ Endpoint(securityin: -, in: OPTIONS /path, errout: -, out: -) CORS with specific allowed headers; preflight request with unsupported header
✅ Endpoint(securityin: -, in: OPTIONS /path, errout: -, out: -) CORS with reflected allowed headers; preflight request
✅ Endpoint(securityin: -, in: OPTIONS /path, errout: -, out: -) CORS with custom response code for preflight requests; valid preflight request
✅ Endpoint(securityin: -, in: OPTIONS /path, errout: -, out: -) CORS with default config; preflight request without Origin (non-CORS)
✅ Endpoint(securityin: -, in: GET /path, errout: -, out: {body as text/plain (UTF-8)}) CORS with default config; valid CORS request
✅ Endpoint(securityin: -, in: GET /path, errout: -, out: {body as text/plain (UTF-8)}) CORS with custom allowed origin, allowed credentials and exposed headers; valid CORS request
✅ Endpoint(securityin: -, in: GET /path, errout: -, out: {body as text/plain (UTF-8)}) CORS with all headers exposed; valid CORS request
✅ returns tapir-generated 404 when defaultHandlers(notFoundWhenRejected = true) is used
✅ Log events with provided functions, skipping certain endpoints