Why does my browser always want to go to port 8000 after bouncy redirects it there once?

382 Views Asked by At

I have an AWS EC2 instance (Windows Server 2022 Datacenter) where I host a website for my music mixes:

http://www.shahspace.com/music mixes/

It's hosted by node.js. Everything works fine except that once in a while, it seems to want to browse the directory instead of render the page.

enter image description here

I did some experimenting and I found out that this happens whenever I attempt to go to my ASP.NET application also under www.shahspace.com (I won't post the exact url as it contains sensitive information but let's call it http://www.shahspace.com/asp.net/. I can fix it by restarting the node.js service. In other words, www.shahspace.com has two different (maybe conflicting) hosting platform: IIS and Node.js.

IIS hosts http://www.shahspace.com/asp.net/ at the path C:\inetpub\wwwroot\shahspace.com\asp.net\ where my ASP.NET application sits. Node.js runs at the path C:\inetpub\wwwroot\ and serves the music mixes landing page from C:\inetpub\wwwroot\music mixes\views\index.hbs. I have it setup like this because I want node.js to be the main hub through which all inbound traffic on port 80 is routed. And since the ASP.NET application is, well, an ASP.NET application, I also need IIS to be the hosting platform for that site which node.js delegates requests to as appropriate.

I have one active inbound rule setup for port 80 in my firewall, and in AWS, I have the same:

enter image description here

IIS has only the default website pointing to C:\inetpub\wwwroot\shahspace.com\asp.net\ and listens on port 8000:

enter image description here

This is what the node.js service looks like:

const bouncy = require('bouncy');
const express = require('express');
const path = require('path');
const { create, engine } = require('express-handlebars');

bouncy(function(req, bounce) {
    const host = req.headers.host;
    if (host === 'shahspace.com' || host === 'www.shahspace.com') {
        if (req.url.includes('/music%20mixes/')) bounce(8002);
        else bounce(8000);
    }
    
    // other domains get bounced to their own respective ports

}).listen(80);
    
const musicMixApp = express();
musicMixApp.engine('.hbs', engine({
    extname: 'hbs',
    defaultLayout: false
}));
musicMixApp.set('view engine', 'hbs');
musicMixApp.set('views', path.join(__dirname, 'shahspace.com/music mixes/views'));

musicMixApp.get('/music%20mixes', (req, res) => {
    const folders = getMixFolders();
    res.render('index', { folders });
});
musicMixApp.get('/music%20mixes/:mix', (req, res) => {
    const mixName = req.params.mix;
    const playlist = getPlaylist(mixName);
    res.render('mix', {
        mixName: mixName.substring(3, mixName.length),
        playlist
    });
});
musicMixApp.get('/music%20mixes/:mix/:mp3', (req, res) => {
    const mix = req.params.mix;
    const mp3 = req.params.mp3;
    res.sendFile(`${__dirname}/shahspace.com/music mixes/${mix}/${mp3}`);
});

musicMixApp.listen(8002);

function getMixFolders() {
    const { readdirSync, statSync } = require('fs');
    
    const mixPath = './shahspace.com/music mixes/';
    const folderInfo = readdirSync(mixPath, { withFileTypes: true })
        .filter(item => item.isDirectory() && item.name !== 'views')
        .map(folder => folder.name)
        .sort((f1, f2) => f1 < f2 ? 1 : -1);
    
    return folderInfo.map(folder => ({
        number: folder.substring(0, 2),
        name: folder.substring(3, folder.length)
    }));
}

function getPlaylist(mixName) {
    if (!mixName) return [];

    const { readdirSync } = require('fs');

    let songs = [];
    try {
        songs = readdirSync(`./shahspace.com/music mixes/${mixName}`, { withFileTypes: true })
            .filter(item => item.name.endsWith('.mp3'));
    } catch (err) {
        return [];
    }

    return songs.map(song => song.name.substring(0, song.name.length - 4));
}

The main thing to look at is the call to bouncy(). What it says is, if the request coming in on port 80 is "shahspace.com" and specifically "shahspace.com/music mixes", then redirect to port 8002, where the musicMixApp is listening. Otherwise, if it's "shahspace.com" but NOT "shahspace.com/music mixes/", then redirect to port 8000 (where my ASP.NET site is listening as determined by the IIS settings for the default website site).

Essentially, this means the node.js server is the only one listening on port 80 and redirects to the appropriate port based on the specified host (determined by req.headers.host). I route to port 8002 for my music mix app and port 8000 for anything under www.shahspace.com that isn't my music mix app. All other domains (i.e. www.not_shahspace.com) are routed to other ports. I do all this with bouncy and bouncy itself listens on port 80.

I don't know if all the above is relevant to the issue I'm experiencing. All I know is that when I go to my ASP.NET site, then back to my music mix app (or just refresh it if it's already open), it attempts to browse the directory instead of loading index.hbs under the views holder. I do know this: if you look at the screen shot of the 403.13 error above, it shows that it's attempting to connect on port 8000. And when I add console logs into the node.js service (where bouncy does its work), it doesn't print anything. So strangely, it seems to go to port 80 before I go to my ASP.NET site and bouncy does its magic, but then after I go to my ASP.NET site and refresh the page on my music mix site (or go to it in a new browser tab), it seems to want to go to port 8000 directly (bypassing bouncy). IOW, it gets IIS to handle the request instead of node.js since IIS is listening on port 8000, and since IIS has directory browsing disabled and there is no index.html at the music mixes folder, I get the 403.13 error.

Enabling directory browsering isn't the answer, of course, as I want to serve up the page rather than allow the user to browse the directory.

If anyone can suggest why this is happening and/or how to solve the problem, it would be much appreciated. Thank you.

UPDATE

I followed samwu's suggest and got request failure tracing to work. I replicated the error and got a full report of what it traced. Now I need someone to help me interpret it. Or maybe not. From what I can tell, the error is that the request is coming in on port 8000 from the get-go, which it shouldn't. It should come in on port 80.

enter image description here

The actual 403.14 error occurs on the 176th row:

enter image description here

But that's no mystery at this point. It's failing to browse the directory because I have directory browsing disabled. And I want that. The question is, why is it coming in on port 8000 rather than 80? Why does running my ASP.NET application (which is on port 8000) cause all subsequent requests to www.shahspace.com/music mixes/ to also be on port 8000?

0

There are 0 best solutions below