Skip to content

Commit

Permalink
fix: Improve support for relative URLs (#78)
Browse files Browse the repository at this point in the history
- Create a shared parseUrl utility that will make sure to match the provided URL string to a url-parse instance
- Support for protocol-relative URLs (Resolves #76)
  • Loading branch information
offirgolan authored Jul 25, 2018
1 parent 4f845e5 commit 2c0083e
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 24 deletions.
15 changes: 2 additions & 13 deletions packages/@pollyjs/core/src/-private/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import URL from 'url-parse';
import stringify from 'fast-json-stable-stringify';
import PollyResponse from './response';
import NormalizeRequest from '../utils/normalize-request';
import removeHostFromUrl from '../utils/remove-host-from-url';
import parseUrl from '../utils/parse-url';
import serializeRequestBody from '../utils/serialize-request-body';
import isAbsoluteUrl from 'is-absolute-url';
import { assert, timestamp } from '@pollyjs/utils';
Expand Down Expand Up @@ -48,18 +48,7 @@ export default class PollyRequest extends HTTPBase {
}

set url(value) {
const url = new URL(value, true);

/*
If the url is relative, setup the parsed url to reflect just that
by removing the host. By default URL sets the host via window.location if
it does not exist.
*/
if (!isAbsoluteUrl(value)) {
removeHostFromUrl(url);
}

this[PARSED_URL] = url;
this[PARSED_URL] = parseUrl(value, true);
}

get absoluteUrl() {
Expand Down
1 change: 1 addition & 0 deletions packages/@pollyjs/core/src/utils/http-headers.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import isObjectLike from 'lodash-es/isObjectLike';

const { keys } = Object;

const HANDLER = {
get(obj, prop) {
// `prop` can be a Symbol so only lower-case string based props.
Expand Down
11 changes: 2 additions & 9 deletions packages/@pollyjs/core/src/utils/normalize-request.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import URL from 'url-parse';
import removeHostFromUrl from './remove-host-from-url';
import parseUrl from './parse-url';
import isObjectLike from 'lodash-es/isObjectLike';
import isAbsoluteUrl from 'is-absolute-url';
import HTTPHeaders from './http-headers';
import stringify from 'fast-json-stable-stringify';

Expand All @@ -14,12 +12,7 @@ export function method(method) {
}

export function url(url, config = {}) {
const parsedUrl = new URL(url, true);

// Remove the host if the url is relative
if (!isAbsoluteUrl(url)) {
removeHostFromUrl(parsedUrl);
}
const parsedUrl = parseUrl(url, true);

// Remove any url properties that have been disabled via the config
keys(config).forEach(key => !config[key] && parsedUrl.set(key, ''));
Expand Down
32 changes: 32 additions & 0 deletions packages/@pollyjs/core/src/utils/parse-url.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import URL from 'url-parse';
import isAbsoluteUrl from 'is-absolute-url';
import removeHostFromUrl from './remove-host-from-url';

/**
* Creates an exact representation of the passed url string with url-parse.
*
* @param {String} url
* @param {...args} args Arguments to pass through to the URL constructor
* @returns {URL} A url-parse URL instance
*/
export default function parseUrl(url, ...args) {
const parsedUrl = new URL(url, ...args);

if (!isAbsoluteUrl(url)) {
if (url.startsWith('//')) {
/*
If the url is protocol-relative, strip out the protocol
*/
parsedUrl.set('protocol', '');
} else {
/*
If the url is relative, setup the parsed url to reflect just that
by removing the host. By default URL sets the host via window.location if
it does not exist.
*/
removeHostFromUrl(parsedUrl);
}
}

return parsedUrl;
}
24 changes: 24 additions & 0 deletions packages/@pollyjs/core/tests/unit/utils/parse-url-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import parseUrl from '../../../src/utils/parse-url';

describe('Unit | Utils | parseUrl', function() {
it('should exist', function() {
expect(parseUrl).to.be.a('function');
});

it('should exactly match passed urls', function() {
[
'/movies/1',
'//netflix.com/movies/1',
'http://netflix.com/movies/1',
'http://netflix.com/movies/1?sort=title&dir=asc'
].forEach(url => expect(parseUrl(url).href).to.equal(url));
});

it('should passthrough arguments to url-parse', function() {
// Passing true tells url-parse to transform the querystring into an object
expect(parseUrl('/movies/1?sort=title&dir=asc', true).query).to.deep.equal({
sort: 'title',
dir: 'asc'
});
});
});
3 changes: 1 addition & 2 deletions testem.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ module.exports = {
serve_files: ['./packages/@pollyjs/*/build/browser/*.js'],
browser_args: {
Chrome: {
mode: 'ci',
args: [
ci: [
// --no-sandbox is needed when running Chrome inside a container
process.env.TRAVIS ? '--no-sandbox' : null,
'--disable-gpu',
Expand Down

0 comments on commit 2c0083e

Please sign in to comment.