CORS: How to configure Apache while developing Node.js Apps?

You will have to deal with CORS – Cross-Origin Resource Sharing – if you develop Node.js Apps locally and want to access local microservices, for example an API service. To avoid CORS issues, you can configure your Apache.

Example: Swagger UI and API Server
Example: Swagger UI and API Server

Imagine, you want to run a Swagger UI that documents your APIs (Application Programming Interface), and provide a server for trying the different endpoints out. The Swagger Node.js Server stub will run on port 8080 by default, and your API service (Node Express) runs for example on port 8085. The server URL is defined in the yaml file of the swagger node server, e.g. http://localhost:8085.

Implement CORS on the API server

To avoid CORS issues, when the browser calls the API server you can implement CORS on the API server (port 8085) and allow requests from port 8080 or from all (*). In this case the npm cors package is one option that allows you to define one origin domain or a list with allowed domains.

const express = require('express');
const router = express.Router();
var cors = require('cors');

// cors options
var corsOptions = {
    origin: 'http://localhost:8080', // this domain is allowed to make API calls
    optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
  }

// Routes with CORS
 router.get('/api/v1/customers', cors(corsOptions), function (req, res) {
    // ...
}

The disadvantage of this approach is that you have to deal with the ports which will be invisible on a production system. This leads to another approach where the web server is configured as a reverse proxy.

Configure the Apache as reverse proxy

I use an Apache web server and configured it so that I do not need to implement CORS as long as the requests remain on the same domain like localhost or api.example.com. Unfortunately, I have not had enough time to appropriate the knowledge of the configuration of a nginx web server. It seems that this server is more convenient for Node.js applications and microservices.

However, you can adjust the relevant virtual host file, e.g. /etc/apache2/sites-available/000-default.conf (look at the comments in the file). You will find addition information her: https://httpd.apache.org/docs/2.4/mod/mod_proxy.html.

#Disable this to setup the reverse proxy
ProxyRequests Off 

#Use incoming Host HTTP request header for proxy request
ProxyPreserveHost On 

#port 8080
#Container for directives applied to proxied resources
<Proxy /docs> # path /docs
	Order deny,allow
	Allow from all
</Proxy>

#Maps remote servers into the local server URL-space
ProxyPass /docs http://localhost:8080/docs #path 'docs' is mapped to localhost:8080/docs

#Adjusts the URL in HTTP response headers sent from a reverse proxied server
ProxyPassReverse /docs http://localhost:8080/docs

<Proxy /api-docs>
	Order deny,allow
	Allow from all
</Proxy>

ProxyPass /api-docs http://localhost:8080/api-docs
ProxyPassReverse /api-docs http://localhost:8080/api-docs

#port 8085
<Proxy /api>
	Order deny,allow
	Allow from all
</Proxy>

ProxyPass /api http://localhost:8085/api
ProxyPassReverse /v1 http://localhost:8085/api

This virtual host configuration allows you to reach the Swagger UI with the URL localhost/docs and localhost/api-docs because the web server connects the path to the local running service on port 8080. The API service is available under localhost/api because the web server connects this path to port 8085. There will be not CORS issue because all requests run on the domain localhost.

Further information:
[1] CORS: Proxy server for remote OData Service in local SAPUI5 Dev
[2] NPM package CORS
[3] Reverse Proxy
[4] Apache
[5] nginx

Leave a Reply