{"id":13447629,"url":"https://github.com/OptimalBits/redbird","last_synced_at":"2025-03-22T01:31:08.826Z","repository":{"id":19402888,"uuid":"22644637","full_name":"OptimalBits/redbird","owner":"OptimalBits","description":"A modern reverse proxy for node","archived":false,"fork":false,"pushed_at":"2024-09-30T08:57:11.000Z","size":861,"stargazers_count":4419,"open_issues_count":116,"forks_count":280,"subscribers_count":71,"default_branch":"master","last_synced_at":"2025-03-19T03:34:41.928Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/OptimalBits.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-08-05T13:33:11.000Z","updated_at":"2025-03-17T23:37:42.000Z","dependencies_parsed_at":"2024-09-27T04:50:00.063Z","dependency_job_id":"df45fd4a-e00c-47ac-812c-78c75e9def32","html_url":"https://github.com/OptimalBits/redbird","commit_stats":{"total_commits":353,"total_committers":50,"mean_commits":7.06,"dds":"0.30594900849858353","last_synced_commit":"d7ad964bf4ea9d261188daf2d2aba7801780ec2a"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OptimalBits%2Fredbird","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OptimalBits%2Fredbird/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OptimalBits%2Fredbird/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OptimalBits%2Fredbird/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OptimalBits","download_url":"https://codeload.github.com/OptimalBits/redbird/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244893420,"owners_count":20527586,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T05:01:22.872Z","updated_at":"2025-03-22T01:31:08.199Z","avatar_url":"https://github.com/OptimalBits.png","language":"TypeScript","readme":"# Redbird Reverse Proxy\n\n\u003cdiv align=\"center\"\u003e\n  \u003cbr/\u003e\n  \u003cimg src=\"https://github.com/user-attachments/assets/f53820d4-96bc-4d94-b0a6-89ac0ae900df\" width=\"500\" /\u003e\n  \u003cbr/\u003e\n  \u003cbr/\u003e\n  \u003cp\u003e\n    It should be easy and robust to handle dynamic virtual hosts, load balancing, proxying web sockets and SSL encryption.\n    With Redbird you get a lightweight and flexible library to build dynamic reverse proxies with the speed and robustness of http-proxy.\n    Redbird includes everything you need for easy reverse routing of your applications.\n    Great for routing many applications from different domains in one single host, handling SSL with ease, etc.\n  \u003c/p\u003e\n  \u003cbr/\u003e\n  \u003cbr/\u003e\n  \u003cp\u003e \n    \u003ca href=\"https://badge.fury.io/js/redbird\"\u003e\n      \u003cimg src=\"https://badge.fury.io/js/redbird.svg\"/\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/semantic-release/semantic-release\"\u003e\n      \u003cimg src=\"https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg\"/\u003e\n    \u003c/a\u003e\n  \u003c/p\u003e\n  \u003cp\u003e\n    \u003cem\u003eFollow \u003ca href=\"https://twitter.com/manast\"\u003e@manast\u003c/a\u003e for *important* Redbird news and updates!\u003c/em\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\n## Features\n\n- Flexible and easy routing\n- Websockets\n- Seamless SSL Support (HTTPS -\u003e HTTP proxy)\n- Automatic HTTP to HTTPS redirects\n- Automatic TLS Certificates generation and renewal using LetsEncrypt\n- Supports HTTP2\n- Load balancer\n- Register and unregister routes programmatically without restart (allows zero downtime deployments)\n- Docker support for automatic registration of running containers\n- Cluster support that enables automatic multi-process\n- Based on top of rock-solid node-http-proxy and battle tested on production in many sites\n- Optional logging, with Pino.\n\n## Install\n\n```sh\nnpm install redbird\n```\n\n## Example\n\nYou can programmatically register or unregister routes dynamically even if the proxy is already running:\n\n```js\nvar proxy = require('redbird')({ port: 80 });\n\n// OPTIONAL: Setup your proxy but disable the X-Forwarded-For header\nvar proxy = require('redbird')({ port: 80, xfwd: false });\n\n// Route to any global ip\nproxy.register('optimalbits.com', 'http://167.23.42.67:8000');\n\n// Route to any local ip, for example from docker containers.\nproxy.register('example.com', 'http://172.17.42.1:8001');\n\n// Route from hostnames as well as paths\nproxy.register('example.com/static', 'http://172.17.42.1:8002');\nproxy.register('example.com/media', 'http://172.17.42.1:8003');\n\n// Subdomains, paths, everything just works as expected\nproxy.register('abc.example.com', 'http://172.17.42.4:8080');\nproxy.register('abc.example.com/media', 'http://172.17.42.5:8080');\n\n// Route to any href including a target path\nproxy.register('foobar.example.com', 'http://172.17.42.6:8080/foobar');\n\n// You can also enable load balancing by registering the same hostname with different\n// target hosts. The requests will be evenly balanced using a Round-Robin scheme.\nproxy.register('balance.me', 'http://172.17.40.6:8080');\nproxy.register('balance.me', 'http://172.17.41.6:8080');\nproxy.register('balance.me', 'http://172.17.42.6:8080');\nproxy.register('balance.me', 'http://172.17.43.6:8080');\n\n// You can unregister routes as well\nproxy.register('temporary.com', 'http://172.17.45.1:8004');\nproxy.unregister('temporary.com', 'http://172.17.45.1:8004');\n\n// LetsEncrypt support\n// With Redbird you can get zero conf and automatic SSL certificates for your domains\nredbird.register('example.com', 'http://172.60.80.2:8082', {\n  ssl: {\n    letsencrypt: {\n      email: 'john@example.com', // Domain owner/admin email\n      production: true, // WARNING: Only use this flag when the proxy is verified to work correctly to avoid being banned!\n    },\n  },\n});\n\n//\n// LetsEncrypt requires a minimal web server for handling the challenges, this is by default on port 3000\n// it can be configured when initiating the proxy. This web server is only used by Redbird internally so most of the time\n// you  do not need to do anything special other than avoid having other web services in the same host running\n// on the same port.\n\n//\n// HTTP2 Support using LetsEncrypt for the certificates\n//\nvar proxy = require('redbird')({\n  port: 80, // http port is needed for LetsEncrypt challenge during request / renewal. Also enables automatic http-\u003ehttps redirection for registered https routes.\n  letsencrypt: {\n    path: __dirname + '/certs',\n    port: 9999, // LetsEncrypt minimal web server port for handling challenges. Routed 80-\u003e9999, no need to open 9999 in firewall. Default 3000 if not defined.\n  },\n  ssl: {\n    http2: true,\n    port: 443, // SSL port used to serve registered https routes with LetsEncrypt certificate.\n  },\n});\n```\n\n## About HTTPS\n\nThe HTTPS proxy supports virtual hosts by using SNI (which most modern browsers support: IE7 and above).\nThe proxying is performed by hostname, so you must use the same SSL certificates for a given hostname independently of its paths.\n\n### LetsEncrypt\n\nSome important considerations when using LetsEncrypt. You need to agree to LetsEncrypt [terms of service](https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf). When using\nLetsEncrypt, the obtained certificates will be copied to disk to the specified path. Its your responsibility to backup, or save persistently when applicable. Keep in mind that these certificates needs to be handled with care so that they cannot be accessed by malicious users. The certificates will be renewed by default one month before expiration, forever.\n\n## HTTPS Example using your own certificates\n\n(NOTE: This is a legacy example not needed when using LetsEncrypt)\n\nConceptually HTTPS is easy, but it is also easy to struggle getting it right. With Redbird its straightforward, check this complete example:\n\n1. Generate a localhost development SSL certificate:\n\n```sh\n/certs $ openssl genrsa -out dev-key.pem 1024\n/certs $ openssl req -new -key dev-key.pem -out dev-csr.pem\n\n// IMPORTANT: Do not forget to fill the field! Common Name (e.g. server FQDN or YOUR name) []:localhost\n\n/certs $ openssl x509 -req -in dev-csr.pem -signkey dev-key.pem -out dev-cert.pem\n\n```\n\nNote: For production sites you need to buy valid SSL certificates from a trusted authority.\n\n2. Create a simple redbird based proxy:\n\n```js\nvar redbird = new require('redbird')({\n  port: 8080,\n\n  // Specify filenames to default SSL certificates (in case SNI is not supported by the\n  // user's browser)\n  ssl: {\n    port: 8443,\n    key: 'certs/dev-key.pem',\n    cert: 'certs/dev-cert.pem',\n  },\n});\n\n// Since we will only have one https host, we dont need to specify additional certificates.\nredbird.register('localhost', 'http://localhost:8082', { ssl: true });\n```\n\n3. Test it:\n\nPoint your browser to `localhost:8000` and you will see how it automatically redirects to your https server and proxies you to\nyour target server.\n\nYou can define many virtual hosts, each with its own SSL certificate. And if you do not define any, they will use the default one\nas in the example above:\n\n```js\nredbird.register('example.com', 'http://172.60.80.2:8082', {\n  ssl: {\n    key: '../certs/example.key',\n    cert: '../certs/example.crt',\n    ca: '../certs/example.ca',\n  },\n});\n\nredbird.register('foobar.com', 'http://172.60.80.3:8082', {\n  ssl: {\n    key: '../certs/foobar.key',\n    cert: '../certs/foobar.crt',\n  },\n});\n```\n\nYou can also specify https hosts as targets and also specify if you want the connection to the target host to be secure (default is true).\n\n```js\nvar redbird = require('redbird')({\n  port: 80,\n  secure: false,\n  ssl: {\n    port: 443,\n    key: '../certs/default.key',\n    cert: '../certs/default.crt',\n  },\n});\nredbird.register('tutorial.com', 'https://172.60.80.2:8083', {\n  ssl: {\n    key: '../certs/tutorial.key',\n    cert: '../certs/tutorial.crt',\n  },\n});\n```\n\nEdge case scenario: you have an HTTPS server with two IP addresses assigned to it and your clients use old software without SNI support. In this case, both IP addresses will receive the same fallback certificate. I.e. some of the domains will get a wrong certificate. To handle this case you can create two HTTPS servers each one bound to its own IP address and serving the appropriate certificate.\n\n```js\nvar redbird = new require('redbird')({\n  port: 8080,\n\n  // Specify filenames to default SSL certificates (in case SNI is not supported by the\n  // user's browser)\n  ssl: [\n    {\n      port: 443,\n      ip: '123.45.67.10', // assigned to tutorial.com\n      key: 'certs/tutorial.key',\n      cert: 'certs/tutorial.crt',\n    },\n    {\n      port: 443,\n      ip: '123.45.67.11', // assigned to my-other-domain.com\n      key: 'certs/my-other-domain.key',\n      cert: 'certs/my-other-domain.crt',\n    },\n  ],\n});\n\n// These certificates will be served if SNI is supported\nredbird.register('tutorial.com', 'http://192.168.0.10:8001', {\n  ssl: {\n    key: 'certs/tutorial.key',\n    cert: 'certs/tutorial.crt',\n  },\n});\nredbird.register('my-other-domain.com', 'http://192.168.0.12:8001', {\n  ssl: {\n    key: 'certs/my-other-domain.key',\n    cert: 'certs/my-other-domain.crt',\n  },\n});\n```\n\n## Docker support\n\nIf you use docker, you can tell Redbird to automatically register routes based on image\nnames. You register your image name and then every time a container starts from that image,\nit gets registered, and unregistered if the container is stopped. If you run more than one\ncontainer from the same image, Redbird will load balance following a round-robin algorithm:\n\n```js\nvar redbird = require('redbird')({\n  port: 8080,\n});\n\nvar docker = require('redbird').docker;\ndocker(redbird).register('old.api.com', 'company/api:v1.0.0');\ndocker(redbird).register('stable.api.com', 'company/api:v2.*');\ndocker(redbird).register('preview.api.com', 'company/api:v[3-9].*');\n```\n\n## etcd backend\n\nRedbird can use [node-etcd](https://github.com/stianeikeland/node-etcd) to automatically create proxy records from an etcd cluster. Configuration\nis accomplished by passing an array of [options](https://github.com/stianeikeland/node-etcd#constructor-options), plus the hosts and path variables,\nwhich define which etcd cluster hosts, and which directory within those hosts, that Redbird should poll for updates.\n\n```js\nvar redbird = require('redbird')({\n  port:8080\n});\n\nvar options = {\n  hosts: ['localhost:2379'], // REQUIRED - you must define array of cluster hosts\n\tpath: ['redbird'], // OPTIONAL - path to etcd keys\n\t... // OPTIONAL - pass in node-etcd connection options\n}\nrequire('redbird').etcd(redbird,options);\n```\n\netcd records can be created in one of two ways, either as a target destination pair:\n`/redbird/example.com\t\t\t\"8.8.8.8\"`\nor by passing a JSON object containing multiple hosts, and Redbird options:\n\n```\n/redbird/derek.com\t\t\t\t{ \"hosts\" : [\"10.10.10.10\", \"11.11.11.11\"]}\n/redbird/johnathan.com    { \"ssl\" : true }\n/redbird/jeff.com         { \"docker\" : \"alpine/alpine:latest\" }\n```\n\n## Cluster support\n\nRedbird supports automatic node cluster generation. To use, just specify the number\nof processes that you want Redbird to use in the options object. Redbird will automatically\nrestart any thread that crashes, increasing reliability.\n\n```js\nvar redbird = new require('redbird')({\n  port: 8080,\n  cluster: 4,\n});\n```\n\n## NTLM support\n\nIf you need NTLM support, you can tell Redbird to add the required header handler. This\nregisters a response handler which makes sure the NTLM auth header is properly split into\ntwo entries from http-proxy.\n\n```js\nvar redbird = new require('redbird')({\n  port: 8080,\n  ntlm: true,\n});\n```\n\n## Custom Resolvers\n\nWith custom resolvers, you can decide how the proxy server handles request. Custom resolvers allow you to extend Redbird considerably. With custom resolvers, you can perform the following:\n\n- Do path-based routing.\n- Do headers based routing.\n- Do wildcard domain routing.\n- Use variable upstream servers based on availability, for example in conjunction with Etcd or any other service discovery platform.\n- And more.\n\nResolvers should be:\n\n1. Be invokable function. The `this` context of such function is the Redbird Proxy object. The resolver function takes in two parameters : `host` and `url`\n2. Have a priority, resolvers with higher priorities are called before those of lower priorities. The default resolver, has a priority of 0.\n3. A resolver should return a route object or a string when matches it matches the parameters passed in. If string is returned, then it must be a valid upstream URL, if object, then the object must conform to the following:\n\n```\n  {\n     url: string or array of string [required], when array, the urls will be load-balanced across.\n     path: path prefix for route, [optional], defaults to '/',\n     opts: {} // Redbird target options, see Redbird.register() [optional],\n  }\n```\n\n### Defining Resolvers\n\nResolvers can be defined when initializing the proxy object with the `resolvers` parameter. An example is below:\n\n```javascript\n// for every URL path that starts with /api/, send request to upstream API service\nconst customResolver1 = {\n  fn: (host, url, req)=\u003e {\n  if (/^\\/api\\//.test(url)) {\n    return 'http://127.0.0.1:8888';\n  },\n  priority: 100\n};\n}\nvar proxy = new require('redbird')({\n  port: 8080,\n  resolvers: [\n    customResolver1,\n  ],\n});\n```\n\n### Adding and Removing Resolvers at Runtime.\n\nYou can add or remove resolvers at runtime, this is useful in situations where your upstream is tied to a service discovery service system.\n\n```javascript\nvar topPriority = function (host, url, req) {\n  return /app\\.example\\.com/.test(host)\n    ? {\n        // load balanced\n        url: ['http://127.0.0.1:8000', 'http://128.0.1.1:9999'],\n      }\n    : null;\n};\n\nproxy.addResolver(topPriority, 200);\n\n// remove top priority after 10 minutes,\nsetTimeout(function () {\n  proxy.removeResolver(topPriority);\n}, 600000);\n```\n\n## Replacing the default HTTP/HTTPS server modules\n\nBy passing `serverModule: module` or `ssl: {serverModule : module}` you can override the default http/https\nservers used to listen for connections with another module.\n\nOne application for this is to enable support for PROXY protocol: This is useful if you want to use a module like\n[findhit-proxywrap](https://github.com/findhit/proxywrap) to enable support for the\n[PROXY protocol](http://www.haproxy.org/download/1.8/doc/proxy-protocol.txt).\n\nPROXY protocol is used in tools like HA-Proxy, and can be optionally enabled in Amazon ELB load balancers to pass the\noriginal client IP when proxying TCP connections (similar to an X-Forwarded-For header, but for raw TCP). This is useful\nif you want to run redbird on AWS behind an ELB load balancer, but have redbird terminate any HTTPS connections so you\ncan have SNI/Let's Encrypt/HTTP2support. With this in place Redbird will see the client's IP address rather\nthan the load-balancer's, and pass this through in an X-Forwarded-For header.\n\n```javascript\n//Options for proxywrap. This means the proxy will also respond to regular HTTP requests without PROXY information as well.\nproxy_opts = { strict: false };\nproxyWrap = require('findhit-proxywrap');\nvar opts = {\n  port: process.env.HTTP_PORT,\n  serverModule: proxyWrap.proxy(require('http'), proxy_opts),\n  ssl: {\n    //Do this if you want http2:\n    http2: true,\n    serverModule: proxyWrap.proxy(require('spdy').server, proxy_opts),\n    //Do this if you only want regular https\n    // serverModule: proxyWrap.proxy( require('http'), proxy_opts),\n    port: process.env.HTTPS_PORT,\n  },\n};\n\n// Create the proxy\nvar proxy = require('redbird')(opts);\n```\n\n## Roadmap\n\n- Statistics (number of connections, load, response times, etc)\n- Rate limiter.\n- Simple IP Filtering.\n- Automatic routing via Redis.\n\n## Reference\n\n[constructor](#redbird)\n[register](#register)\n[unregister](#unregister)\n[notFound](#notFound)\n[close](#close)\n\n\u003ca name=\"redbird\"/\u003e\n\n### Redbird(opts)\n\nThis is the Proxy constructor. Creates a new Proxy and starts listening to\nthe given port.\n\n**Arguments**\n\n```\n    opts {Object} Options to pass to the proxy:\n    {\n    \tport: {Number} // port number that the proxy will listen to.\n    \tssl: { // Optional SSL proxying.\n    \t\tport: {Number} // SSL port the proxy will listen to.\n    \t\t// Default certificates\n    \t\tkey: keyPath,\n    \t\tcert: certPath,\n    \t\tca: caPath // Optional.\n        \tredirectPort: port, // optional https port number to be redirected if entering using http.\n            http2: false, //Optional, setting to true enables http2/spdy support\n            serverModule : require('https') // Optional, override the https server module used to listen for https or http2 connections.  Default is require('https') or require('spdy')\n    \t}\n        bunyan: {Object} Bunyan options. Check [bunyan](https://github.com/trentm/node-bunyan) for info.\n        If you want to disable bunyan, just set this option to false. Keep in mind that\n        having logs enabled incours in a performance penalty of about one order of magnitude per request.\n        resolvers: {Function | Array}  a list of custom resolvers. Can be a single function or an array of functions. See more details about resolvers above.\n        serverModule : {Module} Optional - Override the http server module used to listen for http connections.  Default is require('http')\n\t}\n```\n\n---\n\n\u003ca name=\"register\"/\u003e\n\n#### Redbird::register(src, target, opts)\n\nRegister a new route. As soon as this method is called, the proxy will\nstart routing the sources to the given targets.\n\n**Arguments**\n\n```javascript\n    src {String} {String|URL} A string or a url parsed by node url module.\n    \tNote that port is ignored, since the proxy just listens to one port.\n\n    target {String|URL} A string or a url parsed by node url module.\n    opts {Object} route options:\n    examples:\n    {ssl : true} // Will use default ssl certificates.\n    {ssl: {\n        redirect: true, // False to disable HTTPS autoredirect to this route.\n    \tkey: keyPath,\n    \tcert: certPath,\n    \tca: caPath, // optional\n    \tsecureOptions: constants.SSL_OP_NO_TLSv1 //optional, see below\n    \t}\n    }\n    {onRequest: (req, res, target) =\u003e {\n      // called before forwarding is occurred, you can modify req.headers for example\n      // return undefined to forward to default target\n    }}\n```\n\n\u003e _Note: if you need to use **ssl.secureOptions**, to disable older, insecure TLS versions, import crypto/constants first:_\n\n\u003e `const { constants } = require('crypto')`\n\n---\n\n\u003ca name=\"unregister\"/\u003e\n\n#### Redbird.unregister(src, [target])\n\nUnregisters a route. After calling this method, the given route will not\nbe proxied anymore.\n\n**Arguments**\n\n```javascript\n    src {String|URL} A string or a url parsed by node url module.\n    target {String|URL} A string or a url parsed by node url module. If not\n    specified, it will unregister all routes for the given source.\n```\n\n---\n\n\u003ca name=\"notFound\"/\u003e\n\n#### Redbird.notFound(callback)\n\nGives Redbird a callback function with two parameters, the HTTP request\nand response objects, respectively, which will be called when a proxy route is\nnot found. The default is\n\n```javascript\n    function(req, res){\n      res.statusCode = 404;\n      res.write('Not Found');\n      res.end();\n    };\n```\n\n.\n\n**Arguments**\n\n```javascript\n    src {Function(req, res)} The callback which will be called with the HTTP\n      request and response objects when a proxy route is not found.\n```\n\n---\n\n\u003ca name=\"close\"/\u003e\n\n#### Redbird.close()\n\nClose the proxy stopping all the incoming connections.\n\n---\n","funding_links":[],"categories":["JavaScript","TypeScript","Typescript / Javascript","Software","HarmonyOS","Apps","Proxy","\u003ca name=\"TypeScript\"\u003e\u003c/a\u003eTypeScript"],"sub_categories":["Proxy","Windows Manager","Networking","Booking and Scheduling","Video Streaming"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FOptimalBits%2Fredbird","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FOptimalBits%2Fredbird","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FOptimalBits%2Fredbird/lists"}