{"id":23814200,"url":"https://github.com/stuartpb/ach","last_synced_at":"2026-05-02T21:30:15.469Z","repository":{"id":13167410,"uuid":"15850395","full_name":"stuartpb/ach","owner":"stuartpb","description":"Connect middleware for setting Access-Control headers","archived":false,"fork":false,"pushed_at":"2015-03-30T19:42:08.000Z","size":268,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-12T23:42:57.382Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","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/stuartpb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-01-12T20:43:55.000Z","updated_at":"2019-07-26T10:30:16.000Z","dependencies_parsed_at":"2022-09-15T21:02:16.305Z","dependency_job_id":null,"html_url":"https://github.com/stuartpb/ach","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stuartpb%2Fach","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stuartpb%2Fach/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stuartpb%2Fach/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stuartpb%2Fach/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stuartpb","download_url":"https://codeload.github.com/stuartpb/ach/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240079640,"owners_count":19744726,"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":[],"created_at":"2025-01-02T03:46:48.978Z","updated_at":"2026-05-02T21:30:15.382Z","avatar_url":"https://github.com/stuartpb.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ach\n\n[![Build Status](https://travis-ci.org/stuartpb/ach.png?branch=master)](https://travis-ci.org/stuartpb/ach)\n\nach is a connect/express middleware generator for setting Access-Control\nheaders for Cross-Origin Resource Sharing.\n\n## What is Cross-Origin Resource Sharing (CORS)?\n\nCORS is a set of headers you can set on a response to declare that it's OK\nfor content on other origins (domains) to make certain requests to your site\nthrough the browser that would not normally be allowed (like requests with\ncredentials, or JSON POSTs), and to read the response from these cross-origin\nrequests (which would normally be disallowed). See the\n[W3C Specification][Spec], and the [MDN documentation][MDN].\n\n[Spec]: http://www.w3.org/TR/cors/\n[MDN]: https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS\n\n## Does Cross-Origin Resource Sharing prevent unauthorized requests?\n\n**No.** Responding with Access-Control headers only serves as a mechanism to\ncommunicate to user's browsers when they should *allow* sites on other domains\nto make requests *from that user's browser* to your server. These sites can\nalready trigger simple requests to your domain from the browser: CORS only\nallows more complex requests through a mechanism like XMLHttpRequest that would\notherwise be blocked by default.\n\nThis is the standard-dictated behavior for browsers: other user agents (for\ninstance, a request in Node.js) can make whatever requests they want, including\nany value for the Origin header that they wish.\n\nActually *restricting* access to a server requires an authentication mechanism,\nthe nature of which depends on who and what you're looking to restrict access\n*to*. For example, OAuth is a frequently implemented mechanism for\nauthenticating API consumers.\n\n## Usage\n\nTo use ach with Express \u003e=3.x, mount it on whatever path you want to make\navailable with CORS, using either `app.use([prefix])` or `app.all(route)`,\ndepending on when you want the middleware to run relative to Express's router.\n\n```js\nvar app = require('express')();\napp.use(require('ach')());\napp.get(function(req,res){res.send('You can read me anywhere!')});\n```\n\nNote that attaching this middleware to a route for a *single method* (like\n`app.get`) will not work for [preflighted requests][], which make an `OPTIONS`\nrequest before making the preflighted request. You may work around this by\nattaching the middleware to a corresponding `app.options` route, but, for the\nsimplest approach, attach it for all methods with `app.use` or `app.all`.\n\n[preflighted requests]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests\n\n## Configuration\n\nBy default, ach sets the Access-Control-Allow-Origin to `'*'` (all servers) and\nthe Access-Control-Allow-Headers to `'X-Requested-With'` (to allow\nXMLHttpRequest to declare itself). Either of these can be overridden (these\ndefaults are only set when their respective options are `undefined`; notably,\nif you set the `allowOrigin` option to a different falsy value (such as\n`null`), you will stop any CORS headers from being sent at all).\n\nach allows you to set a number of headers relevant to the control of CORS to\nallow behaviors beyond the default. At runtime, ach tweaks the headers it sends\nslightly to match the expected behavior by the known implementations of CORS\nin practice (in other words, it polyfills to match what the browsers can\nhandle).\n\nFor example, if you had a CDN server with an API route that's meant to serve\nrequests to only your secure site, expose a non-simple header like `Link`,\nand allow the DELETE method, you would do something like:\n\n```js\nvar app = require('express')();\napp.all('/api/*', require('ach')({\n  allowOrigin: 'https://example.com',\n  exposeHeaders: 'Link',\n  allowMethods: 'DELETE'\n}));\n// etc...\n```\n\nach recognizes option names as either JavaScript-conventional camelCase,\nor as case-insensitive Header-Style-Hyphen-Separation (optionally beginning\nwith `Access-Control`). In the presence of multiple equivalent options,\nthe camelCased names take precedence: beyond that, the precedence is\n*undefined*, so don't set different values for the same option.\n\n## Option / Header Behavior Details\n\n### allowOrigin\n\nThe origin or origins allowed to access this resource with CORS.\n\nThis may be either an Array, a space-separated origin-list (including a single\norigin), `'*'` (signifying any domain), or `null` / any other falsy value (which\nwill prevent the setting of Access-Control headers altogether, as mentioned\nabove).\n\nWhen a request is sent with a `Origin` header specified, its match status\nagainst this option controls whether or not any headers will be sent.\n\nIf allowOrigin is set to `'*'`, the headers will be sent: if allowCredentials\nis not a truthy value, 'Access-Control-Allow-Origin' will be sent as `*`. If\nallowCredentials is a truthy value, the 'Access-Control-Allow-Origin' header\nwill be sent with the same value as the request's Origin header, as browsers\ndo not trust the `*` origin with credentials.\n\nOtherwise, the request's `Origin` will be compared against the specified list of\norigins (falsy values and `null` are interpreted as an empty list). If the\npassed origin matches a value of the allowOrigin list, the Access-Control\nheaders will be set, with Access-Control-Allow-Origin set to the value of the\nrequest's Origin (as browser implementations do not recognize origin lists in\npractice).\n\nWhen Access-Control-Allow-Origin is sent with the value of the request's Origin\nheader, unless that Origin is the only one allowed, ach will ensure that the\nresponse's `Vary` header includes `Origin` to inform caching systems not to\ncache the response for other origins.\n\nNote that, while allowOrigin accepts the wildcard value `'*'` in place of an\norigin-list, listed origins *can not* use wildcards (if you wish to support\nmultiple domains, ports, or HTTP-and/or-HTTPS, you must explicitly specify each\norigin). If you need wildcard matching for Origin, you're outside the CORS\nheader specification and, as such, outside the domain of problems `ach()` aims\nto solve.\n\n### allowCredentials\n\nWhether to allow requests with credentials (such as an XMLHttpRequest with\n`withCredentials` set to `true`), or (for GET requests with credentials),\nwhether the client will be allowed to read the results of the request.\n\nSetting this changes the behavior of the wildcard (`'*'`)\nAccess-Control-Allow-Origin header as described above.\n\n### exposeHeaders\n\nA comma-separated list headers on the response to expose to the client.\n\nThe \"simple response headers\" `Cache-Control`, `Content-Language`,\n`Content-Type`, `Expires`, `Last-Modified`, and `Pragma` are always exposed, so\nthis can only be used to expose other headers on the response.\n\n### maxAge\n\nHow many seconds clients should cache these Access-Control rules for.\n\n### allowMethods\n\nA comma-separated list of methods to allow requests to use.\n\nThe \"simple methods\" `GET`, `HEAD`, and `POST` are intrinsically allowed, so\nthis can only be used to whitelist other HTTP methods like `PUT` and `DELETE`.\n\n### allowHeaders\n\nA comma-separated list of headers to allow requests to send.\n\nThe \"simple headers\" `Accept`, `Accept-Language`, and `Content-Language` are\nintrinsically allowed, as is `Content-Type` when its value is one of\n`application/x-www-form-urlencoded`, `multipart/form-data`, or `text/plain`,\nso this can only be used to whitelist other headers.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstuartpb%2Fach","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstuartpb%2Fach","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstuartpb%2Fach/lists"}