Calling HTTPS URLs from http://localhost

Working around Cross Origin restrictions during development

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.

Browser Settings

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.

e.g. --disable-web-security --user-data-dir=~/.chrome-disable-web-security

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.

Installing

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.

Running

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 https://api.example.com.

e.g. http://127.0.0.1:5000/api/foo —>https://api.example.com/api/foo

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 \
-p 5000

The ~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 (replace this with whatever hostname is normally calls the API).

The ~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. ) but the above example is a good general purpose example and follow if you need to extend it.

Tips

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 and are usually functionally equivalent, this is one of those special cases where some browsers, including Chrome, treat differently.

You can still access your locally running via either and but you are likely to find any AJAX requests from the browser will only work if they are made explicitly to rather thanbecause 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.

Written by

Software for news and media and civic tech. Cat herder. Director at Glitch Digital.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store