{"id":13555220,"url":"https://github.com/jpillora/xdomain","last_synced_at":"2025-05-14T10:09:56.510Z","repository":{"id":7924039,"uuid":"9311021","full_name":"jpillora/xdomain","owner":"jpillora","description":"A pure JavaScript CORS alternative","archived":false,"fork":false,"pushed_at":"2022-05-17T03:55:10.000Z","size":889,"stargazers_count":3127,"open_issues_count":50,"forks_count":265,"subscribers_count":107,"default_branch":"gh-pages","last_synced_at":"2025-05-11T04:23:59.569Z","etag":null,"topics":["cors","cross-domain","javascript","xhr"],"latest_commit_sha":null,"homepage":"https://jpillora.com/xdomain/","language":"JavaScript","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/jpillora.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}},"created_at":"2013-04-09T01:55:55.000Z","updated_at":"2025-05-09T13:57:06.000Z","dependencies_parsed_at":"2022-08-30T20:01:05.073Z","dependency_job_id":null,"html_url":"https://github.com/jpillora/xdomain","commit_stats":null,"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpillora%2Fxdomain","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpillora%2Fxdomain/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpillora%2Fxdomain/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpillora%2Fxdomain/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jpillora","download_url":"https://codeload.github.com/jpillora/xdomain/tar.gz/refs/heads/gh-pages","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254120170,"owners_count":22017953,"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":["cors","cross-domain","javascript","xhr"],"created_at":"2024-08-01T12:03:05.593Z","updated_at":"2025-05-14T10:09:56.461Z","avatar_url":"https://github.com/jpillora.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","javascript","前端相关","Data"],"sub_categories":[],"readme":"# XDomain\n\n\u003ca href=\"https://twitter.com/intent/tweet?hashtags=xdomain\u0026original_referer=http%3A%2F%2Fgithub.com%2F\u0026text=XDomain+-+A+pure+JavaScript+CORS+alternative\u0026tw_p=tweetbutton\u0026url=https%3A%2F%2Fgithub.com%2Fjpillora%2Fxdomain\" target=\"_blank\"\u003e\n  \u003cimg src=\"http://jpillora.com/github-twitter-button/img/tweet.png\"\u003e\u003c/img\u003e\n\u003c/a\u003e\n\n## Summary\n\nA pure JavaScript CORS alternative. No server configuration required -\njust add a `proxy.html` on the domain you wish to communicate with. This\nlibrary utilizes [XHook](http://jpillora.com/xhook) to hook all XHR, so XDomain\nwill work seamlessly with any library.\n\n## Features\n\n* Simple\n* Library Agnostic\n  * With [jQuery](http://jpillora.com/xdomain) `$.ajax` (and subsequently `$.get`, `$.post`)\n  * With [Angular](http://jpillora.com/xdomain/example/angular) `$http` service\n* Cross domain XHR just magically works\n  * No need to modify the server code\n  * No need to use IE's silly [XDomainRequest Object](http://msdn.microsoft.com/en-us/library/ie/cc288060.aspx)\n* Easy XHR access to file servers:\n  * [Amazon](http://jpillora.com/xdomain)\n  * [Dropbox](http://jpillora.com/xdomain/example/dropbox)\n* Includes [XHook](http://jpillora.com/xhook) and its [features](https://github.com/jpillora/xhook#features)\n* `proxy.html` files (slaves) may:\n  * White-list domains\n  * White-list paths using regular expressions (e.g. only allow API calls: `/^\\/api/`)\n* Highly [performant](http://jpillora.com/xdomain/example/performance/)\n* Seamless integration with [FormData](http://jpillora.com/xdomain/example/formdata/)\n* Supports [RequiresJS](http://jpillora.com/xdomain/example/requirejs) and [Browserify](http://jpillora.com/xdomain/example/browserify)\n\n## Download\n\n* Development [xdomain.js](https://jpillora.com/xdomain/dist/xdomain.js) 27KB\n* Production [xdomain.min.js](https://jpillora.com/xdomain/dist/xdomain.min.js) 12KB (5.16KB Gzip)\n* CDN (Latest version is `0.8.2`, though you can change to any [release tag](https://github.com/jpillora/xdomain/releases))\n\n  ```html\n  \u003cscript src=\"//unpkg.com/xdomain@0.8.2/dist/xdomain.min.js\"\u003e\u003c/script\u003e\n  ```\n\n## Live Demos\n\n* [Simple GET from S3](http://jpillora.com/xdomain)\n\n* [Serverless S3 Client](http://jpillora.com/s3hook)\n\n## Browser Support\n\nAll except IE6/7 as they don't have `postMessage`\n\n## Quick Usage\n\n_Note: It's_ **important** _to include XDomain before any other library. When XDomain loads, XHook replaces the current `window.XMLHttpRequest`. So if another library saves a reference to the original `window.XMLHttpRequest` and uses that, XHook won't be able to intercept those requests._\n\n1.  On your slave domain (`http://xyz.example.com`), create a small `proxy.html` file:\n\n    ```html\n    \u003c!DOCTYPE HTML\u003e\n    \u003cscript src=\"//unpkg.com/xdomain@0.8.2/dist/xdomain.min.js\" master=\"http://abc.example.com\"\u003e\u003c/script\u003e\n    ```\n\n2.  Then, on your master domain (`http://abc.example.com`), point to your new `proxy.html`:\n\n    ```html\n    \u003cscript src=\"//unpkg.com/xdomain@0.8.2/dist/xdomain.min.js\" slave=\"http://xyz.example.com/proxy.html\"\u003e\u003c/script\u003e\n    ```\n\n3.  **And that's it!** Now, on your master domain, any XHR to `http://xyz.example.com` will automagically work:\n\n    ```js\n    //do some vanilla XHR\n    var xhr = new XMLHttpRequest();\n    xhr.open(\"GET\", \"http://xyz.example.com/secret/file.txt\");\n    xhr.onreadystatechange = function(e) {\n      if (xhr.readyState === 4) console.log(\"got result: \", xhr.responseText);\n    };\n    xhr.send();\n\n    //or if we are using jQuery...\n    $.get(\"http://xyz.example.com/secret/file.txt\").done(function(data) {\n      console.log(\"got result: \", data);\n    });\n    ```\n\n_Tip: If you enjoy being standards compliant, you can also use `data-master` and `data-slave` attributes._\n\n### Using multiple masters and slaves\n\nThe following two snippets are equivalent:\n\n```html\n\u003cscript src=\"//unpkg.com/xdomain@0.8.2/dist/xdomain.min.js\" master=\"http://abc.example.com/api/*\"\u003e\u003c/script\u003e\n```\n\n```html\n\u003cscript src=\"//unpkg.com/xdomain@0.8.2/dist/xdomain.min.js\"\u003e\u003c/script\u003e\n\u003cscript\u003e\nxdomain.masters({\n  'http://abc.example.com': '/api/*'\n});\n\u003c/script\u003e\n```\n\nSo, we can then add more `masters` or (`slaves`) by simply including them in the `object`, see API below.\n\n## API\n\n### `xdomain.slaves`(`slaves`)\n\nWill initialize as a master\n\nEach of the `slaves` must be defined as: `origin`: `proxy file`\n\nThe `slaves` object is used as a _list_ slaves to force one proxy file per origin.\n\nThe **Quick Usage** step 2 above is equivalent to:\n\n```html\n\u003cscript src=\"//unpkg.com/xdomain@0.8.2/dist/xdomain.min.js\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n  xdomain.slaves({\n    \"http://xyz.example.com\": \"/proxy.html\"\n  });\n\u003c/script\u003e\n```\n\n### `xdomain.masters`(`masters`)\n\nWill initialize as a slave\n\nEach of the `masters` must be defined as: `origin`: `path`\n\n`origin` and `path` are converted to a regular expression by escaping all non-alphanumeric chars, then converting `*` into `.*` and finally wrapping it with `^` and `$`. `path` can also be a `RegExp` literal.\n\nRequests that do not match **both** the `origin` and the `path` regular\nexpressions will be blocked.\n\nSo you could use the following `proxy.html` to allow all subdomains of `example.com`:\n\n```html\n\u003cscript src=\"/dist/xdomain.min.js\" data-master=\"http://*.example.com/api/*.json\"\u003e\u003c/script\u003e\n```\n\nWhich is equivalent to:\n\n```html\n\u003cscript src=\"/dist/xdomain.min.js\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n  xdomain.masters({\n    \"http://*.example.com\": \"/api/*.json\"\n  });\n\u003c/script\u003e\n```\n\nWhere `\"/api/*.json\"` becomes the RegExp `/^\\/api\\/.*\\.json$/`\n\nTherefore, you could allow ALL domains with the following `proxy.html`:\n\n```html\n\u003c!-- BEWARE: VERY INSECURE --\u003e\n\u003cscript src=\"/dist/xdomain.min.js\" master=\"*\"\u003e\u003c/script\u003e\n```\n\n### `xdomain.debug` = `false`\n\nWhen `true`, XDomain will log actions to console\n\n### `xdomain.timeout` = `15e3`ms (15 seconds)\n\nNumber of milliseconds until XDomains gives up waiting for an iframe to respond\n\n### `xdomain.on`(`event`, `handler`)\n\n`event` may be `log`, `warn` or `timeout`. When listening for `log` and `warn` events, `handler` with contain the `message` as the first parameter. The `timeout` event fires when an iframe exeeds the `xdomain.timeout` time limit.\n\n### `xdomain.cookies`\n\n**WARNING** :warning: Chrome and possibly other browsers appear to be blocking access to the iframe's `document.cookie` property. This means `Slave-Cookie`s are no longer supported in some browsers.\n\nWhen `withCredentials` is set to `true` for a given request, the cookies of the master and slave are sent to the server using these names. If one is set to `null`, it will not be sent.\n\n```js\n//defaults\nxdomain.cookies = {\n  master: \"Master-Cookie\"\n  slave: \"Slave-Cookie\"\n};\n```\n\n_Note, if you use `\"Cookie\"` as your cookie name, it will be removed by browsers with `Disable 3rd Party Cookies` switched on - this includes all Safari users and many others who purposefully enable it._\n\n## Conceptual Overview\n\n1.  XDomain will create an iframe on the master to the slave's proxy.\n2.  Master will communicate to slave iframe using postMessage.\n3.  Slave will create XHRs on behalf of master then return the results.\n\nXHR interception is done seamlessly via [XHook](https://github.com/jpillora/xhook#overview).\n\n## Internet Explorer\n\nUse the HTML5 document type `\u003c!DOCTYPE HTML\u003e` to prevent your page\nfrom going into quirks mode. If you don't do this, XDomain will warn you about\nthe missing `JSON` and/or `postMessage` globals and will exit.\n\nIf you need a **CORS Polyfill** and you're here because of IE, give this XHook [CORS polyfill](http://jpillora.com/xhook/example/ie-8-9-cors-polyfill.html) a try, however, be mindful of the restrictions listed below.\n\n## FAQ / Troubleshooting\n\nQ: But I love CORS\n\nA: You shouldn't. You should use XDomain because:\n\n* IE uses a different API (XDomainRequest) for CORS, XDomain normalizes this silliness. XDomainRequest also has many restrictions:\n  * Requests must be `GET` or `POST`\n  * Requests must use the same protocol as the page `http` -\u003e `http`\n  * Requests only emit `progress`,`timeout` and `error`\n  * Requests may only use the `Content-Type` header\n* The [CORS spec](http://www.w3.org/TR/cors/) is not as simple as it seems, XDomain allows you to use plain XHR instead.\n* On a RESTful JSON API server, CORS will generate superfluous traffic by sending a\n  preflight OPTIONS request preceding various types of requests.\n* Not everyone is able to modify HTTP headers on the server, but most can upload a `proxy.html` file.\n* Google also uses iframes as postMessage proxies instead of CORS in its Google API JS SDK:\n\n  ```html\n  \u003ciframe name=\"oauth2relay564752183\" id=\"oauth2relay564752183\"\n  src=\"https://accounts.google.com/o/oauth2/postmessageRelay?...\"\u003e \u003c/iframe\u003e\n  ```\n\nQ: XDomain is interfering with another library!\n\nA: XDomain attempts to perfectly implement [XMLHttpRequest2](http://www.w3.org/TR/XMLHttpRequest2/)\nso there _should_ be no differences. If there is a difference, create an issue. Note however, one purposeful\ndifference affects some libraries under IE. Many use the presence of `'withCredentials' in new XMLHttpRequest()`\nto determine if the browser supports CORS.\n\nThe most notable library that does this is jQuery, so [XHook](https://github.com/jpillora/xhook) purposefully defines `withCredentials` to trick jQuery into thinking the browser supports\nCORS, thereby allowing XDomain to function seamlessly in IE. However, this fix is detrimental to\nother libraries like: MixPanel, FB SDK, Intercom as they will incorrectly attempt CORS on domains\nwhich don't have a `proxy.html`. So, if you are using any of these libraries which implement their own CORS workarounds, you can do the\nfollowing to manually disable defining `withCredentials` and manually reenable CORS on jQuery:\n\n```js\n//fix trackers\nxhook.addWithCredentials = false;\n//fix jquery cors\njQuery.support.cors = true;\n```\n\nNote: In newer browsers `xhook.addWithCredentials` has no effect as they already support `withCredentials`.\n\nQ: XDomain works for a few requests and then it stops.\n\nA: Most likely, the slave iframe was removed - this is often due to libraries like Turbolinks\n\nQ: In IE, I'm getting an `Access Denied` error\n\nA: This is error occurs when IE attempts a CORS request. Read on.\n\nQ: The browser is still sending CORS requests.\n\nA: Double check your slaves configuration against the examples.\nIf your slaves configuration is correct, double-check that you're\nincluding XDomain _before_ `window.XMLHttpRequest` is referenced **anywhere**.\nThe safest way to fix it is to include XDomain **first**, it has no dependencies,\nit only modifies `window.XMLHttpRequest`.\n\nQ: The script is loads but the 'Quick Start' steps don't work\n\nA: XDomain only searches the script tags for `master` and `slave` attributes if they have `xdomain` in the `src`. So, if you've renamed or embedded XDomain, you'll need to use the [API](#api) in order to insert your masters and slaves.\n\nQ: It's still not working!\n\nA: Enable `xdomain.debug = true;` (or add a `debug=\"true\"` attribute to the script tag) on both the master and the slave\nand copy the `console.logs` to a new issue. If possible, please provide a live example demonstrating your issue.\n\n## Change log\n\n* `0.8.2`\n\n  * Removed CoffeeScript\n  * Restructured with ES6 and Common.js\n  * Use `parcel` as bundler\n\n## Todo\n\n* Saucelabs testing is broken, need to swap to BrowserStack.\n\n## Contributing\n\n* `npm install`\n* Tab 1\n  * `npm run dev`\n* Tab 2\n  * `npm i -g serve`\n  * `serve -p 3000 .`\n  * `open http://localhost:3000/example/local`\n* `npm run build`\n* See `dist/`\n\n#### Donate\n\nBTC 1AxEWoz121JSC3rV8e9MkaN9GAc5Jxvs4\n\n#### MIT License\n\nCopyright © 2016 Jaime Pillora \u0026lt;dev@jpillora.com\u0026gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n[![Analytics](https://ga-beacon.appspot.com/UA-38709761-8/xdomain/readme)](https://github.com/igrigorik/ga-beacon)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjpillora%2Fxdomain","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjpillora%2Fxdomain","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjpillora%2Fxdomain/lists"}