Creating and deploying a tiny proxy server on Vercel in 10 minutes
Tags: javascript, nextjs, tutorial, node
Published: 2022-02-22 14:48:49

---
title: Creating and deploying a tiny proxy server on Vercel in 10 minutes
published: true
date: 2022-02-22 14:48:00 UTC
tags: #javascript #nextjs #tutorial #node
canonical_url: https://mmazzarolo.com/blog/2022-02-05-creating-and-deploying-a-proxy-server-in-5-minutes/
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/48ajbaqq6ridi0fkqkpu.png
---

I recently created [a tiny proxy server to edit responses of a public API on the fly](https://github.com/mmazzarolo/pinboard-api-proxy), and I was impressed by how easy it is to build and deploy such things on [Vercel](https://vercel.com/).  
In my case, the goal was to allow all origins to fetch the [Pinboard API](https://pinboard.in/howto/#api) by adding an `"Access-Control-Allow-Origin": "*"` header to the API response, but there are plenty of other cases where a proxy server may come in handy.

So, here’s how you can create and deploy a tiny but flexible [Node.js](https://nodejs.org/) proxy server on Vercel in 10 minutes.

## TL;DR

We’ll create a Node.js serverless function that uses [`http-proxy-middleware`](https://github.com/chimurai/http-proxy-middleware) to proxy any `/api` request to (e.g.) `https://example.org`. Within the serverless function code, we can intercept requests/responses and manipulate them on the fly.  
The serverless function will be deployed on Vercel.

## Project setup

Create a project directory, `cd` into it, and initialize an npm project:

```bash
mkdir my-proxy && cd my-proxy
npm init
```

Install [`vercel`](https://github.com/vercel/vercel) as a dependency:

```js
npm install -D vercel
```

Update the `start` script of your `package.json` to `"start": "vercel dev"` in order to run your serverless function locally:

my-proxy/package.json

```json
 {
   "name": "my-proxy",
   "version": "1.0.0",
   "scripts": {
     "start": "vercel dev"
   },
```

Create an `api` directory and an `index.js` file inside of it.

```bash
mkdir api && touch api/index.js
```

Vercel serverless functions use a [file-system-based convention](https://vercel.com/docs/concepts/functions/serverless-functions). So the `api/index.js` file you just created will automatically handle all requests of the `/api` endpoint:

my-proxy/api/index.js

```js
// In Vercel, any file inside the "api" directory is exposed on an "/api" endpoint.

// For an API route to work, you need to export a function as default (a.k.a request handler),
// which then receives the following parameters:
// - req: The request object.
// - res: The response object.
// See https://vercel.com/docs/serverless-functions/supported-languages#node.js for details.
export default async function handler(req, res) {
  res.status(200).send(`Hello world!`);
}
```

By default, on Vercel, the `/api/index.js` file would **strictly match only requests made to the `/api` endpoint** , ignoring sub-paths like `/api/hello`.  
To make `/api/index.js` handle the entire path, we can configure a [Vercel rewrite](https://vercel.com/docs/cli#project-configuration/rewrites) to redirect all `/api/*` calls to the `/api/index.js` file (by specifying the rewrite rule in a `vercel.json` file at the root of the project):

```bash
touch vercel.json
```

my-proxy/vercel.json

```json
{
  "rewrites": [{ "source": "/api/(.*)", "destination": "/api" }]
}
```

You should now be able to deploy your code to Vercel (of course, we haven’t added any “real” logic in `api/index.js`, so it won’t do anything for now).  
My go-to approach on these occasions is to [create a GitHub repo and connect it to Vercel](https://vercel.com/docs/git/vercel-for-github) to automatically deploy the project on each commit. But you can also follow the automated setup by running `npm start`.

## Proxy logic setup

Install [`http-proxy-middleware`](https://github.com/chimurai/http-proxy-middleware), an easy-to-use proxy middleware compatible with Vercel:

```bash
npm i http-proxy-middleware
```

In `/api/index.js`, use `http-proxy-middleware` to create a new proxy and expose it on the route handler:

my-proxy/api/index.js

```js
// Create a proxy to redirect requests of the "/api/*" path to "https://example.org".
//
// Examples:
// GET /api/hello → GET https://example.org/hello
// POST /api/test?color=red → POST https://example.org/test?color=red
//
// Additionally, the proxy will:
// - Add an "x-added" header
// - Remove the "x-removed" header
// From the proxied response.
//
// You can/should update the proxy to suit your needs.
// See https://github.com/chimurai/http-proxy-middleware for more details.
const { createProxyMiddleware } = require('http-proxy-middleware');

const apiProxy = createProxyMiddleware({
  target: "https://example.org",
  changeOrigin: true,
  pathRewrite: {
    "^/api": "" // strip "/api" from the URL
  },
  onProxyRes(proxyRes) {
    proxyRes.headers['x-added'] = 'foobar'; // add new header to response
    delete proxyRes.headers['x-removed']; // remove header from response
  }
});

// Expose the proxy on the "/api/*" endpoint.
export default function (req, res) {
  return apiProxy(req, res);
};
```

Et voilà!

By deploying your code (or running it locally with `npm start`) any call made to the `/api` endpoint will be proxied to `https://example.org`.

Check [the documentation of the `http-proxy-middleware` library](https://github.com/chimurai/http-proxy-middleware) (and of the [`node-http-proxy` library](https://github.com/http-party/node-http-proxy), used under-the-hood) to learn how you can manipulate the proxied request & response.