jdotjdot
jdotjdot

Reputation: 17042

Using path.join on NodeJS on Windows to create URL

I have two dynamic pieces of a URL that I'm trying to join together to make a full URL. Since I don't know the exact strings I'll be joining, I want to use a path-joining library to avoid string-joining errors like "http://www.mysite.com/friends//12334.html", which has an extra slash, etc.

I am working on a Windows 7 Home computer using Node.js.

I tried using the path library's path.join(...), but because I am on Windows, it turned all of the forward slashes backwards, which is obviously incorrect for a URL. Example:

var path = require('path'),
    joined = path.join('http://www.mysite.com/', '/friends/family');

console.log(joined);
// Prints:
// http:\www.miserable.com\friends\family

What function or library can I use to join pieces of a URL together on Windows? Alternatively, how can I get path.join to force UNIX-style separators rather than those of Windows?

Upvotes: 8

Views: 9036

Answers (3)

P. Roebuck
P. Roebuck

Reputation: 41

...how can I get path.join to force UNIX-style separators rather than those of Windows?

While (as @ebohlman noted) URLs aren't filesystem paths, path.posix.join() could be used to create the URL.pathname component.

const path = require('path');
const url = require('url');

const origin = 'http://www.example.com/';
const pathname = path.posix.join(path.posix.sep, 'friends', 'family');

// All at once...
const myURL = new URL(pathname, origin);
console.log(myURL.href);
// => 'http://www.example.com/friends/family'

// In steps...
const myURL2 = new URL(origin);
console.log(myURL2.href);
// => 'http://www.example.com/'
myURL2.pathname = pathname;
console.log(myURL2.href);
// => 'http://www.example.com/friends/family'

Upvotes: 4

blak3r
blak3r

Reputation: 16516

url.resolve isn't what I thought it'd be at first glance... Notice how dir1 is dropped in 2nd example

url.resolve('/one/two/three', 'four')         // '/one/two/four'
url.resolve('http://domain.com/dir1', 'dir2');   // 'http://domain.com/dir2  (dir1 is gone!)

Here's a simple join method I wrote:

    var _s = require('underscore.string');
    /**
     * Joins part1 and part2 with optional separator (defaults to '/'),
     * and adds the optional prefix to part1 if specified 
     * 
     * @param {string} part1
     * @param {string} part2
     * @param {string} [separator] - defaults to '/'
     * @param {string} [prefix] - defaults to empty... pass in "http://" for urls if part1 might not already have it.
     * @returns {string}
     */
    exports.joinWith = function(part1, part2, separator, prefix) {
        var join = "";
        var separatorsFound = 0;

        if( !separator) { separator = "/"; }
        if( !prefix ) { prefix = ""; }

        if( _s.endsWith( part1, separator ) ) { separatorsFound += 1; }
        if( _s.startsWith( part2, separator) ) { separatorsFound += 1; }

        // See if we need to add a join separator or remove one (if both have it already)
        if( separatorsFound === 0 ) { join = separator; }
        else if( separatorsFound === 2 ) { part1 = part1.substr(0, part1.length - separator.length ); }

        // Check if prefix is already set
        if( _s.startsWith( part1, prefix ) ) { prefix = ""; }

        return prefix + part1 + join + part2;
    }

Sample:

// TEST
console.log( exports.joinWith('../something', 'else') );
console.log( exports.joinWith('../something/', 'else') );

console.log( exports.joinWith('something', 'else', "-") );
console.log( exports.joinWith('something', 'up', "-is-") );
console.log( exports.joinWith('something-is-', 'up', "-is-") );

console.log( exports.joinWith('../something/', '/else') );
console.log( exports.joinWith('../something/', '/else', "/") );
console.log( exports.joinWith('somedomain.com', '/somepath', "/") );
console.log( exports.joinWith('somedomain.com', '/somepath', "/", "http://") );

console.log( exports.joinWith('', '/somepath', "/") );

OUTPUT:

../something/else
../something/else
something-else
something-is-up
something-is-up
../something/else
../something/else
somedomain.com/somepath
http://somedomain.com/somepath
/somepath

Upvotes: 2

ebohlman
ebohlman

Reputation: 15003

URLs aren't filesystem paths, so nothing in path is applicable to your requirements. I'd suggest using url.resolve() if it meets your needs, or url.format() if not. Note that you can't simply substitute either for path.join() in your code, since they require different arguments. Read the documentation carefully.

Upvotes: 5

Related Questions