{"id":17871570,"url":"https://github.com/oteku/bs-cors","last_synced_at":"2025-07-21T23:33:32.532Z","repository":{"id":128105715,"uuid":"253011622","full_name":"oteku/bs-cors","owner":"oteku","description":"bs-cors is a Buckelscript binding to cors middleware","archived":false,"fork":false,"pushed_at":"2022-12-12T09:31:46.000Z","size":31,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-13T20:50:17.885Z","etag":null,"topics":["buckelscript-binding","cors","express","reasonml"],"latest_commit_sha":null,"homepage":null,"language":"Reason","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oteku.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-04-04T14:01:19.000Z","updated_at":"2021-12-15T11:04:57.000Z","dependencies_parsed_at":null,"dependency_job_id":"8729981a-6ced-4815-aaf8-104b1ca9e330","html_url":"https://github.com/oteku/bs-cors","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/oteku/bs-cors","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oteku%2Fbs-cors","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oteku%2Fbs-cors/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oteku%2Fbs-cors/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oteku%2Fbs-cors/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oteku","download_url":"https://codeload.github.com/oteku/bs-cors/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oteku%2Fbs-cors/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265636619,"owners_count":23802553,"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","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":["buckelscript-binding","cors","express","reasonml"],"created_at":"2024-10-28T10:35:18.555Z","updated_at":"2025-07-21T23:33:32.507Z","avatar_url":"https://github.com/oteku.png","language":"Reason","funding_links":[],"categories":[],"sub_categories":[],"readme":"# bs-cors\n\nbs-cors is a Buckelscript binding to [cors](https://github.com/expressjs/cors), made by [Troy Goode](https://twitter.com/intent/user?screen_name=troygoode), an expressjs middleware that can be used to enable [Cross-origin resource sharing](https://developer.mozilla.org/fr/docs/Web/HTTP/CORS) with various options.\n\n- [Installation](#installation)\n- [Usage](#usage)\n  - [Simple Usage](#simple-usage-enable-all-cors-requests)\n  - [Enable CORS for a Single Route](#enable-cors-for-a-single-route)\n  - [Configuring CORS](#configuring-cors)\n  - [Configuring CORS w/ Dynamic Origin](#configuring-cors-w-dynamic-origin)\n  - [Enabling CORS Pre-Flight](#enabling-cors-pre-flight)\n  - [Configuring CORS Asynchronously](#configuring-cors-asynchronously)\n- [Configuration Options](#configuration-options)\n- [License](#license)\n- [Author](#author)\n\n## Installation\n\nThis is a [Node.js](https://nodejs.org/en/) module available through the\n[npm registry](https://www.npmjs.com/). Installation is done using the\n[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):\n\n```sh\n$ npm install cors bs-cors\n```\n\nthen add it as a dependency to your **bs-config.json** :\n\n```\n...\n  \"bs-dependencies\": [\"bs-express\", \"bs-cors\", ...],\n...\n\n```\n\n## Usage\n\n### Simple Usage (Enable _All_ CORS Requests)\n\n```reasonml\nopen  Express;\nlet app = express();\n\nApp.use(app,Cors.cors());\n\n\nMiddleware.from((_next, _req) =\u003e {\n      [(\"msg\", Js.Json.string(\"This is CORS-enabled for only example.com !\"))]\n    |\u003e Js.Dict.fromList\n    |\u003e Js.Json.object_\n    |\u003e Response.sendJson\n})\n|\u003e App.get(app, ~path=\"/products/:id\");\n\nlet onListen = e =\u003e\n  switch (e) {\n  | exception (Js.Exn.Error(e)) =\u003e\n    (\n      switch (Js.Exn.message(e)) {\n      | None =\u003e \"UNKNOWN ERROR\"\n      | Some(msg) =\u003e msg\n      }\n    )\n    |\u003e Js.log;\n    Node.Process.exit(1);\n  | _ =\u003e \"CORS-enabled web server listening on port 8080\" |\u003e Js.log\n  };\n\nlet server = App.listen(app, ~port=8080, ~onListen, ());\n```\n\n### Enable CORS for a Single Route\n\n```reasonml\nopen Express;\nlet app = express();\n\n[|\n  Cors.cors(),\n  Middleware.from((_next, _req) =\u003e {\n    [(\"msg\", Js.Json.string(\"This is CORS-enabled for only example.com !\"))]\n    |\u003e Js.Dict.fromList\n    |\u003e Js.Json.object_\n    |\u003e Response.sendJson\n  }),\n|]\n|\u003e App.getWithMany(app, ~path=\"/products/:id\");\n\nlet onListen = e =\u003e\n  switch (e) {\n  | exception (Js.Exn.Error(e)) =\u003e\n    (\n      switch (Js.Exn.message(e)) {\n      | None =\u003e \"UNKNOWN ERROR\"\n      | Some(msg) =\u003e msg\n      }\n    )\n    |\u003e Js.log;\n    Node.Process.exit(1);\n  | _ =\u003e \"CORS-enabled web server listening on port 8080\" |\u003e Js.log\n  };\n\nlet server = App.listen(app, ~port=8080, ~onListen, ());\n```\n\n### Configuring CORS\n\n```reasonml\nopen Express;\nlet app = express();\n\n[|\n  Cors.cors(\n    ~origin=Cors.String(\"example.com\"),\n    ~optionsSuccessStatus=Response.StatusCode.Accepted,\n    (),\n  ), // some legacy browsers (IE11, various SmartTVs) choke on 204\n  Middleware.from((_next, _req) =\u003e {\n    [(\"msg\", Js.Json.string(\"This is CORS-enabled for only example.com !\"))]\n    |\u003e Js.Dict.fromList\n    |\u003e Js.Json.object_\n    |\u003e Response.sendJson\n  }),\n|]\n|\u003e App.getWithMany(app, ~path=\"/products/:id\");\n\n\nlet onListen = e =\u003e\n  switch (e) {\n  | exception (Js.Exn.Error(e)) =\u003e\n    (\n      switch (Js.Exn.message(e)) {\n      | None =\u003e \"UNKNOWN ERROR\"\n      | Some(msg) =\u003e msg\n      }\n    )\n    |\u003e Js.log;\n    Node.Process.exit(1);\n  | _ =\u003e \"CORS-enabled web server listening on port 8080\" |\u003e Js.log\n  };\n\nlet server = App.listen(app, ~port=8080, ~onListen, ());\n```\n\n### Configuring CORS w/ Dynamic Origin\n\n```reasonML\n\nopen Express;\nlet app = express();\n\nlet whitelist = [|\"http:\\/\\/example1.com\", \"http:\\/\\/example2.com\"|];\nlet originFunction:\n  (option(string), (option(Js.Exn.t), bool) =\u003e unit) =\u003e unit =\n  (origin, callback) =\u003e\n    switch (origin) {\n    /* If you do not want to block REST tools or server-to-server requests */\n    | None =\u003e callback(None, true)\n    | Some(o) =\u003e\n      if (Array.exists(item =\u003e item === o, whitelist)) {\n        callback(None, true);\n      } else {\n        callback(Js.Exn.raiseError(\"Not allowed by CORS\"), false);\n      }\n    };\n\n[|\n  Cors.cors(~origin=Function(originFunction), ()),\n  Middleware.from((_next, _req) =\u003e {\n    [(\"msg\", Js.Json.string(\"This is CORS-enabled for only example.com !\"))]\n    |\u003e Js.Dict.fromList\n    |\u003e Js.Json.object_\n    |\u003e Response.sendJson\n  }),\n|]\n|\u003e App.getWithMany(app, ~path=\"/products/:id\");\n\nlet onListen = e =\u003e\n  switch (e) {\n  | exception (Js.Exn.Error(e)) =\u003e\n    (\n      switch (Js.Exn.message(e)) {\n      | None =\u003e \"UNKNOWN ERROR\"\n      | Some(msg) =\u003e msg\n      }\n    )\n    |\u003e Js.log;\n    Node.Process.exit(1);\n  | _ =\u003e \"CORS-enabled web server listening on port 8080\" |\u003e Js.log\n  };\n\nlet server = App.listen(app, ~port=8080, ~onListen, ());\n```\n\n### Enabling CORS Pre-Flight\n\nCertain CORS requests are considered 'complex' and require an initial\n`OPTIONS` request (called the \"pre-flight request\"). An example of a\n'complex' CORS request is one that uses an HTTP verb other than\nGET/HEAD/POST (such as DELETE) or that uses custom headers. To enable\npre-flighting, you must add a new OPTIONS handler for the route you want\nto support:\n\n```reasonml\nopen Express;\nlet app = express();\n\nApp.options(app, ~path=\"/products/:id\", Cors.cors());\n[|\n  Cors.cors(),\n  Middleware.from((_next, _req) =\u003e {\n    [(\"msg\", Js.Json.string(\"This is CORS-enabled for all origins!\"))]\n    |\u003e Js.Dict.fromList\n    |\u003e Js.Json.object_\n    |\u003e Response.sendJson\n  }),\n|]\n|\u003e App.deleteWithMany(app, ~path=\"/products/:id\");\n\n\nlet onListen = e =\u003e\n  switch (e) {\n  | exception (Js.Exn.Error(e)) =\u003e\n    (\n      switch (Js.Exn.message(e)) {\n      | None =\u003e \"UNKNOWN ERROR\"\n      | Some(msg) =\u003e msg\n      }\n    )\n    |\u003e Js.log;\n    Node.Process.exit(1);\n  | _ =\u003e \"CORS-enabled web server listening on port 8080\" |\u003e Js.log\n  };\n```\n\nYou can also enable pre-flight across-the-board like so:\n\n```reasonml\n/* include before other routes */\nApp.options(app, ~path=\"*\", Cors.cors());\n```\n\n### Configuring CORS Asynchronously\n\nTODO\n\n## Configuration Options\n\nThe type of the `cors` middleware function is :\n\n```reasonml\nlet cors:\n  (\n    ~origin: origin=?,\n    ~methods: array(Express.Request.httpMethod)=?,\n    ~allowedHeaders: option(array(string))=?,\n    ~exposedHeaders: option(array(string))=?,\n    ~credentials: bool=?,\n    ~maxAge: option(int)=?,\n    ~preflightContinue: bool=?,\n    ~optionsSuccessStatus: Express.Response.StatusCode.t=?,\n    unit\n  ) =\u003e\n  Express.Middleware.t;\n```\n\n- `origin`: Configures the **Access-Control-Allow-Origin** CORS header. It is a variant with thoses constructors:\n  - `Boolean(bool)` - set `origin` to `Boolean(true)` to reflect the [request origin](http://tools.ietf.org/html/draft-abarth-origin-09), as defined by `req.header('Origin')`, or set it to `Boolean(false)` to disable CORS.\n  - `String(string)` - set `origin` to a specific origin. For example if you set it to `String(\"http:\\/\\/example.com\")` only requests from \"http://example.com\" will be allowed.\n  - `RegExp(Js.Re.t)` - set `origin` to a regular expression pattern which will be used to test the request origin. If it's a match, the request origin will be reflected. For example the pattern `RegExp([%re \"/example\\.com$/\"])` will reflect any request that is coming from an origin ending with \"example.com\".\n  - `Array(array(string))` - set `origin` to an array of valid origins using strings.\n  - `Array(array(Js.Re.t))` - set `origin` to an array of valid origins using RegExp.\n  - `Function((option(string), (option(Js.Exn.t), bool) =\u003e unit) =\u003e unit)` - set `origin` to a function implementing some custom logic. The function takes the request origin as the first parameter and a callback\n- `methods`: Configures the **Access-Control-Allow-Methods** CORS header. Expects an array (ex: `Express.Request.([|Get, Put, Post|])`).\n- `allowedHeaders`: Configures the **Access-Control-Allow-Headers** CORS header. Expects an optional array (ex: `Some([|\"Content-Type\", \"Authorization\"|])`). If not specified, defaults to reflecting the headers specified in the request's **Access-Control-Request-Headers** header.\n- `exposedHeaders`: Configures the **Access-Control-Expose-Headers** CORS header. Expects an optional array (ex: `Some([|\"Content-Range\", \"X-Content-Range\"|])`). If not specified, no custom headers are exposed.\n- `credentials`: Configures the **Access-Control-Allow-Credentials** CORS header. Set to `true` to pass the header, or `false` to be omitted.\n- `maxAge`: Configures the **Access-Control-Max-Age** CORS header. Set to an optional integer to pass the header, otherwise it is omitted.\n- `preflightContinue`: Pass the CORS preflight response to the next handler.\n- `optionsSuccessStatus`: Provides a status code to use for successful `OPTIONS` requests, since some legacy browsers (IE11, various SmartTVs) choke on `204`.\n\nThe default configuration is the equivalent of:\n\n```reasonml\ncors( ~origin=String(\"*\"),\n      ~methods=[|\n                 Request.Get,\n                 Request.Head,\n                 Request.Put,\n                 Request.Patch,\n                 Request.Post,\n                 Request.Delete,\n               |],\n      ~allowedHeaders=None,\n      ~exposedHeaders=None,\n      ~credentials=false,\n      ~maxAge=None,\n      ~preflightContinue=false,\n      ~optionsSuccessStatus=Response.StatusCode.NoContent,\n      ()\n);\n```\n\n## License\n\n[MPL-2.0](https://opensource.org/licenses/MPL-2.0)\n\n## Author\n\n[Thomas Haessle](https://github.com/oteku)\n\n## Thanks to\n\n[Troy Goode](https://github.com/TroyGoode) for building cors !!!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foteku%2Fbs-cors","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foteku%2Fbs-cors","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foteku%2Fbs-cors/lists"}