Skip to content

Commit

Permalink
feat: create static buildURL method
Browse files Browse the repository at this point in the history
This commit creates a static `_buildURL` method on the imgix client. The
method allows full URLs to be formatted for use with imgix.

> note: If the source URL has included parameters, they are merged with
the `params` passed in as an argument.

- `url`: full source URL path string, required
- `params`: imgix params object, optional
- `options`: imgix client options, optional

The method returns a URL string formatted to imgix specifications.
  • Loading branch information
luqven committed Apr 21, 2022
1 parent 2d51810 commit 8c4a193
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 12 deletions.
66 changes: 54 additions & 12 deletions src/index.js
@@ -1,25 +1,22 @@
import md5 from 'md5';
import { Base64 } from 'js-base64';
import { extractUrl } from './helpers';
import md5 from 'md5';
import { getQuery } from 'ufo';


import {
VERSION,
DOMAIN_REGEX,
DEFAULT_DPR,
DEFAULT_OPTIONS,
DOMAIN_REGEX,
DPR_QUALITIES,
DEFAULT_DPR,
VERSION,
} from './constants.js';

import { extractUrl } from './helpers';
import {
validateRange,
validateWidths,
validateAndDestructureOptions,
validateVariableQuality,
validateWidthTolerance,
validateDevicePixelRatios,
validateRange,
validateVariableQualities,
validateVariableQuality,
validateWidths,
validateWidthTolerance,
} from './validators.js';

export default class ImgixClient {
Expand Down Expand Up @@ -62,6 +59,51 @@ export default class ImgixClient {
return this.settings.urlPrefix + this.settings.domain + path + finalParams;
}

/**
*`_buildURL` static method allows full URLs to be formatted for use with
* imgix.
*
* - If the source URL has included parameters, they are merged with
* the `params` passed in as an argument.
* - URL must match `{host}/{pathname}?{query}` otherwise an error is thrown.
*
* @param {String} url - full source URL path string, required
* @param {Object} params - imgix params object, optional
* @param {Object} options - imgix client options, optional
*
* @returns URL string formatted to imgix specifications.
*
* @example
* const client = ImgixClient
* const params = { w: 100 }
* const opts = { useHttps: true }
* const src = "sdk-test.imgix.net/amsterdam.jpg?h=100"
* const url = client._buildURL(src, params, opts)
* console.log(url)
* // => "https://sdk-test.imgix.net/amsterdam.jpg?h=100&w=100"
*/
static _buildURL(url, params = {}, options = {}) {
if (url == null) {
return '';
}

const { host, pathname, search } = extractUrl({
url,
useHTTPS: options.useHTTPS,
});
// merge source URL parameters with options parameters
const combinedParams = { ...getQuery(search), ...params };

// throw error if no host or no pathname present
if (!host.length || !pathname.length) {
throw new Error('_buildURL: URL must match {host}/{pathname}?{query}');
}

const client = new ImgixClient({ domain: host, ...options });

return client.buildURL(pathname, combinedParams);
}

_buildParams(params = {}) {
const queryParams = [
// Set the libraryParam if applicable.
Expand Down
119 changes: 119 additions & 0 deletions test/test-_buildURL.js
@@ -0,0 +1,119 @@
import assert from 'assert';
import ImgixClient from '../src/index.js';

describe('URL Builder:', function describeSuite() {
describe('Calling _buildURL()', function describeSuite() {
let client, params, url, options;

beforeEach(function setupClient() {
client = ImgixClient;
});

describe('on a full URL', function describeSuite() {
url = 'https://assets.imgix.net/images/1.png';
params = { h: 100 };
options = { includeLibraryParam: false, useHTTPS: true };

it('should return a URL with formatted imgix params', function testSpec() {
const expectation = url + '?h=100';
const result = client._buildURL(url, params, options);

assert.strictEqual(result, expectation);
});

describe('that has no scheme', function describeSuite() {
const url = 'assets.imgix.net/images/1.png';
const params = {};
const options = { includeLibraryParam: false, useHTTPS: true };

it('should prepend the scheme to the returned URL', function testSpec() {
const expectation = 'https://' + url;
const result = client._buildURL(url, params, options);

assert.strictEqual(result, expectation);
});
});

describe('that has a proxy path', function describeSuite() {
const url = 'https://assets.imgix.net/https://sdk-test/images/1.png';
const params = {};
const options = { includeLibraryParam: false, useHTTPS: true };

it('should correctly encode the proxy path', function testSpec() {
const expectation = new client({
domain: 'assets.imgix.net',
...options,
}).buildURL('https://sdk-test/images/1.png', params);
const result = client._buildURL(url, params, options);

assert.strictEqual(result, expectation);
});
});

describe('that has a insecure source and secure proxy', function describeSuite() {
const url =
'http://assets.imgix.net/https://sdk-test.imgix.net/images/1.png';
const params = {};
const options = { includeLibraryParam: false, useHTTPS: false };

it('should not modify the source or proxy schemes', function testSpec() {
const expectation =
'http://assets.imgix.net/https%3A%2F%2Fsdk-test.imgix.net%2Fimages%2F1.png';
const result = client._buildURL(url, params, options);

assert.strictEqual(result, expectation);
});
});

describe('that has a secure source and insecure proxy', function describeSuite() {
const url =
'https://assets.imgix.net/http://sdk-test.imgix.net/images/1.png';
const params = {};
const options = { includeLibraryParam: false, useHTTPS: true };

it('should not modify the source or proxy schemes', function testSpec() {
const expectation =
'https://assets.imgix.net/http%3A%2F%2Fsdk-test.imgix.net%2Fimages%2F1.png';
const result = client._buildURL(url, params, options);

assert.strictEqual(result, expectation);
});
});
});

describe('on a malformed URLs', function describeSuite() {
const error = new Error(
'_buildURL: URL must match {host}/{pathname}?{query}',
);
const params = {};
const options = { includeLibraryParam: false, useHTTPS: true };

it('should throw an error if no hostname', function testSpec() {
const url = '/image.png';
assert.throws(function () {
client._buildURL(url, params, options);
}, error);
});

it('should throw an error if no pathname', function testSpec() {
const url = 'assets.imgix.net';
assert.throws(function () {
client._buildURL(url, params, options);
}, error);
});
});

describe('that has parameters in the URL', function describeSuite() {
const url = 'https://assets.imgix.net/images/1.png?w=100&h=100';
const params = { h: 200 };
const options = { includeLibraryParam: false, useHTTPS: true };

it('should overwrite url params with opts params', function testSpec() {
const expectation = 'https://assets.imgix.net/images/1.png?w=100&h=200';
const result = client._buildURL(url, params, options);

assert.strictEqual(result, expectation);
});
});
});
});

0 comments on commit 8c4a193

Please sign in to comment.