Skip to content

Commit

Permalink
Make ADDRESS option optional, determined automatically if not provided.
Browse files Browse the repository at this point in the history
The ADDRESS env variable is used for advertising the address of the service
only. If it is not provided, it can be determined automatically using the
HTTP Request headers 'Host' and 'X-Forwarded-*'. This approach uses ExpressJS
provided functionality but requires 'trusting' headers forwarded from proxies.

Deployers can control the trusted proxies using the TRUST_PROXY option,
documented in the code only as it's very edge-case.

This approach supports the best of both worlds; ADDRESS will use a logical
(probably accurate) value by default, but can be overridden in the case of
unusual proxy scenario or a canonical URL is preferred.
  • Loading branch information
jgroffen committed Jan 21, 2021
1 parent 9eabdc1 commit 70daca8
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 11 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ This is the relay server for CrewLink, an Among Us proximity voice chat program.
Optional environment variables:

- `PORT`: Specifies the port that the server runs on. Defaults to `443` if `HTTPS` is enabled, and `9736` if not.
- `ADDRESS` **(REQUIRED)**: Specifies the server domain
- `NAME`: Specifies the server name
- `ADDRESS` : Specifies the server domain. If not provided, `ADDRESS` is determined automatically (and possibly incorrectly) from HTTP Request headers.
- `NAME`: Specifies the server name.
- `HTTPS`: Enables https. You must place `privkey.pem` and `fullchain.pem` in your CWD.
- `SSLPATH`: Specifies an alternate path to SSL certificates.

Expand Down
39 changes: 30 additions & 9 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,46 @@ interface Signal {
to: string;
}

app.set('view engine', 'pug')
app.use(morgan('combined'))
app.set('view engine', 'pug');
app.use(morgan('combined'));

// TRUST_PROXY can be used to set which proxies can be trusted based on IP
// address. This is an advanced, undocumented environment variable.
// For more details see: https://expressjs.com/en/guide/behind-proxies.html
app.set('trust proxy', process.env.TRUST_PROXY ?? true );

let connectionCount = 0;
let address = process.env.ADDRESS;

/**
* Derives the address used from ExpressJS Request properties.
* The ExpressJS Request properties for hostname and protocol take into account
* the x-forwarded- parameters, so the resulting address is proxy friendly.
* @param req An HTTPRequest object.
*/
function addressFromRequest(req: express.Request) {
let p = ( 'x-forwarded-port' in req.headers ? req.headers['x-forwarded-port'] : port);
if ( p == '80' || p == '443' ) {
return `${req.protocol}://${req.hostname}`;
} else {
return `${req.protocol}://${req.hostname}:${p}`
}
}

if (!address) {
logger.error('You must set the ADDRESS environment variable.');
process.exit(1);
logger.info('ADDRESS environment variable not set.');
logger.info('Advertised server address will be derived from HTTP request headers.');
}

app.get('/', (_, res) => {
res.render('index', { connectionCount, address });
app.get('/', (req, res) => {
res.render('index', { connectionCount, address: (address || addressFromRequest(req)), headers: req.headers });
});

app.get('/health', (req, res) => {
res.json({
uptime: process.uptime(),
connectionCount,
address,
address: (address || addressFromRequest(req)),
name: process.env.NAME
});
})
Expand Down Expand Up @@ -168,5 +189,5 @@ io.on('connection', (socket: socketIO.Socket) => {

server.listen(port);
(async () => {
logger.info('CrewLink Server started: %s', address);
})();
logger.info('CrewLink Server started: %s', address || '[ADDRESS not set]');
})();

0 comments on commit 70daca8

Please sign in to comment.