No matter how much experience you have in software development, you've likely had to deal with the CORS problem.
The good news is that there are now new and different ways to solve this issue, from using an extension for your favorite browser, to defining a custom solution.
In this post, I'll explain how to implement a basic Proxy Server using Node.js so that you can use it even if you're using a different programming language for your main application.
The Problem
Let's suppose you're building a Single-Page Application, and it's running fine in your local environment http://localhost:8000
. At some point, you'll need to perform HTTP requests to an existing server to obtain data, or even authenticate you. All these services are running below https://app.mydomain.com
.
At the time you make the requests, you may have an error like the one shown below:
Access to fetch at 'https://app.mydomain.com' from origin 'http://localhost:8000' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
In this particular case, the browser will restrict the cross-origin HTTP requests for security reasons.
The Solution
In the problem explained above, there is a Single-Page Application that needs access to resources or data. So, there is a security issue on the frontend side, and it can be solved by running a server in just a few steps.
Koa
For the Proxy Server implementation, we're going to use Koa, which is a web framework for Node.js.
Koa is a new web framework designed by the team behind Express, which aims to be a smaller, more expressive, and more robust foundation for web applications and APIs.
It seems that there are very good reasons to use it, right? :-)
Prerequisites
You'll need to have installed the following tools in your local environment:
- Node.js. Preferably the latest LTS version.
- A package manager. You can use either NPM or Yarn. This tutorial will use NPM.
Koa Installation
Before installing Koa and other dependencies, let's create a folder for the Proxy Server:
mkdir proxy-server
cd proxy-server
Now, let's install Koa as the first dependency
npm install koa
As the next step, let's create a proxy.js
file with the following content:
const Koa = require("koa");
const app = new Koa();
app.listen(3000);
console.log("listening on port 3000");
This is the simplest way to create an HTTP server using Koa. You can run it through node proxy.js
command. Of course, it is not very useful yet, but it will help as a basis for implementing the proxy.
Koa Proxy and CORS
It's time to install the next dependencies: @koa/cors
and koa-proxies
:
npm install @koa/cors koa-proxies
@koa/cors
is a package to enable CORS (Cross-Origin Resource Sharing) with Koa.koa-proxies
is a package powered by http-proxy, which is a full-featured HTTP proxy for Node.js
Now, let's update the proxy.js
file, including @koa/cors
, to enable CORS in the current implementation.
const Koa = require("koa");
const cors = require("@koa/cors");
const app = new Koa();
const port = process.env.PORT || 3000;
app.use(cors());
app.listen(port);
console.log(`listening on port ${port}`);
As you can see, the Koa object gets available through new Koa()
, and right after that, you can apply a middleware using the app.use()
method.
- cors(), enable CORS with default options, and allow several HTTP Methods.
Take a look the available Koa middleware list for more reference.
Proxy Server
As the last step, let's configure the Koa proxy using the installed koa-proxies
library.
const Koa = require("koa");
const cors = require("@koa/cors");
const proxy = require("koa-proxies");
const app = new Koa();
const port = process.env.PORT || 3000;
app.use(cors());
app.use(
proxy("/", {
target: "https://app.mydomain.com",
changeOrigin: true,
logs: true,
})
);
app.listen(port);
console.log(`listening on port ${port}`);
Again, the app.use()
method enables the use of proxy()
as a middleware. Pay attention to the used options:
- target, the URL string to be parsed
- changeOrigin, changes the origin of the host header to the target URL
- logs, enable default logs
The TypeScript Solution
The previous solution works fine using JavaScript only. In case you require using TypeScript, you'll need to create the tsconfig.json
file first:
tsc --init
This command will auto-generate the tsconfig.json
file using default options for the compiler. Let's apply a couple of updates before moving forward:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true
}
}
Next, let's install the TypeScript types for koa
and @koa/cors
packages:
npm install --save-dev @types/koa @types/koa__cors
Finally, create the proxy.ts
file with the following content:
// proxy.ts
import Koa from "koa";
import cors from "@koa/cors";
import proxy from "koa-proxies";
const app: Koa = new Koa();
const port: number | string = process.env.PORT || 3000;
app.use(cors());
const proxyOptions: proxy.IKoaProxiesOptions = {
target: "https://app.mydomain.com",
changeOrigin: true,
logs: true,
};
app.use(proxy("/", proxyOptions));
app.listen(port);
console.log(`listening on port ${port}`);
As you may see in the previous code snippet, it's about using the right types, and configuring the TypeScript compiler.
You can run the proxy.ts
file using this command:
npm run start
Which will run the TypeScript compiler followed by the generated script: tsc && node dist/proxy.js
.
Source Code of the Project
Find the complete project in this GitHub repository: cors-proxy-server-koa. Do not forget to give it a star āļø, and play around with the code.
Feel free to reach out on Twitter if you have any questions. Follow me on GitHub to see more about my work.