Sunday, 12 March 2017

Location of Index Changes if Loading from a Route with Trailing Slash

I have a public directory which holds my bower components, stylesheets, and js files. All of my views are rendered server side with ejs and fed via routes. I load the partials from my ngroute and everything works as expected. However if I try and load something with a trailing "/" or any string after the slash, the ngroute will no longer redirect to the 404 page, but instead will change the location of index that is loaded. This is easiest to see in the console of the server (ignore the favicon.ico calls).

this is what happens when you load with a trailing slash

localhost:8080/login through address bar

The magic happens on port 8080
GET / 304 17.814 ms - -
GET /partials/homepage 304 30.868 ms - -
GET /favicon.ico 204 1.351 ms - -
loading index
GET /login/ 304 12.520 ms - -
loading index
loading index
loading index
loading index
GET /login/js/module.js 304 6.756 ms - -
GET /login/js/config.js 304 5.081 ms - -
GET /login/js/controllers/account.js 304 2.985 ms - -
GET /login/js/components/tournament.js 304 1.364 ms - -
GET /favicon.ico 204 0.455 ms - - 

and this is what happens, when you load without a trailing slash. This results in the page being loaded successfully.

localhost:8080/login/ through address bar

The magic happens on port 8080
GET / 304 54.692 ms - -
GET /partials/homepage 304 4.255 ms - -
GET /favicon.ico 204 1.338 ms - -
loading index
GET /login 304 1.847 ms - -
GET /partials/login 304 1.062 ms - -
GET /favicon.ico 204 0.499 ms - -

In both cases I loaded the websites homepage first, and then I manually typed in the url and pressed enter. If you use a hyperlink (so you don't have to reload index) to access a directly with a trailing slash this is the result. This brings me to the correct login page.

localhost:8080/login/ through hyperlink on homepage

The magic happens on port 8080
GET / 304 92.836 ms - -
GET /partials/homepage 200 4.227 ms - 490
GET /favicon.ico 204 0.791 ms - -
GET /partials/login 304 1.270 ms - -
GET /favicon.ico 204 0.905 ms - -

Below are the important files...

server.js

let express  = require('express');
let app      = express();
let mongoose = require('mongoose');
mongoose.Promise = require('bluebird');
let passport = require('passport');
let flash    = require('connect-flash');
let path = require('path');

let morgan       = require('morgan');
let cookieParser = require('cookie-parser');
let bodyParser   = require('body-parser');
let session      = require('express-session');

let configDB = require('./config/database.js');
let configNetwork = require('./config/network.js');
let configAuth = require('./config/auth.js');

mongoose.connect(configDB.url);

app.use(express.static(__dirname + '/public'));
app.use('/bower_components',  express.static(__dirname + '/bower_components'));

app.use(morgan('dev'));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.set('view engine', 'ejs');

require('./config/passport')(passport);
app.use(session({
    secret: configAuth.sessionSecret,
    resave: true,
    saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());

require('./routes/users.js')(app, passport);
require('./routes/tournament.js')(app);
require('./routes/index.js')(app);
//must be loaded as last route
app.get('*', function (req, res) {
    console.log("loading index");
    res.render('index');
});

let port = process.env.PORT || configNetwork.port;
app.listen(port);
console.log('The magic happens on port ' + port);

./routes/index.js

module.exports = function(app) {

    app.get('/', function (req, res) {
        res.render('index');
    });

    app.get('/component_loader/:template', function (req, res) {
        console.log(req.params.template);
        res.render('partials/component_loader',{ template: req.params.template });
    });

    app.get('/favicon.ico', function(req, res) {
        res.sendStatus(204);
    });

    app.get('/partials/404',function (req, res) {
        res.render('partials/404');
    });

    app.get('/partials/homepage',function (req, res) {
        res.render('partials/homepage');
    });

    app.get('/partials/login', function(req, res) {
        res.render('partials/login',{ message: req.flash('loginMessage') });
    });

    app.get('/partials/signup', function(req, res) {
        res.render('partials/signup',{ message: req.flash('signupMessage') });
    });

    app.get('/partials/tournament', function(req, res) {
        res.render('partials/tournament');
    });

    app.get('/partials/account', function(req, res) {
        console.log("authenticating");
        if (req.isAuthenticated()) {
            res.render('partials/account',{ message: req.flash('challongeUpdate') });
        } else {
            res.render('partials/login',{ message: req.flash('loginMessage') })
        }
    });
};

index.ejs

<!doctype html>
<html lang="en" ng-app="bracket-archive">
<head>
    <meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="A mathup and bracket tracking system">
    <meta name="keywords" content="super smash bros, melee, bracket, smashgg, challonge, matchup">
    <meta name="robots" content="index, follow">
    <meta name="revisit-after" content="7 days">
    <title>Bracket Archive</title>
    <link rel="stylesheet/less" type="text/css" href="/resources/less/bootswatch.less">
    <script src="/bower_components/jquery/dist/jquery.min.js"></script>
    <script src="/bower_components/angular/angular.min.js"></script>
    <script src="/bower_components/angular-route/angular-route.min.js"></script>
    <script src="/bower_components/less/dist/less.min.js"></script>
    <script src="/bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
    <script src="js/module.js"></script>
    <script src="js/config.js"></script>
    <script src="js/controllers/account.js"></script>
    <script src="js/components/tournament.js"></script>

    <base href="/">

    <style>
        body {
            padding-top: 80px;
        }
    </style>
</head>

<body>
<nav class="navbar navbar-default navbar-fixed-top">
    <div class="container">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="/">Bracket Archive</a>
        </div>
        <div class="collapse navbar-collapse" id="myNavbar">
            <ul class="nav navbar-nav navbar-right">
                <li><a href="/login">LOGIN</a></li>
                <li><a href="/signup">SIGNUP</a></li>
            </ul>
        </div>
    </div>
</nav>

<div ng-view></div>
</body>

</html>

js/config.js this is in in the public directory

angular.module('bracket-archive').config(['$locationProvider', '$routeProvider',
    function config($locationProvider, $routeProvider) {

        $routeProvider.when('/404', {
            templateUrl: '/partials/404'

        }).when('/', {
            templateUrl: '/partials/homepage'

        }).when('/signup', {
            templateUrl: '/partials/signup'

        }).when('/login', {
            templateUrl: '/partials/login'

        }).when('/tournament/:id', {
            templateUrl: '/component_loader/tournament'

        }).when('/account', {
            templateUrl: '/partials/account',
            controller: 'accountController'

        }).otherwise({
            redirectTo:  '/404'
        });

        // use the HTML5 History API
        $locationProvider.html5Mode({
            enabled: true,
            requireBase: false
        });
    }
]);
angular.module('bracket-archive').run(function ($rootScope) {
    $rootScope.$on('$locationChangeStart', function (event, next, current) {
        $(document).trigger('routeChange');
    });
});



via Christopher Powroznik

No comments:

Post a Comment