Calling HTTPS URLs from http://localhost
Making requests to HTTPS APIs from HTTP sites running on localhost can be a pain, especially as browsers keep changing how they expose the option.
The only way to turn off Cross Origin Restrictions in Chrome is to turn off the feature completely when starting the browser by passing arguments to it.
On my Mac, I have the following in my
.bash_profile so I can just type
chrome at the command prompt so I can quickly start an instance of Chrome with web security disabled for development.
alias chrome=”/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --disable-web-security --user-data-dir=~/.chrome-disable-web-security”
This saves me from having to remember the flags needed and allows me to easily test things in Chrome, although it doesn’t work in *every* case as some servers also require header re-writing (keep reading for more on this).
It’s a bit easier in Firefox but the features related to it are split across multiple options and you may need to disable multiple flags to get things working — and the options (and even plugins) are limited and don’t help in all cases and is unfortunately quite limited in usefulness.
In Safari it’s very easy, as you can turn it off directly from the “Develop” menu, which in turn is enabled under Advanced preferences and you are done.
Simple Reverse Proxy
If those aren’t helpful, an alternative — other than creating your own snake oil certificate — is to use a simple reverse proxy like mitmproxy.
This approach works on all platforms, on all browsers and can be useful in application development too.
It works by re-writing the request/response headers on the fly, allowing you to call remote services from your localhost website without having to edit or disable any security features in your browser.
The mitmproxy utility is cross platform and easy to install.
On a Mac with Homebrew:
brew install mitmproxy
On Debian or Ubuntu:
apt-get instal mitmproxy
There are also binary releases for Windows and other platforms.
It’s simple to use and you don’t need to create a configuration file.
The following command will proxy all requests made to any path at
http://127.0.0.1:5000 to the server at
mitmproxy -R https://api.example.com \
--setheader :~q:Host:api.example.com \
--setheader :~q:Origin:www.example.com \
--setheader :~s:Access-Control-Allow-Origin:* \
--setheader :~s:Access-Control-Allow-Methods:GET,PUT,POST,DELETE \
--setheader :~s:Access-Control-Allow-Headers:Authorization \
~q option sets a request header that overrides the Host header with the hostname of the remote API (so the remote service knows how to proccess the request correctly) and sets the Origin header to be that of www.example.com (replace this with whatever hostname is normally calls the API).
~s options injects a response header to add a CORS headers to the response from the remote API — so the browser will allow the request.
You might need to add additional response headers if you need to pass additional headers or methods (e.g. OPTIONS) but the above example is a good general purpose example and follow if you need to extend it.
Note that you should make calls to your new local API endpoint via AJAX or fetch by calling http://127.0.0.1:5000 rather than http://localhost:5000.
While localhost and 127.0.0.1 are usually functionally equivalent, this is one of those special cases where some browsers, including Chrome, treat localhost differently.
You can still access your locally running website via either localhost and 127.0.0.1, but you are likely to find any AJAX requests from the browser will only work if they are made explicitly to 127.0.0.1 rather than localhost, because of how the browser treats requests made to the hostname localhost.
A bonus feature of using mitmproxy is it makes network debugging easier, as it lets you inspect the requests, responses and headers with an arguably nicer interface than many browsers network inspection panels.