@cseitz/proxy
TypeScript icon, indicating that this package has built-in type declarations

1.0.0 • Public • Published

Proxy

Facilitates reverse proxying via lite express.js server.

Used as a lightweight NGINX alternative when in development mode.

Example

Note: The rules are in order of precedence.

  • Once a request is matched by one of the match functions, its destination is decided and no other matching is attempted.
import { wasRequestProxied, createReverseProxy } from '@cseitz/proxy';
import { WebSocketServer } from 'ws';
import { createServer } from 'http';
import express from 'express';

const port = 5000;

/** Express app */
export const app = express();


/** Node HTTP Server */
export const server = createServer((req, res) => (
    // Only route requests that don't get caught by the proxy
    !proxyRequest(req, res) && app(req, res)
));

/** Websocket Server */
export const wss = new WebSocketServer({
    noServer: true,
})

/** Define reverse proxies (like NGINX) */
const proxyRequest = createReverseProxy({ server }, {
    api: {
        /**
         * This rule prevents requests to the API from being proxied
         * - notice how its missing the `server` block, meaning it acts as a request trap that ensures requests dont get proxied
         * */
        enabled: true,
        match(req, { ws }) {
            if (ws) {
                if (!req.url?.startsWith('/_next'))
                    return true; // Matches non-NextJS websockets
            } else {
                if (req.url?.startsWith('/api'))
                    return true; // Matches API routes
            }
        },
    },
    staff: {
        // This rule proxies requests to the staff portal, which runs one port higher than the API
        enabled: true,
        server: {
            ws: true,
            target: {
                host: 'localhost',
                port: port + 1,
            },
        },
        match(req) {
            // Proxy requests that are on the `staff` subdomain, such as `staff.localhost`
            if (req.headers.host?.includes('staff')) {
                return true;
            }
        },
    },
    web: {
        // This catch-all rule forwards any remaining requests to the website running 2 ports higher.
        enabled: true,
        server: {
            ws: true,
            target: {
                host: 'localhost',
                port: port + 2,
            },
        },
        match(req) {
            // Match any requests
            return true;
        },
    }
})

/** Upgrade websockets */
server.on('upgrade', (req, socket, head) => {
    if (!wasRequestProxied(req)) {
        // The request wasn't proxied, so we can do any websocket logic we want
        wss.handleUpgrade(req, socket, head, ws => {
            wss.emit('connection', ws, req);
        })
    }
});


/** Close connections when the process is about to exit */
process.on('SIGTERM', () => {
    wssHandle.broadcastReconnectNotification();
    server.close();
    wss.close();
});


/** Start the server on the specified port */
server.listen(port, () => {
    console.timeEnd('development proxy ready');
});

Readme

Keywords

none

Package Sidebar

Install

npm i @cseitz/proxy

Weekly Downloads

1

Version

1.0.0

License

ISC

Unpacked Size

14 kB

Total Files

6

Last publish

Collaborators

  • cseitz