{"id":32195698,"url":"https://github.com/zerg000000/simple-cors","last_synced_at":"2025-10-22T02:19:15.853Z","repository":{"id":62435274,"uuid":"311940018","full_name":"zerg000000/simple-cors","owner":"zerg000000","description":"Simply usable CORS middleware / interceptor for Clojure","archived":false,"fork":false,"pushed_at":"2023-06-27T02:52:14.000Z","size":75,"stargazers_count":28,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-27T22:30:49.118Z","etag":null,"topics":["clojure-ring","cors","reitit"],"latest_commit_sha":null,"homepage":"","language":"Clojure","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/zerg000000.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":["zerg000000"]}},"created_at":"2020-11-11T10:42:39.000Z","updated_at":"2023-10-20T19:43:53.000Z","dependencies_parsed_at":"2022-11-01T21:02:39.099Z","dependency_job_id":null,"html_url":"https://github.com/zerg000000/simple-cors","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/zerg000000/simple-cors","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerg000000%2Fsimple-cors","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerg000000%2Fsimple-cors/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerg000000%2Fsimple-cors/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerg000000%2Fsimple-cors/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zerg000000","download_url":"https://codeload.github.com/zerg000000/simple-cors/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerg000000%2Fsimple-cors/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280365627,"owners_count":26318388,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-22T02:00:06.515Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["clojure-ring","cors","reitit"],"created_at":"2025-10-22T02:19:10.831Z","updated_at":"2025-10-22T02:19:15.846Z","avatar_url":"https://github.com/zerg000000.png","language":"Clojure","readme":"# Simple CORS\n\n[![Clojars Project](https://img.shields.io/clojars/v/zerg000000/simple-cors.svg)](https://clojars.org/zerg000000/simple-cors)\n\nBare minimum CORS middleware/interceptor for Clojure.\n\n## Features\n\n* Provide just enough CORS required by [Browser](https://fetch.spec.whatwg.org/#cors-protocol).\n* Reasonable performance\n* Support Ring middleware / Reitit interceptor / Aleph middleware\n* Support all CORS features, especially `Access-Control-Max-Age`\n\n## Get Started\n\nAdd to your deps.edn\n\n```clojure\n{zerg000000/simple-cors {:mvn/version \"0.0.8\"}}\n```\n\nWhen use in [Ring](https://github.com/ring-clojure/ring) handler\n\n```clojure\n(require '[simple-cors.ring.middleware :as cors])\n\n(def app (cors/wrap handler {:cors-config {:allowed-request-methods [:post :get]\n                                           :allowed-request-headers [\"Authorization\" \"Content-Type\"]\n                                           :origins [\"https://yahoo.com\"\n                                                     \"https://google.com\"]\n                                           :max-age 300}}))\n```\n\nWhen use in [Reitit](https://github.com/metosin/reitit)\n\n```clojure\n(require '[simple-cors.reitit.interceptor :as cors]\n         '[reitit.interceptor.sieppari]\n         '[reitit.http :as http])\n\n(def app \n  (let [config {:cors-config {:allowed-request-methods [:post :get]\n                              :allowed-request-headers [\"Authorization\" \"Content-Type\"]\n                              :origins [\"https://yahoo.com\"\n                                        \"https://google.com\"]\n                              :max-age 300}}]\n    (http/ring-handler\n     (http/router routes\n                  {:reitit.http/default-options-endpoint \n                   (cors/make-default-options-endpoint config)})\n     {:executor reitit.interceptor.sieppari/executor\n      :interceptors [(cors/cors-interceptor config)]})))\n```\n\nWhen use in [Aleph](https://github.com/aleph-io/aleph)\n\n```clojure\n(require '[simple-cors.aleph.middleware :as cors])\n\n(def app (cors/wrap handler {:cors-config {:allowed-request-methods [:post :get]\n                                           :allowed-request-headers [\"Authorization\" \"Content-Type\"]\n                                           :origins [\"https://yahoo.com\"\n                                                     \"https://google.com\"]\n                                           :max-age 300}}))\n```\n\nFull config map, you can also see the spec in `simple-cors.specs`\n\n```clojure\n{:cors-config {:allowed-request-methods [:post :get]\n               :allowed-request-headers [\"Authorization\" \"Content-Type\"]\n               :allow-credentials? true\n               :origins [\"https://yahoo.com\"\n                         \"https://google.com\"]\n               :max-age 300\n               :exposed-headers [\"x-amz-date\"]}\n :preflight-forbidden-response {:status 403}\n :preflight-ok-response {:status 200}}\n```\n\n### Static / Any Origin / Fn CORS\n\nNormally, Static is good and enough\n\n```clojure\n{:cors-config {...\n               :origins [\"https://whatever.co\"]\n               ...}}\n```\n\nSome casual user might want CORS matched with any origin\n\n```clojure\n{:cors-config {...\n               :origins \"*\"\n               ...}}\n```\n\nThe ultimate solution is to provide your own matching function\n\n```clojure\n{:cors-config {...\n               :origins #{\"https://whatever.co\"}\n               ...}}\n; or\n{:cors-config {...\n               :origins (fn [origin] (and (str/starts-with? origin \"https://\")\n                                          (str/ends-with? origin \".google.com\")))\n               ...}}\n```\n\n### Combine Multiple Config\n\nSupport combining multiple CORS config with performance penalty.\nAt most one AnyOrigin in configs, and will act as the last fallback. \n\n```clojure\n{:cors-config [{...\n                :origin \"*\"\n                ...}\n               {...\n                :origin [\"http://abc\"]\n                ...}]}\n```\n\n## Why\n\n### Not checking or blocking invalid request\n\nSince the main idea of CORS is to provide information for a browser to take action.\nIn most of the cases, we can do little on pure server side\n\n## TODO\n\n- [ ] more tests\n- [ ] more docstring\n\n## Reference\n\n### Reference Doc\n\n* [whatwg](https://fetch.spec.whatwg.org/#cors-protocol)\n* [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)\n\n### Reference Implementation \n\n* [pedestal](https://github.com/pedestal/pedestal/blob/aa71a3a630dd21861c0682eeeebec762cbf3f85c/service/src/io/pedestal/http/cors.clj)\n* [nasus](https://github.com/kachayev/nasus/blob/371d60e08948c52c56ae1f0ac3f39f4105383aaf/src/http/server.clj#L317)\n* [netty](https://github.com/barchart/barchart-project-netty/blob/master/codec-http/src/main/java/io/netty/handler/codec/http/cors/CorsHandler.java)\n\n\n## License\n\nCopyright © 2020 Simple CORS\n\nSimple CORS is licensed under the MIT license, available at MIT and also in the LICENSE file.\n","funding_links":["https://github.com/sponsors/zerg000000"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzerg000000%2Fsimple-cors","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzerg000000%2Fsimple-cors","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzerg000000%2Fsimple-cors/lists"}