Problem
http://localhost:3000 can’t call your remote API because of browser-enforced limitations involving CORS, cookie sharing, and HTTPS.
Solution
Set up local.yourdomain.com
on your dev machine so your browser will successfully call your remote service at api.yourdomain.com
, for example.
How to set it up
1. Edit your hosts file
Add a custom host to your /etc/hosts
file (location of hosts file varies by OS):
127.0.0.1 localhost
127.0.0.1 local.yourdomain.com
The domain you set here depends on the domain of the API. If, for example, the API server you’re trying to call is staging.api.yourdomain.com
and that server’s CORS settings are configured to allow local.yourdomain.com
then you would add local.yourdomain.com
to the hosts file. If the server’s CORS config allows *.
yourdomain.com
then you could technically use any subdomain you want. The point is whatever your server CORS settings allow your local host needs to be a match.
Also, cookies’ domain
should be set to this host (or at least set to the domain, e.g. .
yourdomain.com
) so the browser will pass cookies to the remote API.
2. Install nginx
This will vary by OS, but brew install nginx
is recommended on macOS.
3. Install dev-nginx
Again, brew makes this easy. Run these two commands:
brew tap guardian/homebrew-devtools
brew install guardian/devtools/dev-nginx
Then in your app’s root directory create a file named nginx-mappings.yml
and paste this in it:
name: your-domain
domain-root: yourdomain.com
mappings:
- port: 3000 (or whatever your local app server is running on)
prefix: local
Now cd
to your app’s root if you’re not already there and then run:
dev-nginx setup-app nginx-mappings.yml
This creates an nginx config based on that YAML file, sets up a certificate for local HTTPS, and restarts nginx. You may need to restart you app server, but then you should be able to access https://local.yourdomain.com!
4. Other settings
If you can access your new local.yourdomain.com
but the browser is still failing to call the remote API, there are a number of things to double-check. These include:
fetch's
credentials: 'include'
fetch's
mode: 'cors'
Any required cookies have a matching
domain
The API server CORS settings using a wildcard (
*
) to allow any domain. This setting prevents browsers from sending auth tokens (i.e.Authorization
header and cookies can't be sent).
Help me help you
I wanted to do this with as simple a setup as possible, but couldn't find anything explaining how to do this directly with an Apache server or nginx without the dev-nginx tool (not that the tool isn't good - it was a lifesaver!).
If you know how to achieve this without extra tools, please share in the comments and I'll update the article for others.