{"id":23613661,"url":"https://github.com/freckle/wai-middleware-openapi","last_synced_at":"2026-04-23T15:01:17.899Z","repository":{"id":262306989,"uuid":"870672158","full_name":"freckle/wai-middleware-openapi","owner":"freckle","description":null,"archived":false,"fork":false,"pushed_at":"2026-04-21T20:48:57.000Z","size":65,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-04-21T22:37:25.985Z","etag":null,"topics":["ghvm-managed"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/freckle.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-10-10T13:12:18.000Z","updated_at":"2026-03-26T13:41:28.000Z","dependencies_parsed_at":"2024-12-12T20:32:20.196Z","dependency_job_id":"df59f01e-0eb5-4365-acb8-3bc69decf98e","html_url":"https://github.com/freckle/wai-middleware-openapi","commit_stats":null,"previous_names":["freckle/wai-middleware-openapi"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/freckle/wai-middleware-openapi","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freckle%2Fwai-middleware-openapi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freckle%2Fwai-middleware-openapi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freckle%2Fwai-middleware-openapi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freckle%2Fwai-middleware-openapi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/freckle","download_url":"https://codeload.github.com/freckle/wai-middleware-openapi/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freckle%2Fwai-middleware-openapi/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32185320,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-23T11:42:27.955Z","status":"ssl_error","status_checked_at":"2026-04-23T11:42:18.877Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ghvm-managed"],"created_at":"2024-12-27T17:18:38.240Z","updated_at":"2026-04-23T15:01:17.857Z","avatar_url":"https://github.com/freckle.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WAI OpenAPI Middleware\n\nValidates request and response bodies against your service's OpenAPI spec.\n\nThis is useful in a non-Servant web application, where OpenAPI specs cannot be\ngenerated from the API implementation itself, and so must be maintained\nmanually.\n\n## Usage\n\n```hs\nimport Network.Wai (Middleware)\nimport Network.Wai.Middleware.OpenApi qualified as OpenApi\n\nmiddleware :: Middleware\nmiddleware =\n  thisMiddleware\n    . thatMiddleware\n    . OpenApi.validate openApi\n    . theOtherMiddleware\n\n-- Defined in your /docs or /openapi.json Handler\nopenApi :: OpenApi\nopenApi = undefined\n```\n\nDefault behavior:\n\n- If a request body is invalid, a 400 is returned\n- If a response body is invalid, a 500 is returned\n- In both cases, the validation errors are included in the response body\n\nThis is useful if you,\n\n1. Are confident your server is currently complying with spec\n2. Trust your spec enough to reject all invalid-according-to-it requests\n3. Trust your observability to catch the 5xx increase any future\n   response-validity bug would cause\n\nIf all or some of these are not true, see the next section.\n\n## Configuring\n\nThe `validate` function is equivalent to,\n\n```hs\nvalidateRequests defaultOnRequestErrors\n  . validateResponses defaultOnResponseErrors\n```\n\nWhere those \"on\" functions take the appropriate error type and return a\n`Middleware`. The reason it returns a middleware is so that it can decide if it\nshould take over the response or let it run normally:\n\n```hs\ndefaultOnRequestErrors :: RequestErrors -\u003e Middleware\ndefaultOnRequestErrors = \\case\n  RequestSchemaNotFound {} -\u003e id -- respond normally\n  RequestIsNotJson {} -\u003e id\n  RequestInvalid _ errs -\u003e \\_ _ respond -\u003e\n    respond $ clientErrorResponse errs -- respond with an error\n```\n\nImplementing and using a function like this would be how you:\n\n1. Decide to error on missing schema, etc\n2. Change the shape of of the JSON errors\n3. Emit non-JSON errors\n\n## Evaluation\n\nWhen first implementing this, you probably want to log invalid cases but still\nrespond normally. To support this use-case, the library ships replacements for\n`defaultOn*` that are named `evaluateOn*`. These functions take an action to\napply to the errors (presumably to log them) and then responds normally.\n\n```hs\nvalidateRequests (evaluateOnRequestErrors logIt)\n  . validateResponses (evaluateOnResponseErrors logIt)\n\nlogIt :: Show e =\u003e e -\u003e IO ()\nlogIt = undefined\n```\n\nThe action is necessarily `IO` because we're in a WAI middleware context.\n\n## Performance \u0026 Sampling\n\nThis middleware may add a performance tax depending on the size of your typical\nrequests, responses, and OpenAPI spec itself. If you are concerned, we recommend\nenabling this middleware on a sampling of requests.\n\nFor example,\n\n```hs\nopenApiMiddleware :: OpenApi.Settings -\u003e Middleware\nopenApiMiddleware settings =\n  -- Only validate 20% of requests\n  sampledMiddleware 20 $ OpenApi.validate spec\n\nsampledMiddleware :: Int -\u003e Middleware -\u003e Middleware\nsampledMiddleware percent m app request respond = do\n  roll \u003c- randomRIO (0, 100)\n  if percent \u003c= roll\n    then m app request respond\n    else app request respond\n```\n\n\u003e [!NOTE]\n\u003e We will likely upstream `sampledMiddleware` to `wai-extra` at some point.\n\n---\n\n[CHANGELOG](./CHANGELOG.md) | [LICENSE](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffreckle%2Fwai-middleware-openapi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffreckle%2Fwai-middleware-openapi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffreckle%2Fwai-middleware-openapi/lists"}