Skip to content

Commit c7f2ff3

Browse files
committed
Implement .urlParams
1 parent a3cd08a commit c7f2ff3

File tree

9 files changed

+127
-7
lines changed

9 files changed

+127
-7
lines changed

README.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Requests are configured via method calls and each method always returns a fresh
1414
- Understands Content-Type (decodes JSON responses by default)
1515
- [TypeScript support](#usage-with-typescript)
1616
- [Works on modern browsers and some older ones](#browser-support)
17-
- [Fully tested](/test/specs) (see e.g. [requests.spec.js](/test/specs/requests.spec.js))
17+
- [Fully tested](/test/specs) (see e.g. [requests.spec.js](/test/specs/requests.spec.js)) in real browsers, thanks to Sauce Labs
1818

1919
Why not use fetch, axios, jQuery, etc..? See [COMPARISON.md](COMPARISON.md).
2020

@@ -86,6 +86,11 @@ request
8686
console.error(error.response.status);
8787
})
8888

89+
// ... with URL parameters
90+
request
91+
.get('https://example.com/api/accounts/:accountId/info')
92+
.urlParams({ accountId: 123 })
93+
8994
// Make a POST request
9095
request
9196
.post('https://example.com/accounts')
@@ -166,6 +171,7 @@ The following methods are available.
166171
- [.post(url)](#post)
167172
- [.method(method)](#method)
168173
- [.url(url)](#url)
174+
- [.urlParams(object)](#urlparams)
169175
- [.baseUrl(url)](#baseurl)
170176
- [.query(object | string)](#query)
171177
- [.headers(object)](#headers)
@@ -239,6 +245,23 @@ Sets the full URL of the request. If a query-string is present, it will override
239245

240246
Where `url` is a string, e.g. `'https://example.com/accounts'`.
241247

248+
### urlParams
249+
250+
Sets URL parameters which will be replaced from the URL when the request is sent.
251+
252+
```js
253+
.urlParams(object)
254+
```
255+
256+
Where `object` is an object.
257+
258+
Example:
259+
260+
```js
261+
// Will make request to "/api/accounts/123/info"
262+
request.get('/api/accounts/:accountId/info').urlParams({ accountId: 123 })
263+
```
264+
242265
### baseUrl
243266

244267
Sets the base URL to which all subsequent request URLs will be appended.

build/yea.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@
5656
return segments.join('&');
5757
}
5858

59+
function replaceUrlParams(url, params) {
60+
for (var key in params) {
61+
var regex = new RegExp(':' + key, 'g');
62+
url = url.replace(regex, params[key]);
63+
}
64+
return url;
65+
}
66+
5967
function createUrl(baseUrl, path, query) {
6068
var url = '';
6169
if (baseUrl) {
@@ -73,6 +81,7 @@
7381

7482
function mergeConfig(config, updated) {
7583
return assign({}, config, updated, {
84+
urlParams: assign({}, config.urlParams, updated.urlParams || {}),
7685
headers: assign({}, config.headers, updated.headers || {}),
7786
responseTransformers: [].concat(updated.responseTransformers || config.responseTransformers),
7887
polyfills: assign({}, config.polyfills, updated.polyfills || {}),
@@ -111,6 +120,7 @@
111120
this.utils = {
112121
assign: assign,
113122
toQueryString: toQueryString,
123+
replaceUrlParams: replaceUrlParams,
114124
createUrl: createUrl,
115125
parsePropPath: parsePropPath,
116126
applyPropPath: applyPropPath
@@ -148,6 +158,12 @@
148158
return new YeaAjaxRequest(mergeConfig(this._config, { url: url, query: query }));
149159
};
150160

161+
YeaAjaxRequest.prototype.urlParams = function urlParams(urlParams) {
162+
var config = mergeConfig(this._config, {});
163+
config.urlParams = assign({}, urlParams);
164+
return new YeaAjaxRequest(config);
165+
};
166+
151167
YeaAjaxRequest.prototype.baseUrl = function baseUrl(baseUrl) {
152168
if (baseUrl === null) {
153169
baseUrl = '';
@@ -370,8 +386,9 @@
370386
}
371387
};
372388

373-
var url = createUrl(config.baseUrl, config.url, config.query);
374-
httpRequest.open(config.method, url, true);
389+
var url = replaceUrlParams(config.url, config.urlParams);
390+
var fullUrl = createUrl(config.baseUrl, url, config.query);
391+
httpRequest.open(config.method, fullUrl, true);
375392

376393
for (var name in config.headers) {
377394
httpRequest.setRequestHeader(name, config.headers[name]);
@@ -398,6 +415,7 @@
398415
method: 'GET',
399416
baseUrl: '',
400417
url: '',
418+
urlParams: {},
401419
query: '',
402420
body: '',
403421
headers: {},

build/yea.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

index.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ declare class YeaAjaxRequest implements PromiseLike<YeaResponse> {
7777
*/
7878
url(url: string): this;
7979

80+
/**
81+
* Sets URL parameters which will be replaced from the URL when the request is sent.
82+
*/
83+
urlParams(urlParams: object): this;
84+
8085
/**
8186
* Sets the base URL to which all subsequent request URLs will be appended.
8287
*/

src/index.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@
5656
return segments.join('&');
5757
}
5858

59+
function replaceUrlParams(url, params) {
60+
for (var key in params) {
61+
var regex = new RegExp(':' + key, 'g');
62+
url = url.replace(regex, params[key]);
63+
}
64+
return url;
65+
}
66+
5967
function createUrl(baseUrl, path, query) {
6068
var url = '';
6169
if (baseUrl) {
@@ -73,6 +81,7 @@
7381

7482
function mergeConfig(config, updated) {
7583
return assign({}, config, updated, {
84+
urlParams: assign({}, config.urlParams, updated.urlParams || {}),
7685
headers: assign({}, config.headers, updated.headers || {}),
7786
responseTransformers: [].concat(updated.responseTransformers || config.responseTransformers),
7887
polyfills: assign({}, config.polyfills, updated.polyfills || {}),
@@ -111,6 +120,7 @@
111120
this.utils = {
112121
assign: assign,
113122
toQueryString: toQueryString,
123+
replaceUrlParams: replaceUrlParams,
114124
createUrl: createUrl,
115125
parsePropPath: parsePropPath,
116126
applyPropPath: applyPropPath
@@ -148,6 +158,12 @@
148158
return new YeaAjaxRequest(mergeConfig(this._config, { url: url, query: query }));
149159
};
150160

161+
YeaAjaxRequest.prototype.urlParams = function urlParams(urlParams) {
162+
var config = mergeConfig(this._config, {});
163+
config.urlParams = assign({}, urlParams);
164+
return new YeaAjaxRequest(config);
165+
};
166+
151167
YeaAjaxRequest.prototype.baseUrl = function baseUrl(baseUrl) {
152168
if (baseUrl === null) {
153169
baseUrl = '';
@@ -370,8 +386,9 @@
370386
}
371387
};
372388

373-
var url = createUrl(config.baseUrl, config.url, config.query);
374-
httpRequest.open(config.method, url, true);
389+
var url = replaceUrlParams(config.url, config.urlParams);
390+
var fullUrl = createUrl(config.baseUrl, url, config.query);
391+
httpRequest.open(config.method, fullUrl, true);
375392

376393
for (var name in config.headers) {
377394
httpRequest.setRequestHeader(name, config.headers[name]);
@@ -398,6 +415,7 @@
398415
method: 'GET',
399416
baseUrl: '',
400417
url: '',
418+
urlParams: {},
401419
query: '',
402420
body: '',
403421
headers: {},

test/server/helper-server.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ app.get('/dump-headers', function (req, res) {
2828
return "".concat(name, ": ").concat(req.headers[name]);
2929
}).join('\n'));
3030
});
31+
app.get('/dump-url/*', function (req, res) {
32+
return res.send(req.originalUrl);
33+
});
3134
app.get('/dump-query', function (req, res) {
3235
return res.send(Object.keys(req.query).sort().map(function (key) {
3336
return "".concat(key, ": ").concat(req.query[key]);

test/specs/methods.spec.js

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ describe('Methods', function () {
22
describe('defaults', function () {
33
it('has defaults', function () {
44
var defaults = yea.toObject();
5-
expect(defaults).to.have.keys(['method', 'baseUrl', 'url', 'query', 'body', 'headers', 'responseTransformers', 'allowedStatusCode', 'timeout', 'prop', 'polyfills']);
5+
expect(defaults).to.have.keys(['method', 'baseUrl', 'url', 'urlParams', 'query', 'body', 'headers', 'responseTransformers', 'allowedStatusCode', 'timeout', 'prop', 'polyfills']);
66
expect(defaults.method).to.equal('GET');
77
expect(defaults.baseUrl).to.equal('');
88
expect(defaults.url).to.equal('');
9+
expect(defaults.urlParams).to.deep.equal({});
910
expect(defaults.query).to.equal('');
1011
expect(defaults.body).to.equal('');
1112
expect(defaults.headers).to.deep.equal({});
@@ -127,6 +128,32 @@ describe('Methods', function () {
127128
});
128129
});
129130

131+
describe('.urlParams', function () {
132+
it('sets urlParams', function () {
133+
expect(yea.urlParams({ super: 'yes' }).toObject().urlParams).to.deep.equal({ super: 'yes' });
134+
expect(yea.urlParams({ SUPER: 'yes' }).toObject().urlParams).to.deep.equal({ SUPER: 'yes' });
135+
});
136+
137+
it('overwrites existing urlParams', function () {
138+
var req = yea.urlParams({ super: 'yes', foo: 'sir' });
139+
expect(req.urlParams({ foo: 'bar', fresh: 'sure' }).toObject().urlParams).to.deep.equal({ foo: 'bar', fresh: 'sure' });
140+
});
141+
142+
it('leaves no references', function () {
143+
var urlParams = { super: 'yes' };
144+
var req = yea.urlParams(urlParams);
145+
expect(req.toObject().urlParams).to.not.equal(urlParams);
146+
urlParams.super = 'modified';
147+
expect(req.toObject().urlParams.super).to.equal('yes');
148+
});
149+
150+
it('is immutable', function () {
151+
var req = yea.urlParams({ super: 123 });
152+
expect(req).to.not.equal(yea);
153+
expect(req.constructor).to.equal(yea.constructor);
154+
});
155+
});
156+
130157
describe('.baseUrl', function () {
131158
it('sets baseUrl', function () {
132159
expect(yea.baseUrl('http://example.com').toObject().baseUrl).to.equal('http://example.com');

test/specs/requests.spec.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,18 @@ describe('Requests', function () {
126126
});
127127
});
128128

129+
it('replaces urlParams if present', function () {
130+
return yea
131+
.url('/dump-url/:accountId')
132+
.urlParams({ accountId: 123 })
133+
.send()
134+
.then(function (response) {
135+
expect(response.status).to.equal(200);
136+
expect(response.body).to.be.a('string');
137+
expect(response.body).to.equal('/dump-url/123');
138+
});
139+
});
140+
129141
it('sends body', function () {
130142
return yea
131143
.method('post')

test/specs/utils.spec.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,20 @@ describe('utils', function () {
6262
});
6363
});
6464

65+
describe('.replaceUrlParams', function () {
66+
it('replaces param placeholders in URL', function () {
67+
expect(yea.utils.replaceUrlParams('', {})).to.equal('');
68+
expect(yea.utils.replaceUrlParams('http://example.com', {})).to.equal('http://example.com');
69+
expect(yea.utils.replaceUrlParams('/accounts', {})).to.equal('/accounts');
70+
expect(yea.utils.replaceUrlParams('/accounts/:accountId', {})).to.equal('/accounts/:accountId');
71+
expect(yea.utils.replaceUrlParams('/accounts/:accountId', { accountId: 123 })).to.equal('/accounts/123');
72+
expect(yea.utils.replaceUrlParams('/accounts/:accountId/info', { accountId: 123 })).to.equal('/accounts/123/info');
73+
expect(yea.utils.replaceUrlParams('/accounts/:account-id', { 'account-id': 123 })).to.equal('/accounts/123');
74+
expect(yea.utils.replaceUrlParams('/accounts/:AccountId', { 'accountId': 123 })).to.equal('/accounts/:AccountId');
75+
expect(yea.utils.replaceUrlParams('/:repeat/:repeat', { repeat: 123 })).to.equal('/123/123');
76+
});
77+
});
78+
6579
describe('.createUrl', function () {
6680
it('creates URL from baseUrl, path and query', function () {
6781
expect(yea.utils.createUrl('', 'accounts')).to.equal('accounts');

0 commit comments

Comments
 (0)