/** * connect-slashes * Trailing slash redirect middleware for Connect * https://github.com/avinoamr/connect-slashes * * The MIT License * * Copyright (c) 2010-2012 Roi Avinoam and connect-slashes authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ // Only create RegExp objects once var reQuery = /[\?\&]+/; var reDoubleSlashes = /(\/\/+)/; var slashes = function( append, options ) { options = options || {}; ( append === false ) || ( append = true ); // default to append slashes mode return function slashes( req, res, next ) { if ( "GET" == req.method || "HEAD" == req.method || "OPTIONS" == req.method ) { // Use originalUrl when defined ( for express compatibility); var url = (req.originalUrl || req.url).split( reQuery ) , location = url[ 0 ] , redirect , headers; if ( append && "/" != location[ location.length - 1 ] ) { // append slashes redirect = location + "/"; } else if ( !append && "/" == location[ location.length - 1 ] && "/" != location ) { // remove slashes redirect = location.slice( 0, location.length - 1 ); } // complete the redirect url if ( redirect ) { if ( url.length > 1 ) { redirect += "?" + url.slice( 1 ).join( "&" ); } redirect = ( options.base || "" ) + redirect; // prepend the base path redirect = redirect.replace( reDoubleSlashes, "/" ); // see issue #2 if ( "/" != redirect[ 0 ] ) { redirect = "/" + redirect; // guarantee absolute redirect } headers = options.headers || {}; headers[ "Location" ] = redirect; res.writeHead( options.code || 301, headers ); res.end(); return; } } next(); }; }; // module.exports = slashes;