Agent
- should remember defaults
- if (typeof Promise === 'undefined') { return; } let called = 0; let event_called = 0; const agent = request .agent() .accept('json') .use(() => { called++; }) .once('request', () => { event_called++; }) .query({ hello: 'world' }) .set('X-test', 'testing'); assert.equal(0, called); assert.equal(0, event_called); return agent .get(`${base}/echo`) .then((res) => { assert.equal(1, called); assert.equal(1, event_called); assert.equal('application/json', res.headers.accept); assert.equal('testing', res.headers['x-test']); return agent.get(`${base}/querystring`); }) .then((res) => { assert.equal(2, called); assert.equal(2, event_called); assert.deepEqual({ hello: 'world' }, res.body); });
request
- should set statusCode
- request.get(`${uri}/login`, (err, res) => { try { assert.strictEqual(res.statusCode, 200); done(); } catch (err_) { done(err_); } });
- with callback in the method call
- request.get(`${uri}/login`, (err, res) => { assert.equal(res.status, 200); done(); });
- with data in the method call
- request.post(`${uri}/echo`, { foo: 'bar' }).end((err, res) => { assert.equal('{"foo":"bar"}', res.text); done(); });
- with callback and data in the method call
- request.post(`${uri}/echo`, { foo: 'bar' }, (err, res) => { assert.equal('{"foo":"bar"}', res.text); done(); });
- should invoke .end()
- request.get(`${uri}/login`, (err, res) => { try { assert.equal(res.status, 200); done(); } catch (err_) { done(err_); } });
- should issue a request
- request.get(`${uri}/login`).end((err, res) => { try { assert.equal(res.status, 200); done(); } catch (err_) { done(err_); } });
- is optional with a promise
- if (typeof Promise === 'undefined') { return; } return request .get(`${uri}/login`) .then((res) => res.status) .then() .then((status) => { assert.equal(200, status, 'Real promises pass results through'); });
- called only once with a promise
- if (typeof Promise === 'undefined') { return; } const req = request.get(`${uri}/unique`); return Promise.all([req, req, req]).then((results) => { results.forEach((item) => { assert.equal( item.body, results[0].body, 'It should keep returning the same result after being called once' ); }); });
- ok
- let calledErrorEvent = false; let calledOKHandler = false; request .get(`${uri}/error`) .ok((res) => { assert.strictEqual(500, res.status); calledOKHandler = true; return true; }) .on('error', (err) => { calledErrorEvent = true; }) .end((err, res) => { try { assert.ifError(err); assert.strictEqual(res.status, 500); assert(!calledErrorEvent); assert(calledOKHandler); done(); } catch (err_) { done(err_); } });
- should be an Error object
- let calledErrorEvent = false; request .get(`${uri}/error`) .on('error', (err) => { assert.strictEqual(err.status, 500); calledErrorEvent = true; }) .end((err, res) => { try { if (NODE) { res.error.message.should.equal('cannot GET /error (500)'); } else { res.error.message.should.equal(`cannot GET ${uri}/error (500)`); } assert.strictEqual(res.error.status, 500); assert(err, 'should have an error for 500'); assert.equal(err.message, 'Internal Server Error'); assert(calledErrorEvent); done(); } catch (err_) { done(err_); } });
- with .then() promise
- if (typeof Promise === 'undefined') { return; } return request.get(`${uri}/error`).then( () => { assert.fail(); }, (err) => { assert.equal(err.message, 'Internal Server Error'); } );
- with .ok() returning false
- if (typeof Promise === 'undefined') { return; } return request .get(`${uri}/echo`) .ok(() => false) .then( () => { assert.fail(); }, (err) => { assert.equal(200, err.response.status); assert.equal(err.message, 'OK'); } );
- with .ok() throwing an Error
- if (typeof Promise === 'undefined') { return; } return request .get(`${uri}/echo`) .ok(() => { throw new Error('boom'); }) .then( () => { assert.fail(); }, (err) => { assert.equal(200, err.response.status); assert.equal(err.message, 'boom'); } );
- should be an object
- request.get(`${uri}/login`).end((err, res) => { try { assert.equal('Express', res.header['x-powered-by']); done(); } catch (err_) { done(err_); } });
- should only set headers for ownProperties of header
- try { request .get(`${uri}/echo-headers`) .set('valid', 'ok') .end((err, res) => { if ( !err && res.body && res.body.valid && !res.body.hasOwnProperty('invalid') ) { return done(); } done(err || new Error('fail')); }); } catch (err) { done(err); }
- should be set when present
- request.get(`${uri}/login`).end((err, res) => { try { res.charset.should.equal('utf-8'); done(); } catch (err_) { done(err_); } });
- should provide the first digit
- request.get(`${uri}/login`).end((err, res) => { try { assert(!err, 'should not have an error for success responses'); assert.equal(200, res.status); assert.equal(2, res.statusType); done(); } catch (err_) { done(err_); } });
- should provide the mime-type void of params
- request.get(`${uri}/login`).end((err, res) => { try { res.type.should.equal('text/html'); res.charset.should.equal('utf-8'); done(); } catch (err_) { done(err_); } });
- should set the header field
- request .post(`${uri}/echo`) .set('X-Foo', 'bar') .set('X-Bar', 'baz') .end((err, res) => { try { assert.equal('bar', res.header['x-foo']); assert.equal('baz', res.header['x-bar']); done(); } catch (err_) { done(err_); } });
- should set the header fields
- request .post(`${uri}/echo`) .set({ 'X-Foo': 'bar', 'X-Bar': 'baz' }) .end((err, res) => { try { assert.equal('bar', res.header['x-foo']); assert.equal('baz', res.header['x-bar']); done(); } catch (err_) { done(err_); } });
- should set the Content-Type
- request .post(`${uri}/echo`) .type('text/x-foo') .end((err, res) => { try { res.header['content-type'].should.equal('text/x-foo'); done(); } catch (err_) { done(err_); } });
- should map "json"
- request .post(`${uri}/echo`) .type('json') .send('{"a": 1}') .end((err, res) => { try { res.should.be.json(); done(); } catch (err_) { done(err_); } });
- should map "html"
- request .post(`${uri}/echo`) .type('html') .end((err, res) => { try { res.header['content-type'].should.equal('text/html'); done(); } catch (err_) { done(err_); } });
- should set Accept
- request .get(`${uri}/echo`) .accept('text/x-foo') .end((err, res) => { try { res.header.accept.should.equal('text/x-foo'); done(); } catch (err_) { done(err_); } });
- should map "json"
- request .get(`${uri}/echo`) .accept('json') .end((err, res) => { try { res.header.accept.should.equal('application/json'); done(); } catch (err_) { done(err_); } });
- should map "xml"
- request .get(`${uri}/echo`) .accept('xml') .end((err, res) => { try { // Mime module keeps changing this :( assert( res.header.accept == 'application/xml' || res.header.accept == 'text/xml' ); done(); } catch (err_) { done(err_); } });
- should map "html"
- request .get(`${uri}/echo`) .accept('html') .end((err, res) => { try { res.header.accept.should.equal('text/html'); done(); } catch (err_) { done(err_); } });
- should write the string
- request .post(`${uri}/echo`) .type('json') .send('{"name":"tobi"}') .end((err, res) => { try { res.text.should.equal('{"name":"tobi"}'); done(); } catch (err_) { done(err_); } });
- should default to json
- request .post(`${uri}/echo`) .send({ name: 'tobi' }) .end((err, res) => { try { res.should.be.json(); res.text.should.equal('{"name":"tobi"}'); done(); } catch (err_) { done(err_); } });
- should merge the objects
- request .post(`${uri}/echo`) .send({ name: 'tobi' }) .send({ age: 1 }) .end((err, res) => { try { res.should.be.json(); if (NODE) { res.buffered.should.be.true(); } res.text.should.equal('{"name":"tobi","age":1}'); done(); } catch (err_) { done(err_); } });
- should check arity
- request .post(`${uri}/echo`) .send({ name: 'tobi' }) .end((err, res) => { try { assert.ifError(err); res.text.should.equal('{"name":"tobi"}'); done(); } catch (err_) { done(err_); } });
- should emit request
- const req = request.post(`${uri}/echo`); req.on('request', (request) => { assert.equal(req, request); done(); }); req.end();
- should emit response
- request .post(`${uri}/echo`) .send({ name: 'tobi' }) .on('response', (res) => { res.text.should.equal('{"name":"tobi"}'); done(); }) .end();
- should support successful fulfills with .then(fulfill)
- if (typeof Promise === 'undefined') { return done(); } request .post(`${uri}/echo`) .send({ name: 'tobi' }) .then((res) => { res.type.should.equal('application/json'); res.text.should.equal('{"name":"tobi"}'); done(); });
- should reject an error with .then(null, reject)
- if (typeof Promise === 'undefined') { return done(); } request.get(`${uri}/error`).then(null, (err) => { assert.equal(err.status, 500); assert.equal(err.response.text, 'boom'); done(); });
- should reject an error with .catch(reject)
- if (typeof Promise === 'undefined') { return done(); } request.get(`${uri}/error`).catch((err) => { assert.equal(err.status, 500); assert.equal(err.response.text, 'boom'); done(); });
- should abort the request
- const req = request.get(`${uri}/delay/3000`); req.end((err, res) => { try { assert(false, 'should not complete the request'); } catch (err_) { done(err_); } }); req.on('error', (error) => { done(error); }); req.on('abort', done); setTimeout(() => { req.abort(); }, 500);
- should abort the promise
- const req = request.get(`${uri}/delay/3000`); setTimeout(() => { req.abort(); }, 10); return req.then( () => { assert.fail('should not complete the request'); }, (err) => { assert.equal('ABORTED', err.code); } );
- should allow chaining .abort() several times
- const req = request.get(`${uri}/delay/3000`); req.end((err, res) => { try { assert(false, 'should not complete the request'); } catch (err_) { done(err_); } }); // This also verifies only a single 'done' event is emitted req.on('abort', done); setTimeout(() => { req.abort().abort().abort(); }, 1000);
- should not allow abort then end
- request .get(`${uri}/delay/3000`) .abort() .end((err, res) => { done(err ? undefined : new Error('Expected abort error')); });
- should describe the request
- const req = request.post(`${uri}/echo`).send({ foo: 'baz' }); req.end((err, res) => { try { const json = req.toJSON(); assert.equal('POST', json.method); assert(/\/echo$/.test(json.url)); assert.equal('baz', json.data.foo); done(); } catch (err_) { done(err_); } });
- should allow request body
- request .options(`${uri}/options/echo/body`) .send({ foo: 'baz' }) .end((err, res) => { try { assert.equal(err, null); assert.strictEqual(res.body.foo, 'baz'); done(); } catch (err_) { done(err_); } });
- nop with no querystring
- request .get(`${uri}/url`) .sortQuery() .end((err, res) => { try { assert.equal(res.text, '/url'); done(); } catch (err_) { done(err_); } });
- should sort the request querystring
- request .get(`${uri}/url`) .query('search=Manny') .query('order=desc') .sortQuery() .end((err, res) => { try { assert.equal(res.text, '/url?order=desc&search=Manny'); done(); } catch (err_) { done(err_); } });
- should allow disabling sorting
- request .get(`${uri}/url`) .query('search=Manny') .query('order=desc') .sortQuery() // take default of true .sortQuery(false) // override it in later call .end((err, res) => { try { assert.equal(res.text, '/url?search=Manny&order=desc'); done(); } catch (err_) { done(err_); } });
- should sort the request querystring using customized function
- request .get(`${uri}/url`) .query('name=Nick') .query('search=Manny') .query('order=desc') .sortQuery((a, b) => a.length - b.length) .end((err, res) => { try { assert.equal(res.text, '/url?name=Nick&order=desc&search=Manny'); done(); } catch (err_) { done(err_); } });
res.statusCode
should allow the send shorthand
with a callback
.end()
res.error
res.header
set headers
res.charset
res.statusType
res.type
req.set(field, val)
req.set(obj)
req.type(str)
req.accept(str)
req.send(str)
req.send(Object)
when called several times
.end(fn)
.then(fulfill, reject)
.catch(reject)
.abort()
req.toJSON()
req.options()
req.sortQuery()
req.set("Content-Type", contentType)
- should work with just the contentType component
- request .post(`${uri}/echo`) .set('Content-Type', 'application/json') .send({ name: 'tobi' }) .end((err, res) => { assert(!err); done(); });
- should work with the charset component
- request .post(`${uri}/echo`) .set('Content-Type', 'application/json; charset=utf-8') .send({ name: 'tobi' }) .end((err, res) => { assert(!err); done(); });
req.send(Object) as "form"
- should send x-www-form-urlencoded data
- request .post(`${base}/echo`) .type('form') .send({ name: 'tobi' }) .end((err, res) => { res.header['content-type'].should.equal( 'application/x-www-form-urlencoded' ); res.text.should.equal('name=tobi'); done(); });
- should merge the objects
- request .post(`${base}/echo`) .type('form') .send({ name: { first: 'tobi', last: 'holowaychuk' } }) .send({ age: '1' }) .end((err, res) => { res.header['content-type'].should.equal( 'application/x-www-form-urlencoded' ); res.text.should.equal( 'name%5Bfirst%5D=tobi&name%5Blast%5D=holowaychuk&age=1' ); done(); });
with req.type() set to form
when called several times
req.attach
- ignores null file
- request .post('/echo') .attach('image', null) .end((err, res) => { done(); });
req.field
- allow bools
- if (!formDataSupported) { return done(); } request .post(`${base}/formecho`) .field('bools', true) .field('strings', 'true') .end((err, res) => { assert.ifError(err); assert.deepStrictEqual(res.body, { bools: 'true', strings: 'true' }); done(); });
- allow objects
- if (!formDataSupported) { return done(); } request .post(`${base}/formecho`) .field({ bools: true, strings: 'true' }) .end((err, res) => { assert.ifError(err); assert.deepStrictEqual(res.body, { bools: 'true', strings: 'true' }); done(); });
- works with arrays in objects
- if (!formDataSupported) { return done(); } request .post(`${base}/formecho`) .field({ numbers: [1, 2, 3] }) .end((err, res) => { assert.ifError(err); assert.deepStrictEqual(res.body, { numbers: ['1', '2', '3'] }); done(); });
- works with arrays
- if (!formDataSupported) { return done(); } request .post(`${base}/formecho`) .field('letters', ['a', 'b', 'c']) .end((err, res) => { assert.ifError(err); assert.deepStrictEqual(res.body, { letters: ['a', 'b', 'c'] }); done(); });
- throw when empty
- should.throws(() => { request.post(`${base}/echo`).field(); }, /name/); should.throws(() => { request.post(`${base}/echo`).field('name'); }, /val/);
- cannot be mixed with send()
- assert.throws(() => { request.post('/echo').field('form', 'data').send('hi'); }); assert.throws(() => { request.post('/echo').send('hi').field('form', 'data'); });
req.send(Object) as "json"
- should default to json
- request .post(`${uri}/echo`) .send({ name: 'tobi' }) .end((err, res) => { res.should.be.json(); res.text.should.equal('{"name":"tobi"}'); done(); });
- should work with arrays
- request .post(`${uri}/echo`) .send([1, 2, 3]) .end((err, res) => { res.should.be.json(); res.text.should.equal('[1,2,3]'); done(); });
- should work with value null
- request .post(`${uri}/echo`) .type('json') .send('null') .end((err, res) => { res.should.be.json(); assert.strictEqual(res.body, null); done(); });
- should work with value false
- request .post(`${uri}/echo`) .type('json') .send('false') .end((err, res) => { res.should.be.json(); res.body.should.equal(false); done(); });
- should work with value 0
- // fails in IE9 request .post(`${uri}/echo`) .type('json') .send('0') .end((err, res) => { res.should.be.json(); res.body.should.equal(0); done(); });
- should work with empty string value
- request .post(`${uri}/echo`) .type('json') .send('""') .end((err, res) => { res.should.be.json(); res.body.should.equal(''); done(); });
- should work with GET
- request .get(`${uri}/echo`) .send({ tobi: 'ferret' }) .end((err, res) => { try { res.should.be.json(); res.text.should.equal('{"tobi":"ferret"}'); ({ tobi: 'ferret' }.should.eql(res.body)); done(); } catch (err_) { done(err_); } });
- should work with vendor MIME type
- request .post(`${uri}/echo`) .set('Content-Type', 'application/vnd.example+json') .send({ name: 'vendor' }) .end((err, res) => { res.text.should.equal('{"name":"vendor"}'); ({ name: 'vendor' }.should.eql(res.body)); done(); });
- should merge the objects
- request .post(`${uri}/echo`) .send({ name: 'tobi' }) .send({ age: 1 }) .end((err, res) => { res.should.be.json(); res.text.should.equal('{"name":"tobi","age":1}'); ({ name: 'tobi', age: 1 }.should.eql(res.body)); done(); });
when called several times
res.body
- should parse the body
- request.get(`${uri}/json`).end((err, res) => { res.text.should.equal('{"name":"manny"}'); res.body.should.eql({ name: 'manny' }); done(); });
- should not throw a parse error
- request.head(`${uri}/json`).end((err, res) => { try { assert.strictEqual(err, null); assert.strictEqual(res.text, undefined); assert.strictEqual(Object.keys(res.body).length, 0); done(); } catch (err_) { done(err_); } });
- should return the raw response
- request.get(`${uri}/invalid-json`).end((err, res) => { assert.deepEqual( err.rawResponse, ")]}', {'header':{'code':200,'text':'OK','version':'1.0'},'data':'some data'}" ); done(); });
- should return the http status code
- request.get(`${uri}/invalid-json-forbidden`).end((err, res) => { assert.equal(err.statusCode, 403); done(); });
- should not throw a parse error
- request.get(`${uri}/no-content`).end((err, res) => { try { assert.strictEqual(err, null); assert.strictEqual(res.text, ''); assert.strictEqual(Object.keys(res.body).length, 0); done(); } catch (err_) { done(err_); } });
- should parse the body
- request.get(`${uri}/json-hal`).end((err, res) => { if (err) return done(err); res.text.should.equal('{"name":"hal 5000"}'); res.body.should.eql({ name: 'hal 5000' }); done(); });
- should parse the body
- request.get(`${uri}/collection-json`).end((err, res) => { res.text.should.equal('{"name":"chewbacca"}'); res.body.should.eql({ name: 'chewbacca' }); done(); });
application/json
HEAD requests
Invalid JSON response
No content
application/json+hal
vnd.collection+json
request
- should retain header fields
- request .get(`${base}/header`) .set('X-Foo', 'bar') .end((err, res) => { try { assert(res.body); res.body.should.have.property('x-foo', 'bar'); done(); } catch (err_) { done(err_); } });
- should preserve timeout across redirects
- request .get(`${base}/movies/random`) .timeout(250) .end((err, res) => { try { assert(err instanceof Error, 'expected an error'); err.should.have.property('timeout', 250); done(); } catch (err_) { done(err_); } });
- should successfully redirect after retry on error
- const id = Math.random() * 1000000 * Date.now(); request .get(`${base}/error/redirect/${id}`) .retry(2) .end((err, res) => { assert(res.ok, 'response should be ok'); assert(res.text, 'first movie page'); done(); });
- should preserve retries across redirects
- const id = Math.random() * 1000000 * Date.now(); request .get(`${base}/error/redirect-error${id}`) .retry(2) .end((err, res) => { assert(err, 'expected an error'); assert.equal(2, err.retries, 'expected an error with .retries'); assert.equal(500, err.status, 'expected an error status of 500'); done(); });
- should redirect with same method
- request .put(`${base}/redirect-303`) .send({ msg: 'hello' }) .redirects(1) .on('redirect', (res) => { res.headers.location.should.equal('/reply-method'); }) .end((err, res) => { if (err) { done(err); return; } res.text.should.equal('method=get'); done(); });
- should redirect with same method
- if (isMSIE) return done(); // IE9 broken request .put(`${base}/redirect-307`) .send({ msg: 'hello' }) .redirects(1) .on('redirect', (res) => { res.headers.location.should.equal('/reply-method'); }) .end((err, res) => { if (err) { done(err); return; } res.text.should.equal('method=put'); done(); });
- should redirect with same method
- if (isMSIE) return done(); // IE9 broken request .put(`${base}/redirect-308`) .send({ msg: 'hello' }) .redirects(1) .on('redirect', (res) => { res.headers.location.should.equal('/reply-method'); }) .end((err, res) => { if (err) { done(err); return; } res.text.should.equal('method=put'); done(); });
on redirect
on 303
on 307
on 308
request
- Request inheritance
- assert(request.get(`${uri}/`) instanceof request.Request);
- request() simple GET without callback
- request('GET', 'test/test.request.js').end(); next();
- request() simple GET
- request('GET', `${uri}/ok`).end((err, res) => { try { assert(res instanceof request.Response, 'respond with Response'); assert(res.ok, 'response should be ok'); assert(res.text, 'res.text'); next(); } catch (err_) { next(err_); } });
- request() simple HEAD
- request.head(`${uri}/ok`).end((err, res) => { try { assert(res instanceof request.Response, 'respond with Response'); assert(res.ok, 'response should be ok'); assert(!res.text, 'res.text'); next(); } catch (err_) { next(err_); } });
- request() GET 5xx
- request('GET', `${uri}/error`).end((err, res) => { try { assert(err); assert.equal(err.message, 'Internal Server Error'); assert(!res.ok, 'response should not be ok'); assert(res.error, 'response should be an error'); assert(!res.clientError, 'response should not be a client error'); assert(res.serverError, 'response should be a server error'); next(); } catch (err_) { next(err_); } });
- request() GET 4xx
- request('GET', `${uri}/notfound`).end((err, res) => { try { assert(err); assert.equal(err.message, 'Not Found'); assert(!res.ok, 'response should not be ok'); assert(res.error, 'response should be an error'); assert(res.clientError, 'response should be a client error'); assert(!res.serverError, 'response should not be a server error'); next(); } catch (err_) { next(err_); } });
- request() GET 404 Not Found
- request('GET', `${uri}/notfound`).end((err, res) => { try { assert(err); assert(res.notFound, 'response should be .notFound'); next(); } catch (err_) { next(err_); } });
- request() GET 400 Bad Request
- request('GET', `${uri}/bad-request`).end((err, res) => { try { assert(err); assert(res.badRequest, 'response should be .badRequest'); next(); } catch (err_) { next(err_); } });
- request() GET 401 Bad Request
- request('GET', `${uri}/unauthorized`).end((err, res) => { try { assert(err); assert(res.unauthorized, 'response should be .unauthorized'); next(); } catch (err_) { next(err_); } });
- request() GET 406 Not Acceptable
- request('GET', `${uri}/not-acceptable`).end((err, res) => { try { assert(err); assert(res.notAcceptable, 'response should be .notAcceptable'); next(); } catch (err_) { next(err_); } });
- request() GET 204 No Content
- request('GET', `${uri}/no-content`).end((err, res) => { try { assert.ifError(err); assert(res.noContent, 'response should be .noContent'); next(); } catch (err_) { next(err_); } });
- request() DELETE 204 No Content
- request('DELETE', `${uri}/no-content`).end((err, res) => { try { assert.ifError(err); assert(res.noContent, 'response should be .noContent'); next(); } catch (err_) { next(err_); } });
- request() header parsing
- request('GET', `${uri}/notfound`).end((err, res) => { try { assert(err); assert.equal('text/html; charset=utf-8', res.header['content-type']); assert.equal('Express', res.header['x-powered-by']); next(); } catch (err_) { next(err_); } });
- request() .status
- request('GET', `${uri}/notfound`).end((err, res) => { try { assert(err); assert.equal(404, res.status, 'response .status'); assert.equal(4, res.statusType, 'response .statusType'); next(); } catch (err_) { next(err_); } });
- get()
- request.get(`${uri}/notfound`).end((err, res) => { try { assert(err); assert.equal(404, res.status, 'response .status'); assert.equal(4, res.statusType, 'response .statusType'); next(); } catch (err_) { next(err_); } });
- put()
- request.put(`${uri}/user/12`).end((err, res) => { try { assert.equal('updated', res.text, 'response text'); next(); } catch (err_) { next(err_); } });
- put().send()
- request .put(`${uri}/user/13/body`) .send({ user: 'new' }) .end((err, res) => { try { assert.equal('received new', res.text, 'response text'); next(); } catch (err_) { next(err_); } });
- post()
- request.post(`${uri}/user`).end((err, res) => { try { assert.equal('created', res.text, 'response text'); next(); } catch (err_) { next(err_); } });
- del()
- request.del(`${uri}/user/12`).end((err, res) => { try { assert.equal('deleted', res.text, 'response text'); next(); } catch (err_) { next(err_); } });
- delete()
- request.delete(`${uri}/user/12`).end((err, res) => { try { assert.equal('deleted', res.text, 'response text'); next(); } catch (err_) { next(err_); } });
- post() data
- request .post(`${uri}/todo/item`) .type('application/octet-stream') .send('tobi') .end((err, res) => { try { assert.equal('added "tobi"', res.text, 'response text'); next(); } catch (err_) { next(err_); } });
- request .type()
- request .post(`${uri}/user/12/pet`) .type('urlencoded') .send('pet=tobi') .end((err, res) => { try { assert.equal('added pet "tobi"', res.text, 'response text'); next(); } catch (err_) { next(err_); } });
- request .type() with alias
- request .post(`${uri}/user/12/pet`) .type('application/x-www-form-urlencoded') .send('pet=tobi') .end((err, res) => { try { assert.equal('added pet "tobi"', res.text, 'response text'); next(); } catch (err_) { next(err_); } });
- request .get() with no data or callback
- request.get(`${uri}/echo-header/content-type`); next();
- request .send() with no data only
- request.post(`${uri}/user/5/pet`).type('urlencoded').send('pet=tobi'); next();
- request .send() with callback only
- request .get(`${uri}/echo-header/accept`) .set('Accept', 'foo/bar') .end((err, res) => { try { assert.equal('foo/bar', res.text); next(); } catch (err_) { next(err_); } });
- request .accept() with json
- request .get(`${uri}/echo-header/accept`) .accept('json') .end((err, res) => { try { assert.equal('application/json', res.text); next(); } catch (err_) { next(err_); } });
- request .accept() with application/json
- request .get(`${uri}/echo-header/accept`) .accept('application/json') .end((err, res) => { try { assert.equal('application/json', res.text); next(); } catch (err_) { next(err_); } });
- request .accept() with xml
- request .get(`${uri}/echo-header/accept`) .accept('xml') .end((err, res) => { try { // We can't depend on mime module to be consistent with this assert(res.text == 'application/xml' || res.text == 'text/xml'); next(); } catch (err_) { next(err_); } });
- request .accept() with application/xml
- request .get(`${uri}/echo-header/accept`) .accept('application/xml') .end((err, res) => { try { assert.equal('application/xml', res.text); next(); } catch (err_) { next(err_); } });
- request .end()
- request .put(`${uri}/echo-header/content-type`) .set('Content-Type', 'text/plain') .send('wahoo') .end((err, res) => { try { assert.equal('text/plain', res.text); next(); } catch (err_) { next(err_); } });
- request .send()
- request .put(`${uri}/echo-header/content-type`) .set('Content-Type', 'text/plain') .send('wahoo') .end((err, res) => { try { assert.equal('text/plain', res.text); next(); } catch (err_) { next(err_); } });
- request .set()
- request .put(`${uri}/echo-header/content-type`) .set('Content-Type', 'text/plain') .send('wahoo') .end((err, res) => { try { assert.equal('text/plain', res.text); next(); } catch (err_) { next(err_); } });
- request .set(object)
- request .put(`${uri}/echo-header/content-type`) .set({ 'Content-Type': 'text/plain' }) .send('wahoo') .end((err, res) => { try { assert.equal('text/plain', res.text); next(); } catch (err_) { next(err_); } });
- POST urlencoded
- request .post(`${uri}/pet`) .type('urlencoded') .send({ name: 'Manny', species: 'cat' }) .end((err, res) => { try { assert.equal('added Manny the cat', res.text); next(); } catch (err_) { next(err_); } });
- POST json
- request .post(`${uri}/pet`) .type('json') .send({ name: 'Manny', species: 'cat' }) .end((err, res) => { try { assert.equal('added Manny the cat', res.text); next(); } catch (err_) { next(err_); } });
- POST json array
- request .post(`${uri}/echo`) .send([1, 2, 3]) .end((err, res) => { try { assert.equal( 'application/json', res.header['content-type'].split(';')[0] ); assert.equal('[1,2,3]', res.text); next(); } catch (err_) { next(err_); } });
- POST json default
- request .post(`${uri}/pet`) .send({ name: 'Manny', species: 'cat' }) .end((err, res) => { try { assert.equal('added Manny the cat', res.text); next(); } catch (err_) { next(err_); } });
- POST json contentType charset
- request .post(`${uri}/echo`) .set('Content-Type', 'application/json; charset=UTF-8') .send({ data: ['data1', 'data2'] }) .end((err, res) => { try { assert.equal('{"data":["data1","data2"]}', res.text); next(); } catch (err_) { next(err_); } });
- POST json contentType vendor
- request .post(`${uri}/echo`) .set('Content-Type', 'application/vnd.example+json') .send({ data: ['data1', 'data2'] }) .end((err, res) => { try { assert.equal('{"data":["data1","data2"]}', res.text); next(); } catch (err_) { next(err_); } });
- POST multiple .send() calls
- request .post(`${uri}/pet`) .send({ name: 'Manny' }) .send({ species: 'cat' }) .end((err, res) => { try { assert.equal('added Manny the cat', res.text); next(); } catch (err_) { next(err_); } });
- POST multiple .send() strings
- request .post(`${uri}/echo`) .send('user[name]=tj') .send('user[email]=tj@vision-media.ca') .end((err, res) => { try { assert.equal( 'application/x-www-form-urlencoded', res.header['content-type'].split(';')[0] ); assert.equal( res.text, 'user[name]=tj&user[email]=tj@vision-media.ca' ); next(); } catch (err_) { next(err_); } });
- POST with no data
- request .post(`${uri}/empty-body`) .send() .end((err, res) => { try { assert.ifError(err); assert(res.noContent, 'response should be .noContent'); next(); } catch (err_) { next(err_); } });
- GET .type
- request.get(`${uri}/pets`).end((err, res) => { try { assert.equal('application/json', res.type); next(); } catch (err_) { next(err_); } });
- GET Content-Type params
- request.get(`${uri}/text`).end((err, res) => { try { assert.equal('utf-8', res.charset); next(); } catch (err_) { next(err_); } });
- GET json
- request.get(`${uri}/pets`).end((err, res) => { try { assert.deepEqual(res.body, ['tobi', 'loki', 'jane']); next(); } catch (err_) { next(err_); } });
- GET json-seq
- request .get(`${uri}/json-seq`) .buffer() .end((err, res) => { try { assert.ifError(err); assert.deepEqual(res.text, '\u001E{"id":1}\n\u001E{"id":2}\n'); next(); } catch (err_) { next(err_); } });
- GET x-www-form-urlencoded
- request.get(`${uri}/foo`).end((err, res) => { try { assert.deepEqual(res.body, { foo: 'bar' }); next(); } catch (err_) { next(err_); } });
- GET shorthand
- request.get(`${uri}/foo`, (err, res) => { try { assert.equal('foo=bar', res.text); next(); } catch (err_) { next(err_); } });
- POST shorthand
- request.post(`${uri}/user/0/pet`, { pet: 'tobi' }, (err, res) => { try { assert.equal('added pet "tobi"', res.text); next(); } catch (err_) { next(err_); } });
- POST shorthand without callback
- request.post(`${uri}/user/0/pet`, { pet: 'tobi' }).end((err, res) => { try { assert.equal('added pet "tobi"', res.text); next(); } catch (err_) { next(err_); } });
- GET querystring object with array
- request .get(`${uri}/querystring`) .query({ val: ['a', 'b', 'c'] }) .end((err, res) => { try { assert.deepEqual(res.body, { val: ['a', 'b', 'c'] }); next(); } catch (err_) { next(err_); } });
- GET querystring object with array and primitives
- request .get(`${uri}/querystring`) .query({ array: ['a', 'b', 'c'], string: 'foo', number: 10 }) .end((err, res) => { try { assert.deepEqual(res.body, { array: ['a', 'b', 'c'], string: 'foo', number: 10 }); next(); } catch (err_) { next(err_); } });
- GET querystring object with two arrays
- request .get(`${uri}/querystring`) .query({ array1: ['a', 'b', 'c'], array2: [1, 2, 3] }) .end((err, res) => { try { assert.deepEqual(res.body, { array1: ['a', 'b', 'c'], array2: [1, 2, 3] }); next(); } catch (err_) { next(err_); } });
- GET querystring object
- request .get(`${uri}/querystring`) .query({ search: 'Manny' }) .end((err, res) => { try { assert.deepEqual(res.body, { search: 'Manny' }); next(); } catch (err_) { next(err_); } });
- GET querystring append original
- request .get(`${uri}/querystring?search=Manny`) .query({ range: '1..5' }) .end((err, res) => { try { assert.deepEqual(res.body, { search: 'Manny', range: '1..5' }); next(); } catch (err_) { next(err_); } });
- GET querystring multiple objects
- request .get(`${uri}/querystring`) .query({ search: 'Manny' }) .query({ range: '1..5' }) .query({ order: 'desc' }) .end((err, res) => { try { assert.deepEqual(res.body, { search: 'Manny', range: '1..5', order: 'desc' }); next(); } catch (err_) { next(err_); } });
- GET querystring with strings
- request .get(`${uri}/querystring`) .query('search=Manny') .query('range=1..5') .query('order=desc') .end((err, res) => { try { assert.deepEqual(res.body, { search: 'Manny', range: '1..5', order: 'desc' }); next(); } catch (err_) { next(err_); } });
- GET querystring with strings and objects
- request .get(`${uri}/querystring`) .query('search=Manny') .query({ order: 'desc', range: '1..5' }) .end((err, res) => { try { assert.deepEqual(res.body, { search: 'Manny', range: '1..5', order: 'desc' }); next(); } catch (err_) { next(err_); } });
- GET shorthand payload goes to querystring
- request.get( `${uri}/querystring`, { foo: 'FOO', bar: 'BAR' }, (err, res) => { try { assert.deepEqual(res.body, { foo: 'FOO', bar: 'BAR' }); next(); } catch (err_) { next(err_); } } );
- HEAD shorthand payload goes to querystring
- request.head( `${uri}/querystring-in-header`, { foo: 'FOO', bar: 'BAR' }, (err, res) => { try { assert.deepEqual(JSON.parse(res.headers.query), { foo: 'FOO', bar: 'BAR' }); next(); } catch (err_) { next(err_); } } );
- request(method, url)
- request('GET', `${uri}/foo`).end((err, res) => { try { assert.equal('bar', res.body.foo); next(); } catch (err_) { next(err_); } });
- request(url)
- request(`${uri}/foo`).end((err, res) => { try { assert.equal('bar', res.body.foo); next(); } catch (err_) { next(err_); } });
- request(url, fn)
- request(`${uri}/foo`, (err, res) => { try { assert.equal('bar', res.body.foo); next(); } catch (err_) { next(err_); } });
- req.timeout(ms)
- const req = request.get(`${uri}/delay/3000`).timeout(1000); req.end((err, res) => { try { assert(err, 'error missing'); assert.equal(1000, err.timeout, 'err.timeout missing'); assert.equal( 'Timeout of 1000ms exceeded', err.message, 'err.message incorrect' ); assert.equal(null, res); assert(req.timedout, true); next(); } catch (err_) { next(err_); } });
- req.timeout(ms) with redirect
- const req = request.get(`${uri}/delay/const`).timeout(1000); req.end((err, res) => { try { assert(err, 'error missing'); assert.equal(1000, err.timeout, 'err.timeout missing'); assert.equal( 'Timeout of 1000ms exceeded', err.message, 'err.message incorrect' ); assert.equal(null, res); assert(req.timedout, true); next(); } catch (err_) { next(err_); } });
- request event
- request .get(`${uri}/foo`) .on('request', (req) => { try { assert.equal(`${uri}/foo`, req.url); next(); } catch (err) { next(err); } }) .end();
- response event
- request .get(`${uri}/foo`) .on('response', (res) => { try { assert.equal('bar', res.body.foo); next(); } catch (err) { next(err); } }) .end();
- response should set statusCode
- request.get(`${uri}/ok`, (err, res) => { try { assert.strictEqual(res.statusCode, 200); next(); } catch (err_) { next(err_); } });
- req.toJSON()
- request.get(`${uri}/ok`).end((err, res) => { try { const j = (res.request || res.req).toJSON(); ['url', 'method', 'data', 'headers'].forEach((prop) => { assert(j.hasOwnProperty(prop)); }); next(); } catch (err_) { next(err_); } });
.retry(count)
- should not retry if passed "0"
- request .get(`${base}/error`) .retry(0) .end((err, res) => { try { assert(err, 'expected an error'); assert.equal( undefined, err.retries, 'expected an error without .retries' ); assert.equal(500, err.status, 'expected an error status of 500'); done(); } catch (err_) { done(err_); } });
- should not retry if passed an invalid number
- request .get(`${base}/error`) .retry(-2) .end((err, res) => { try { assert(err, 'expected an error'); assert.equal( undefined, err.retries, 'expected an error without .retries' ); assert.equal(500, err.status, 'expected an error status of 500'); done(); } catch (err_) { done(err_); } });
- should not retry if passed undefined
- request .get(`${base}/error`) .retry(undefined) .end((err, res) => { try { assert(err, 'expected an error'); assert.equal( undefined, err.retries, 'expected an error without .retries' ); assert.equal(500, err.status, 'expected an error status of 500'); done(); } catch (err_) { done(err_); } });
- should handle server error after repeat attempt
- request .get(`${base}/error`) .retry(2) .end((err, res) => { try { assert(err, 'expected an error'); assert.equal(2, err.retries, 'expected an error with .retries'); assert.equal(500, err.status, 'expected an error status of 500'); done(); } catch (err_) { done(err_); } });
- should retry if passed nothing
- request .get(`${base}/error`) .retry() .end((err, res) => { try { assert(err, 'expected an error'); assert.equal(1, err.retries, 'expected an error with .retries'); assert.equal(500, err.status, 'expected an error status of 500'); done(); } catch (err_) { done(err_); } });
- should retry if passed "true"
- request .get(`${base}/error`) .retry(true) .end((err, res) => { try { assert(err, 'expected an error'); assert.equal(1, err.retries, 'expected an error with .retries'); assert.equal(500, err.status, 'expected an error status of 500'); done(); } catch (err_) { done(err_); } });
- should handle successful request after repeat attempt from server error
- request .get(`${base}/error/ok/${uniqid()}`) .query({ qs: 'present' }) .retry(2) .end((err, res) => { try { assert.ifError(err); assert(res.ok, 'response should be ok'); assert(res.text, 'res.text'); done(); } catch (err_) { done(err_); } });
- should handle server timeout error after repeat attempt
- request .get(`${base}/delay/400`) .timeout(200) .retry(2) .end((err, res) => { try { assert(err, 'expected an error'); assert.equal(2, err.retries, 'expected an error with .retries'); assert.equal( 'number', typeof err.timeout, 'expected an error with .timeout' ); assert.equal('ECONNABORTED', err.code, 'expected abort error code'); done(); } catch (err_) { done(err_); } });
- should handle successful request after repeat attempt from server timeout
- const url = `/delay/1200/ok/${uniqid()}?built=in`; request .get(base + url) .query('string=ified') .query({ json: 'ed' }) .timeout(600) .retry(2) .end((err, res) => { try { assert.ifError(err); assert(res.ok, 'response should be ok'); assert.equal(res.text, `ok = ${url}&string=ified&json=ed`); done(); } catch (err_) { done(err_); } });
- should handle successful request after repeat attempt from server timeout when using .then(fulfill, reject)
- const url = `/delay/1200/ok/${uniqid()}?built=in`; request .get(base + url) .query('string=ified') .query({ json: 'ed' }) .timeout(600) .retry(1) .then((res, err) => { try { assert.ifError(err); assert(res.ok, 'response should be ok'); assert.equal(res.text, `ok = ${url}&string=ified&json=ed`); done(); } catch (err_) { done(err_); } });
- should correctly abort a retry attempt
- let aborted = false; const req = request.get(`${base}/delay/400`).timeout(200).retry(2); req.end((err, res) => { try { assert(false, 'should not complete the request'); } catch (err_) { done(err_); } }); req.on('abort', () => { aborted = true; }); setTimeout(() => { req.abort(); setTimeout(() => { try { assert(aborted, 'should be aborted'); done(); } catch (err) { done(err); } }, 150); }, 150);
- should correctly retain header fields
- request .get(`${base}/error/ok/${uniqid()}`) .query({ qs: 'present' }) .retry(2) .set('X-Foo', 'bar') .end((err, res) => { try { assert.ifError(err); assert(res.body); res.body.should.have.property('x-foo', 'bar'); done(); } catch (err_) { done(err_); } });
- should not retry on 4xx responses
- request .get(`${base}/bad-request`) .retry(2) .end((err, res) => { try { assert(err, 'expected an error'); assert.equal(0, err.retries, 'expected an error with 0 .retries'); assert.equal(400, err.status, 'expected an error status of 400'); done(); } catch (err_) { done(err_); } });
- should execute callback on retry if passed
- let callbackCallCount = 0; function retryCallback(request) { callbackCallCount++; } request .get(`${base}/error`) .retry(2, retryCallback) .end((err, res) => { try { assert(err, 'expected an error'); assert.equal(2, err.retries, 'expected an error with .retries'); assert.equal(500, err.status, 'expected an error status of 500'); assert.equal( 2, callbackCallCount, 'expected the callback to be called on each retry' ); done(); } catch (err_) { done(err_); } });
.timeout(ms)
- should error
- request .get(`${base}/delay/500`) .timeout(150) .end((err, res) => { assert(err, 'expected an error'); assert.equal( 'number', typeof err.timeout, 'expected an error with .timeout' ); assert.equal('ECONNABORTED', err.code, 'expected abort error code'); done(); });
- should error in promise interface
- request .get(`${base}/delay/500`) .timeout(150) .catch((err) => { assert(err, 'expected an error'); assert.equal( 'number', typeof err.timeout, 'expected an error with .timeout' ); assert.equal('ECONNABORTED', err.code, 'expected abort error code'); done(); });
- should handle gzip timeout
- request .get(`${base}/delay/zip`) .timeout(150) .end((err, res) => { assert(err, 'expected an error'); assert.equal( 'number', typeof err.timeout, 'expected an error with .timeout' ); assert.equal('ECONNABORTED', err.code, 'expected abort error code'); done(); });
- should handle buffer timeout
- request .get(`${base}/delay/json`) .buffer(true) .timeout(150) .end((err, res) => { assert(err, 'expected an error'); assert.equal( 'number', typeof err.timeout, 'expected an error with .timeout' ); assert.equal('ECONNABORTED', err.code, 'expected abort error code'); done(); });
- should error on deadline
- request .get(`${base}/delay/500`) .timeout({ deadline: 150 }) .end((err, res) => { assert(err, 'expected an error'); assert.equal( 'number', typeof err.timeout, 'expected an error with .timeout' ); assert.equal('ECONNABORTED', err.code, 'expected abort error code'); done(); });
- should support setting individual options
- request .get(`${base}/delay/500`) .timeout({ deadline: 10 }) .timeout({ response: 99999 }) .end((err, res) => { assert(err, 'expected an error'); assert.equal('ECONNABORTED', err.code, 'expected abort error code'); assert.equal('ETIME', err.errno); done(); });
- should error on response
- request .get(`${base}/delay/500`) .timeout({ response: 150 }) .end((err, res) => { assert(err, 'expected an error'); assert.equal( 'number', typeof err.timeout, 'expected an error with .timeout' ); assert.equal('ECONNABORTED', err.code, 'expected abort error code'); assert.equal('ETIMEDOUT', err.errno); done(); });
- should accept slow body with fast response
- request .get(`${base}/delay/slowbody`) .timeout({ response: 1000 }) .on('progress', () => { // This only makes the test faster without relying on arbitrary timeouts request.get(`${base}/delay/slowbody/finish`).end(); }) .end(done);
when timeout is exceeded
request
- should use plugin success
- const now = `${Date.now()}`; function uuid(req) { req.set('X-UUID', now); return req; } function prefix(req) { req.url = uri + req.url; return req; } request .get('/echo') .use(uuid) .use(prefix) .end((err, res) => { assert.strictEqual(res.statusCode, 200); assert.equal(res.get('X-UUID'), now); done(); });
use
subclass
- should be an instance of Request
- const req = request.get('/'); assert(req instanceof request.Request);
- should use patched subclass
- assert(OriginalRequest); let constructorCalled; let sendCalled; function NewRequest(...args) { constructorCalled = true; OriginalRequest.apply(this, args); } NewRequest.prototype = Object.create(OriginalRequest.prototype); NewRequest.prototype.send = function () { sendCalled = true; return this; }; request.Request = NewRequest; const req = request.get('/').send(); assert(constructorCalled); assert(sendCalled); assert(req instanceof NewRequest); assert(req instanceof OriginalRequest);
- should use patched subclass in agent too
- if (!request.agent) return; // Node-only function NewRequest(...args) { OriginalRequest.apply(this, args); } NewRequest.prototype = Object.create(OriginalRequest.prototype); request.Request = NewRequest; const req = request.agent().del('/'); assert(req instanceof NewRequest); assert(req instanceof OriginalRequest);
request
- should gain a session on POST
- agent3.post(`${base}/signin`).then((res) => { res.should.have.status(200); should.not.exist(res.headers['set-cookie']); res.text.should.containEql('dashboard'); })
- should start with empty session (set cookies)
- agent1.get(`${base}/dashboard`).end((err, res) => { should.exist(err); res.should.have.status(401); should.exist(res.headers['set-cookie']); done(); });
- should gain a session (cookies already set)
- agent1.post(`${base}/signin`).then((res) => { res.should.have.status(200); should.not.exist(res.headers['set-cookie']); res.text.should.containEql('dashboard'); })
- should persist cookies across requests
- agent1.get(`${base}/dashboard`).then((res) => { res.should.have.status(200); })
- should have the cookie set in the end callback
- agent4 .post(`${base}/setcookie`) .then(() => agent4.get(`${base}/getcookie`)) .then((res) => { res.should.have.status(200); assert.strictEqual(res.text, 'jar'); })
- should not share cookies
- agent2.get(`${base}/dashboard`).end((err, res) => { should.exist(err); res.should.have.status(401); done(); });
- should not lose cookies between agents
- agent1.get(`${base}/dashboard`).then((res) => { res.should.have.status(200); })
- should be able to follow redirects
- agent1.get(base).then((res) => { res.should.have.status(200); res.text.should.containEql('dashboard'); })
- should be able to post redirects
- agent1 .post(`${base}/redirect`) .send({ foo: 'bar', baz: 'blaaah' }) .then((res) => { res.should.have.status(200); res.text.should.containEql('simple'); res.redirects.should.eql([`${base}/simple`]); })
- should be able to limit redirects
- agent1 .get(base) .redirects(0) .end((err, res) => { should.exist(err); res.should.have.status(302); res.redirects.should.eql([]); res.header.location.should.equal('/dashboard'); done(); });
- should be able to create a new session (clear cookie)
- agent1.post(`${base}/signout`).then((res) => { res.should.have.status(200); should.exist(res.headers['set-cookie']); })
- should regenerate with an empty session
- agent1.get(`${base}/dashboard`).end((err, res) => { should.exist(err); res.should.have.status(401); should.not.exist(res.headers['set-cookie']); done(); });
persistent agent
Basic auth
- should set Authorization
- const new_url = URL.parse(base); new_url.auth = 'tobi:learnboost'; new_url.pathname = '/basic-auth'; request.get(URL.format(new_url)).end((err, res) => { res.status.should.equal(200); done(); });
- should set Authorization
- request .get(`${base}/basic-auth`) .auth('tobi', 'learnboost') .end((err, res) => { res.status.should.equal(200); done(); });
- should set authorization
- request .get(`${base}/basic-auth/again`) .auth('tobi') .end((err, res) => { res.status.should.eql(200); done(); });
when credentials are present in url
req.auth(user, pass)
req.auth(user + ":" + pass)
[node] request
- should send body with .get().send()
- request .get(`${base}/echo`) .set('Content-Type', 'text/plain') .send('wahoo') .end((err, res) => { try { assert.equal('wahoo', res.text); next(); } catch (err_) { next(err_); } });
- should preserve the encoding of the url
- request.get(`${base}/url?a=(b%29`).end((err, res) => { assert.equal('/url?a=(b%29', res.text); done(); });
- should format the url
- request.get(url.parse(`${base}/login`)).then((res) => { assert(res.ok); })
- should default to http
- request.get('localhost:5000/login').then((res) => { assert.equal(res.status, 200); })
- should describe the response
- request .post(`${base}/echo`) .send({ foo: 'baz' }) .then((res) => { const obj = res.toJSON(); assert.equal('object', typeof obj.header); assert.equal('object', typeof obj.req); assert.equal(200, obj.status); assert.equal('{"foo":"baz"}', obj.text); })
- should default to an empty object
- request.get(`${base}/login`).then((res) => { res.links.should.eql({}); })
- should parse the Link header field
- request.get(`${base}/links`).end((err, res) => { res.links.next.should.equal( 'https://api.github.com/repos/visionmedia/mocha/issues?page=2' ); done(); });
- should remove the header field
- request .post(`${base}/echo`) .unset('User-Agent') .end((err, res) => { assert.equal(void 0, res.header['user-agent']); done(); });
- should set/get header fields case-insensitively
- const r = request.post(`${base}/echo`); r.set('MiXeD', 'helloes'); assert.strictEqual(r.get('mixed'), 'helloes');
- should unset header fields case-insensitively
- const r = request.post(`${base}/echo`); r.set('MiXeD', 'helloes'); r.unset('MIXED'); assert.strictEqual(r.get('mixed'), undefined);
- should write the given data
- const req = request.post(`${base}/echo`); req.set('Content-Type', 'application/json'); assert.equal('boolean', typeof req.write('{"name"')); assert.equal('boolean', typeof req.write(':"tobi"}')); req.end((err, res) => { res.text.should.equal('{"name":"tobi"}'); done(); });
- should pipe the response to the given stream
- const stream = new EventEmitter(); stream.buf = ''; stream.writable = true; stream.write = function (chunk) { this.buf += chunk; }; stream.end = function () { this.buf.should.equal('{"name":"tobi"}'); done(); }; request.post(`${base}/echo`).send('{"name":"tobi"}').pipe(stream);
- should enable buffering
- request .get(`${base}/custom`) .buffer() .end((err, res) => { assert.ifError(err); assert.equal('custom stuff', res.text); assert(res.buffered); done(); });
- should take precedence over request.buffer['someMimeType'] = false
- const type = 'application/barbaz'; const send = 'some text'; request.buffer[type] = false; request .post(`${base}/echo`) .type(type) .send(send) .buffer() .end((err, res) => { delete request.buffer[type]; assert.ifError(err); assert.equal(res.type, type); assert.equal(send, res.text); assert(res.buffered); done(); });
- should disable buffering
- request .post(`${base}/echo`) .type('application/x-dog') .send('hello this is dog') .buffer(false) .end((err, res) => { assert.ifError(err); assert.equal(null, res.text); res.body.should.eql({}); let buf = ''; res.setEncoding('utf8'); res.on('data', (chunk) => { buf += chunk; }); res.on('end', () => { buf.should.equal('hello this is dog'); done(); }); });
- should take precedence over request.buffer['someMimeType'] = true
- const type = 'application/foobar'; const send = 'hello this is a dog'; request.buffer[type] = true; request .post(`${base}/echo`) .type(type) .send(send) .buffer(false) .end((err, res) => { delete request.buffer[type]; assert.ifError(err); assert.equal(null, res.text); assert.equal(res.type, type); assert(!res.buffered); res.body.should.eql({}); let buf = ''; res.setEncoding('utf8'); res.on('data', (chunk) => { buf += chunk; }); res.on('end', () => { buf.should.equal(send); done(); }); });
- should not throw an error when using the client-side "withCredentials" method
- request .get(`${base}/custom`) .withCredentials() .end((err, res) => { assert.ifError(err); done(); });
- should return the defaut agent
- const req = request.post(`${base}/echo`); req.agent().should.equal(false); done();
- should set an agent to undefined and ensure it is chainable
- const req = request.get(`${base}/echo`); const ret = req.agent(undefined); ret.should.equal(req); assert.strictEqual(req.agent(), undefined); done();
- should set passed agent
- const http = require('http'); const req = request.get(`${base}/echo`); const agent = new http.Agent(); const ret = req.agent(agent); ret.should.equal(req); req.agent().should.equal(agent); done();
- should still use buffering
- return request .post(`${base}/echo`) .type('application/x-dog') .send('hello this is dog') .then((res) => { assert.equal(null, res.text); assert.equal(res.body.toString(), 'hello this is dog'); res.buffered.should.be.true; });
- should be set to the byte length of a non-buffer object
- const decoder = new StringDecoder('utf8'); let img = fs.readFileSync(`${__dirname}/fixtures/test.png`); img = decoder.write(img); request .post(`${base}/echo`) .type('application/x-image') .send(img) .buffer(false) .end((err, res) => { assert.ifError(err); assert(!res.buffered); assert.equal(res.header['content-length'], Buffer.byteLength(img)); done(); });
- should be set to the length of a buffer object
- const img = fs.readFileSync(`${__dirname}/fixtures/test.png`); request .post(`${base}/echo`) .type('application/x-image') .send(img) .buffer(true) .end((err, res) => { assert.ifError(err); assert(res.buffered); assert.equal(res.header['content-length'], img.length); done(); });
with an url
with an object
without a schema
res.toJSON()
res.links
req.unset(field)
case-insensitive
req.write(str)
req.pipe(stream)
.buffer()
.buffer(false)
.withCredentials()
.agent()
.agent(undefined)
.agent(new http.Agent())
with a content type other than application/json or text/*
content-length
req.buffer['someMimeType']
- should respect that agent.buffer(true) takes precedent
- const agent = request.agent(); agent.buffer(true); const type = 'application/somerandomtype'; const send = 'somerandomtext'; request.buffer[type] = false; agent .post(`${base}/echo`) .type(type) .send(send) .end((err, res) => { delete request.buffer[type]; assert.ifError(err); assert.equal(res.type, type); assert.equal(send, res.text); assert(res.buffered); done(); });
- should respect that agent.buffer(false) takes precedent
- const agent = request.agent(); agent.buffer(false); const type = 'application/barrr'; const send = 'some random text2'; request.buffer[type] = true; agent .post(`${base}/echo`) .type(type) .send(send) .end((err, res) => { delete request.buffer[type]; assert.ifError(err); assert.equal(null, res.text); assert.equal(res.type, type); assert(!res.buffered); res.body.should.eql({}); let buf = ''; res.setEncoding('utf8'); res.on('data', (chunk) => { buf += chunk; }); res.on('end', () => { buf.should.equal(send); done(); }); });
- should disable buffering for that mimetype when false
- const type = 'application/bar'; const send = 'some random text'; request.buffer[type] = false; request .post(`${base}/echo`) .type(type) .send(send) .end((err, res) => { delete request.buffer[type]; assert.ifError(err); assert.equal(null, res.text); assert.equal(res.type, type); assert(!res.buffered); res.body.should.eql({}); let buf = ''; res.setEncoding('utf8'); res.on('data', (chunk) => { buf += chunk; }); res.on('end', () => { buf.should.equal(send); done(); }); });
- should enable buffering for that mimetype when true
- const type = 'application/baz'; const send = 'woooo'; request.buffer[type] = true; request .post(`${base}/echo`) .type(type) .send(send) .end((err, res) => { delete request.buffer[type]; assert.ifError(err); assert.equal(res.type, type); assert.equal(send, res.text); assert(res.buffered); done(); });
- should fallback to default handling for that mimetype when undefined
- const type = 'application/bazzz'; const send = 'woooooo'; return request .post(`${base}/echo`) .type(type) .send(send) .then((res) => { assert.equal(res.type, type); assert.equal(send, res.body.toString()); assert(res.buffered); });
exports
- should expose .protocols
- Object.keys(request.protocols).should.eql(['http:', 'https:', 'http2:']);
- should expose .serialize
- Object.keys(request.serialize).should.eql([ 'application/x-www-form-urlencoded', 'application/json' ]);
- should expose .parse
- Object.keys(request.parse).should.eql([ 'application/x-www-form-urlencoded', 'application/json', 'text', 'application/octet-stream', 'application/pdf', 'image' ]);
- should export .buffer
- Object.keys(request.buffer).should.eql([]);
flags
- should set res.error and res.clientError
- request.get(`${base}/notfound`).end((err, res) => { assert(err); assert(!res.ok, 'response should not be ok'); assert(res.error, 'response should be an error'); assert(res.clientError, 'response should be a client error'); assert(!res.serverError, 'response should not be a server error'); done(); });
- should set res.error and res.serverError
- request.get(`${base}/error`).end((err, res) => { assert(err); assert(!res.ok, 'response should not be ok'); assert(!res.notFound, 'response should not be notFound'); assert(res.error, 'response should be an error'); assert(!res.clientError, 'response should not be a client error'); assert(res.serverError, 'response should be a server error'); done(); });
- should res.notFound
- request.get(`${base}/notfound`).end((err, res) => { assert(err); assert(res.notFound, 'response should be .notFound'); done(); });
- should set req.badRequest
- request.get(`${base}/bad-request`).end((err, res) => { assert(err); assert(res.badRequest, 'response should be .badRequest'); done(); });
- should set res.unauthorized
- request.get(`${base}/unauthorized`).end((err, res) => { assert(err); assert(res.unauthorized, 'response should be .unauthorized'); done(); });
- should set res.notAcceptable
- request.get(`${base}/not-acceptable`).end((err, res) => { assert(err); assert(res.notAcceptable, 'response should be .notAcceptable'); done(); });
- should set res.noContent
- request.get(`${base}/no-content`).end((err, res) => { assert(!err); assert(res.noContent, 'response should be .noContent'); done(); });
- should set res.created
- request.post(`${base}/created`).end((err, res) => { assert(!err); assert(res.created, 'response should be .created'); done(); });
- should set res.unprocessableEntity
- request.post(`${base}/unprocessable-entity`).end((err, res) => { assert(err); assert( res.unprocessableEntity, 'response should be .unprocessableEntity' ); done(); });
with 4xx response
with 5xx response
with 404 Not Found
with 400 Bad Request
with 401 Bad Request
with 406 Not Acceptable
with 204 No Content
with 201 Created
with 422 Unprocessable Entity
Merging objects
- Don't mix Buffer and JSON
- assert.throws(() => { request .post('/echo') .send(Buffer.from('some buffer')) .send({ allowed: false }); });
req.send(String)
- should default to "form"
- request .post(`${base}/echo`) .send('user[name]=tj') .send('user[email]=tj@vision-media.ca') .end((err, res) => { res.header['content-type'].should.equal( 'application/x-www-form-urlencoded' ); res.body.should.eql({ user: { name: 'tj', email: 'tj@vision-media.ca' } }); done(); });
res.body
- should parse the body
- request.get(`${base}/form-data`).end((err, res) => { res.text.should.equal('pet[name]=manny'); res.body.should.eql({ pet: { name: 'manny' } }); done(); });
application/x-www-form-urlencoded
https
- should give a good response
- request .get(testEndpoint) .ca(ca) .end((err, res) => { assert.ifError(err); assert(res.ok); assert.strictEqual('Safe and secure!', res.text); done(); });
- should reject unauthorized response
- return request .get(testEndpoint) .trustLocalhost(false) .then( () => { throw new Error('Allows MITM'); }, () => {} );
- should not reject unauthorized response
- return request .get(testEndpoint) .disableTLSCerts() .then(({ status }) => { assert.strictEqual(status, 200); });
- should trust localhost unauthorized response
- return request.get(testEndpoint).trustLocalhost(true);
- should trust overriden localhost unauthorized response
- return request .get(`https://example.com:${server.address().port}`) .connect('127.0.0.1') .trustLocalhost();
- should be able to make multiple requests without redefining the certificate
- const agent = request.agent({ ca }); agent.get(testEndpoint).end((err, res) => { assert.ifError(err); assert(res.ok); assert.strictEqual('Safe and secure!', res.text); agent.get(url.parse(testEndpoint)).end((err, res) => { assert.ifError(err); assert(res.ok); assert.strictEqual('Safe and secure!', res.text); done(); }); });
certificate authority
request
.agent
client certificates
request
.agent
res.body
- should parse the body
- request.get(`${base}/image`).end((err, res) => { res.type.should.equal('image/png'); Buffer.isBuffer(res.body).should.be.true(); (res.body.length - img.length).should.equal(0); done(); });
- should parse the body
- request .get(`${base}/image-as-octets`) .buffer(true) // that's tech debt :( .end((err, res) => { res.type.should.equal('application/octet-stream'); Buffer.isBuffer(res.body).should.be.true(); (res.body.length - img.length).should.equal(0); done(); });
- should parse the body (using responseType)
- request .get(`${base}/image-as-octets`) .responseType('blob') .end((err, res) => { res.type.should.equal('application/octet-stream'); Buffer.isBuffer(res.body).should.be.true(); (res.body.length - img.length).should.equal(0); done(); });
image/png
application/octet-stream
application/octet-stream
zlib
- should deflate the content
- request.get(base).end((err, res) => { res.should.have.status(200); res.text.should.equal(subject); res.headers['content-length'].should.be.below(subject.length); done(); });
- should protect from zip bombs
- request .get(base) .buffer(true) .maxResponseSize(1) .end((err, res) => { try { assert.equal('Maximum response size reached', err && err.message); done(); } catch (err_) { done(err_); } });
- should ignore trailing junk
- request.get(`${base}/junk`).end((err, res) => { res.should.have.status(200); res.text.should.equal(subject); done(); });
- should ignore missing data
- request.get(`${base}/chopped`).end((err, res) => { assert.equal(undefined, err); res.should.have.status(200); res.text.should.startWith(subject); done(); });
- should handle corrupted responses
- request.get(`${base}/corrupt`).end((err, res) => { assert(err, 'missing error'); assert(!res, 'response should not be defined'); done(); });
- should handle no content with gzip header
- request.get(`${base}/nocontent`).end((err, res) => { assert.ifError(err); assert(res); res.should.have.status(204); res.text.should.equal(''); res.headers.should.not.have.property('content-length'); done(); });
- should buffer if asked
- return request .get(`${base}/binary`) .buffer(true) .then((res) => { res.should.have.status(200); assert(res.headers['content-length']); assert(res.body.byteLength); assert.equal(subject, res.body.toString()); });
- should emit buffers
- request.get(`${base}/binary`).end((err, res) => { res.should.have.status(200); res.headers['content-length'].should.be.below(subject.length); res.on('data', (chunk) => { chunk.should.have.length(subject.length); }); res.on('end', done); });
without encoding set
Multipart
- should set a multipart field value
- const req = request.post(`${base}/echo`); req.field('user[name]', 'tobi'); req.field('user[age]', '2'); req.field('user[species]', 'ferret'); return req.then((res) => { res.body['user[name]'].should.equal('tobi'); res.body['user[age]'].should.equal('2'); res.body['user[species]'].should.equal('ferret'); });
- should work with file attachments
- const req = request.post(`${base}/echo`); req.field('name', 'Tobi'); req.attach('document', 'test/node/fixtures/user.html'); req.field('species', 'ferret'); return req.then((res) => { res.body.name.should.equal('Tobi'); res.body.species.should.equal('ferret'); const html = res.files.document; html.name.should.equal('user.html'); html.type.should.equal('text/html'); read(html.path).should.equal('<h1>name</h1>'); });
- should attach a file
- const req = request.post(`${base}/echo`); req.attach('one', 'test/node/fixtures/user.html'); req.attach('two', 'test/node/fixtures/user.json'); req.attach('three', 'test/node/fixtures/user.txt'); return req.then((res) => { const html = res.files.one; const json = res.files.two; const text = res.files.three; html.name.should.equal('user.html'); html.type.should.equal('text/html'); read(html.path).should.equal('<h1>name</h1>'); json.name.should.equal('user.json'); json.type.should.equal('application/json'); read(json.path).should.equal('{"name":"tobi"}'); text.name.should.equal('user.txt'); text.type.should.equal('text/plain'); read(text.path).should.equal('Tobi'); });
- should fail the request with an error
- const req = request.post(`${base}/echo`); req.attach('name', 'foo'); req.attach('name2', 'bar'); req.attach('name3', 'baz'); req.end((err, res) => { assert.ok(Boolean(err), 'Request should have failed.'); err.code.should.equal('ENOENT'); err.message.should.containEql('ENOENT'); err.path.should.equal('foo'); done(); });
- promise should fail
- return request .post(`${base}/echo`) .field({ a: 1, b: 2 }) .attach('c', 'does-not-exist.txt') .then( (res) => assert.fail('It should not allow this'), (err) => { err.code.should.equal('ENOENT'); err.path.should.equal('does-not-exist.txt'); } );
- should report ECONNREFUSED via the callback
- request .post('http://127.0.0.1:1') // nobody is listening there .attach('name', 'file-does-not-exist') .end((err, res) => { assert.ok(Boolean(err), 'Request should have failed'); err.code.should.equal('ECONNREFUSED'); done(); });
- should report ECONNREFUSED via Promise
- return request .post('http://127.0.0.1:1') // nobody is listening there .attach('name', 'file-does-not-exist') .then( (res) => assert.fail('Request should have failed'), (err) => err.code.should.equal('ECONNREFUSED') );
- should use the custom filename
- request .post(`${base}/echo`) .attach('document', 'test/node/fixtures/user.html', 'doc.html') .then((res) => { const html = res.files.document; html.name.should.equal('doc.html'); html.type.should.equal('text/html'); read(html.path).should.equal('<h1>name</h1>'); })
- should fire progress event
- let loaded = 0; let total = 0; let uploadEventWasFired = false; request .post(`${base}/echo`) .attach('document', 'test/node/fixtures/user.html') .on('progress', (event) => { total = event.total; loaded = event.loaded; if (event.direction === 'upload') { uploadEventWasFired = true; } }) .end((err, res) => { if (err) return done(err); const html = res.files.document; html.name.should.equal('user.html'); html.type.should.equal('text/html'); read(html.path).should.equal('<h1>name</h1>'); total.should.equal(223); loaded.should.equal(223); uploadEventWasFired.should.equal(true); done(); });
- filesystem errors should be caught
- request .post(`${base}/echo`) .attach('filedata', 'test/node/fixtures/non-existent-file.ext') .end((err, res) => { assert.ok(Boolean(err), 'Request should have failed.'); err.code.should.equal('ENOENT'); err.path.should.equal('test/node/fixtures/non-existent-file.ext'); done(); });
- should set a multipart field value
- request .post(`${base}/echo`) .field('first-name', 'foo') .field('last-name', 'bar') .end((err, res) => { if (err) done(err); res.should.be.ok(); res.body['first-name'].should.equal('foo'); res.body['last-name'].should.equal('bar'); done(); });
- should set multiple multipart fields
- request .post(`${base}/echo`) .field({ 'first-name': 'foo', 'last-name': 'bar' }) .end((err, res) => { if (err) done(err); res.should.be.ok(); res.body['first-name'].should.equal('foo'); res.body['last-name'].should.equal('bar'); done(); });
#field(name, value)
#attach(name, path)
when a file does not exist
#attach(name, path, filename)
#field(name, val)
#field(object)
with network error
- should error
- request.get(`http://localhost:${this.port}/`).end((err, res) => { assert(err, 'expected an error'); done(); });
request
- should start with 200
- request.get(`${base}/if-mod`).end((err, res) => { res.should.have.status(200); res.text.should.match(/^\d+$/); ts = Number(res.text); done(); });
- should then be 304
- request .get(`${base}/if-mod`) .set('If-Modified-Since', new Date(ts).toUTCString()) .end((err, res) => { res.should.have.status(304); // res.text.should.be.empty done(); });
not modified
req.parse(fn)
- should take precedence over default parsers
- request .get(`${base}/manny`) .parse(request.parse['application/json']) .end((err, res) => { assert(res.ok); assert.equal('{"name":"manny"}', res.text); assert.equal('manny', res.body.name); done(); });
- should be the only parser
- request .get(`${base}/image`) .buffer(false) .parse((res, fn) => { res.on('data', () => {}); }) .then((res) => { assert(res.ok); assert.strictEqual(res.text, undefined); res.body.should.eql({}); })
- should emit error if parser throws
- request .get(`${base}/manny`) .parse(() => { throw new Error('I am broken'); }) .on('error', (err) => { err.message.should.equal('I am broken'); done(); }) .end();
- should emit error if parser returns an error
- request .get(`${base}/manny`) .parse((res, fn) => { fn(new Error('I am broken')); }) .on('error', (err) => { err.message.should.equal('I am broken'); done(); }) .end();
- should not emit error on chunked json
- request.get(`${base}/chunked-json`).end((err) => { assert.ifError(err); done(); });
- should not emit error on aborted chunked json
- const req = request.get(`${base}/chunked-json`); req.end((err) => { assert.ifError(err); done(); }); setTimeout(() => { req.abort(); }, 50);
pipe on redirect
- should follow Location
- const stream = fs.createWriteStream(destPath); const redirects = []; const req = request .get(base) .on('redirect', (res) => { redirects.push(res.headers.location); }) .connect({ inapplicable: 'should be ignored' }); stream.on('finish', () => { redirects.should.eql(['/movies', '/movies/all', '/movies/all/0']); fs.readFileSync(destPath, 'utf8').should.eql('first movie page'); done(); }); req.pipe(stream);
request pipe
- should act as a writable stream
- const req = request.post(base); const stream = fs.createReadStream('test/node/fixtures/user.json'); req.type('json'); req.on('response', (res) => { res.body.should.eql({ name: 'tobi' }); done(); }); stream.pipe(req);
- end() stops piping
- const stream = fs.createWriteStream(destPath); request.get(base).end((err, res) => { try { res.pipe(stream); return done(new Error('Did not prevent nonsense pipe')); } catch { /* expected error */ } done(); });
- should act as a readable stream
- const stream = fs.createWriteStream(destPath); let responseCalled = false; const req = request.get(base); req.type('json'); req.on('response', (res) => { res.status.should.eql(200); responseCalled = true; }); stream.on('finish', () => { JSON.parse(fs.readFileSync(destPath, 'utf8')).should.eql({ name: 'tobi' }); responseCalled.should.be.true(); done(); }); req.pipe(stream);
- should follow redirects
- const stream = fs.createWriteStream(destPath); let responseCalled = false; const req = request.get(base + '/redirect'); req.type('json'); req.on('response', (res) => { res.status.should.eql(200); responseCalled = true; }); stream.on('finish', () => { JSON.parse(fs.readFileSync(destPath, 'utf8')).should.eql({ name: 'tobi' }); responseCalled.should.be.true(); done(); }); req.pipe(stream);
- should not throw on bad redirects
- const stream = fs.createWriteStream(destPath); let responseCalled = false; let errorCalled = false; const req = request.get(base + '/badRedirectNoLocation'); req.type('json'); req.on('response', (res) => { responseCalled = true; }); req.on('error', (err) => { err.message.should.eql('No location header for redirect'); errorCalled = true; stream.end(); }); stream.on('finish', () => { responseCalled.should.be.false(); errorCalled.should.be.true(); done(); }); req.pipe(stream);
req.query(String)
- should support passing in a string
- request .del(base) .query('name=t%F6bi') .end((err, res) => { res.body.should.eql({ name: 't%F6bi' }); done(); });
- should work with url query-string and string for query
- request .del(`${base}/?name=tobi`) .query('age=2%20') .end((err, res) => { res.body.should.eql({ name: 'tobi', age: '2 ' }); done(); });
- should support compound elements in a string
- request .del(base) .query('name=t%F6bi&age=2') .end((err, res) => { res.body.should.eql({ name: 't%F6bi', age: '2' }); done(); });
- should work when called multiple times with a string
- request .del(base) .query('name=t%F6bi') .query('age=2%F6') .end((err, res) => { res.body.should.eql({ name: 't%F6bi', age: '2%F6' }); done(); });
- should work with normal `query` object and query string
- request .del(base) .query('name=t%F6bi') .query({ age: '2' }) .end((err, res) => { res.body.should.eql({ name: 't%F6bi', age: '2' }); done(); });
- should not encode raw backticks, but leave encoded ones as is
- return Promise.all([ request .get(`${base}/raw-query`) .query('name=`t%60bi`&age`=2') .then((res) => { res.text.should.eql('name=`t%60bi`&age`=2'); }), request.get(base + '/raw-query?`age%60`=2%60`').then((res) => { res.text.should.eql('`age%60`=2%60`'); }), request .get(`${base}/raw-query`) .query('name=`t%60bi`') .query('age`=2') .then((res) => { res.text.should.eql('name=`t%60bi`&age`=2'); }) ]);
req.query(Object)
- should construct the query-string
- request .del(base) .query({ name: 'tobi' }) .query({ order: 'asc' }) .query({ limit: ['1', '2'] }) .end((err, res) => { res.body.should.eql({ name: 'tobi', order: 'asc', limit: ['1', '2'] }); done(); });
- should encode raw backticks
- request .get(`${base}/raw-query`) .query({ name: '`tobi`' }) .query({ 'orde%60r': null }) .query({ '`limit`': ['%602`'] }) .end((err, res) => { res.text.should.eql('name=%60tobi%60&orde%2560r&%60limit%60=%25602%60'); done(); });
- should not error on dates
- const date = new Date(0); request .del(base) .query({ at: date }) .end((err, res) => { assert.equal(date.toISOString(), res.body.at); done(); });
- should work after setting header fields
- request .del(base) .set('Foo', 'bar') .set('Bar', 'baz') .query({ name: 'tobi' }) .query({ order: 'asc' }) .query({ limit: ['1', '2'] }) .end((err, res) => { res.body.should.eql({ name: 'tobi', order: 'asc', limit: ['1', '2'] }); done(); });
- should append to the original query-string
- request .del(`${base}/?name=tobi`) .query({ order: 'asc' }) .end((err, res) => { res.body.should.eql({ name: 'tobi', order: 'asc' }); done(); });
- should retain the original query-string
- request.del(`${base}/?name=tobi`).end((err, res) => { res.body.should.eql({ name: 'tobi' }); done(); });
- should keep only keys with null querystring values
- request .del(`${base}/url`) .query({ nil: null }) .end((err, res) => { res.text.should.equal('/url?nil'); done(); });
- query-string should be sent on pipe
- const req = request.put(`${base}/?name=tobi`); const stream = fs.createReadStream('test/node/fixtures/user.json'); req.on('response', (res) => { res.body.should.eql({ name: 'tobi' }); done(); }); stream.pipe(req);
request.get
- should follow Location with a GET request
- const req = request.get(`${base}/test-301`).redirects(1); req.end((err, res) => { const headers = req.req.getHeaders ? req.req.getHeaders() : req.req._headers; headers.host.should.eql(`localhost:${server2.address().port}`); res.status.should.eql(200); res.text.should.eql('GET'); done(); });
- should follow Location with a GET request
- const req = request.get(`${base}/test-302`).redirects(1); req.end((err, res) => { const headers = req.req.getHeaders ? req.req.getHeaders() : req.req._headers; res.status.should.eql(200); res.text.should.eql('GET'); done(); });
- should follow Location with a GET request
- const req = request.get(`${base}/test-303`).redirects(1); req.end((err, res) => { const headers = req.req.getHeaders ? req.req.getHeaders() : req.req._headers; headers.host.should.eql(`localhost:${server2.address().port}`); res.status.should.eql(200); res.text.should.eql('GET'); done(); });
- should follow Location with a GET request
- const req = request.get(`${base}/test-307`).redirects(1); req.end((err, res) => { const headers = req.req.getHeaders ? req.req.getHeaders() : req.req._headers; headers.host.should.eql(`localhost:${server2.address().port}`); res.status.should.eql(200); res.text.should.eql('GET'); done(); });
- should follow Location with a GET request
- const req = request.get(`${base}/test-308`).redirects(1); req.end((err, res) => { const headers = req.req.getHeaders ? req.req.getHeaders() : req.req._headers; headers.host.should.eql(`localhost:${server2.address().port}`); res.status.should.eql(200); res.text.should.eql('GET'); done(); });
on 301 redirect
on 302 redirect
on 303 redirect
on 307 redirect
on 308 redirect
request.post
- should follow Location with a GET request
- const req = request.post(`${base}/test-301`).redirects(1); req.end((err, res) => { const headers = req.req.getHeaders ? req.req.getHeaders() : req.req._headers; headers.host.should.eql(`localhost:${server2.address().port}`); res.status.should.eql(200); res.text.should.eql('GET'); done(); });
- should follow Location with a GET request
- const req = request.post(`${base}/test-302`).redirects(1); req.end((err, res) => { const headers = req.req.getHeaders ? req.req.getHeaders() : req.req._headers; headers.host.should.eql(`localhost:${server2.address().port}`); res.status.should.eql(200); res.text.should.eql('GET'); done(); });
- should follow Location with a GET request
- const req = request.post(`${base}/test-303`).redirects(1); req.end((err, res) => { const headers = req.req.getHeaders ? req.req.getHeaders() : req.req._headers; headers.host.should.eql(`localhost:${server2.address().port}`); res.status.should.eql(200); res.text.should.eql('GET'); done(); });
- should follow Location with a POST request
- const req = request.post(`${base}/test-307`).redirects(1); req.end((err, res) => { const headers = req.req.getHeaders ? req.req.getHeaders() : req.req._headers; headers.host.should.eql(`localhost:${server2.address().port}`); res.status.should.eql(200); res.text.should.eql('POST'); done(); });
- should follow Location with a POST request
- const req = request.post(`${base}/test-308`).redirects(1); req.end((err, res) => { const headers = req.req.getHeaders ? req.req.getHeaders() : req.req._headers; headers.host.should.eql(`localhost:${server2.address().port}`); res.status.should.eql(200); res.text.should.eql('POST'); done(); });
on 301 redirect
on 302 redirect
on 303 redirect
on 307 redirect
on 308 redirect
request
- should merge cookies if agent is used
- request .agent() .get(`${base}/cookie-redirect`) .set('Cookie', 'orig=1; replaced=not') .end((err, res) => { try { assert.ifError(err); assert(/orig=1/.test(res.text), 'orig=1/.test'); assert(/replaced=yes/.test(res.text), 'replaced=yes/.test'); assert(/from-redir=1/.test(res.text), 'from-redir=1'); done(); } catch (err_) { done(err_); } });
- should not merge cookies if agent is not used
- request .get(`${base}/cookie-redirect`) .set('Cookie', 'orig=1; replaced=not') .end((err, res) => { try { assert.ifError(err); assert(/orig=1/.test(res.text), '/orig=1'); assert(/replaced=not/.test(res.text), '/replaced=not'); assert(!/replaced=yes/.test(res.text), '!/replaced=yes'); assert(!/from-redir/.test(res.text), '!/from-redir'); done(); } catch (err_) { done(err_); } });
- should have previously set cookie for subsquent requests when agent is used
- const agent = request.agent(); agent.get(`${base}/set-cookie`).end((err) => { assert.ifError(err); agent .get(`${base}/show-cookies`) .set({ Cookie: 'orig=1' }) .end((err, res) => { try { assert.ifError(err); assert(/orig=1/.test(res.text), 'orig=1/.test'); assert(/persist=123/.test(res.text), 'persist=123'); done(); } catch (err_) { done(err_); } }); });
- should follow Location
- const redirects = []; request .get(base) .on('redirect', (res) => { redirects.push(res.headers.location); }) .end((err, res) => { try { const arr = ['/movies', '/movies/all', '/movies/all/0']; redirects.should.eql(arr); res.text.should.equal('first movie page'); done(); } catch (err_) { done(err_); } });
- should follow Location with IP override
- const redirects = []; const url = URL.parse(base); return request .get(`http://redir.example.com:${url.port || '80'}${url.pathname}`) .connect({ '*': url.hostname }) .on('redirect', (res) => { redirects.push(res.headers.location); }) .then((res) => { const arr = ['/movies', '/movies/all', '/movies/all/0']; redirects.should.eql(arr); res.text.should.equal('first movie page'); });
- should follow Location with IP:port override
- const redirects = []; const url = URL.parse(base); return request .get(`http://redir.example.com:9999${url.pathname}`) .connect({ '*': { host: url.hostname, port: url.port || 80 } }) .on('redirect', (res) => { redirects.push(res.headers.location); }) .then((res) => { const arr = ['/movies', '/movies/all', '/movies/all/0']; redirects.should.eql(arr); res.text.should.equal('first movie page'); });
- should not follow on HEAD by default
- const redirects = []; return request .head(base) .ok(() => true) .on('redirect', (res) => { redirects.push(res.headers.location); }) .then((res) => { redirects.should.eql([]); res.status.should.equal(302); });
- should follow on HEAD when redirects are set
- const redirects = []; request .head(base) .redirects(10) .on('redirect', (res) => { redirects.push(res.headers.location); }) .end((err, res) => { try { const arr = []; arr.push('/movies'); arr.push('/movies/all'); arr.push('/movies/all/0'); redirects.should.eql(arr); assert(!res.text); done(); } catch (err_) { done(err_); } });
- should remove Content-* fields
- request .post(`${base}/header`) .type('txt') .set('X-Foo', 'bar') .set('X-Bar', 'baz') .send('hey') .end((err, res) => { try { assert(res.body); res.body.should.have.property('x-foo', 'bar'); res.body.should.have.property('x-bar', 'baz'); res.body.should.not.have.property('content-type'); res.body.should.not.have.property('content-length'); res.body.should.not.have.property('transfer-encoding'); done(); } catch (err_) { done(err_); } });
- should retain cookies
- request .get(`${base}/header`) .set('Cookie', 'foo=bar;') .end((err, res) => { try { assert(res.body); res.body.should.have.property('cookie', 'foo=bar;'); done(); } catch (err_) { done(err_); } });
- should not resend query parameters
- const redirects = []; const query = []; request .get(`${base}/?foo=bar`) .on('redirect', (res) => { query.push(res.headers.query); redirects.push(res.headers.location); }) .end((err, res) => { try { const arr = []; arr.push('/movies'); arr.push('/movies/all'); arr.push('/movies/all/0'); redirects.should.eql(arr); res.text.should.equal('first movie page'); query.should.eql(['{"foo":"bar"}', '{}', '{}']); res.headers.query.should.eql('{}'); done(); } catch (err_) { done(err_); } });
- should handle no location header
- request.get(`${base}/bad-redirect`).end((err, res) => { try { err.message.should.equal('No location header for redirect'); done(); } catch (err_) { done(err_); } });
- should redirect to a sibling path
- const redirects = []; request .get(`${base}/relative`) .on('redirect', (res) => { redirects.push(res.headers.location); }) .end((err, res) => { try { redirects.should.eql(['tobi']); res.text.should.equal('tobi'); done(); } catch (err_) { done(err_); } });
- should redirect to a parent path
- const redirects = []; request .get(`${base}/relative/sub`) .on('redirect', (res) => { redirects.push(res.headers.location); }) .end((err, res) => { try { redirects.should.eql(['../tobi']); res.text.should.equal('tobi'); done(); } catch (err_) { done(err_); } });
- should alter the default number of redirects to follow
- const redirects = []; request .get(base) .redirects(2) .on('redirect', (res) => { redirects.push(res.headers.location); }) .end((err, res) => { try { const arr = []; assert(res.redirect, 'res.redirect'); arr.push('/movies'); arr.push('/movies/all'); redirects.should.eql(arr); res.text.should.match(/Moved Temporarily|Found/); done(); } catch (err_) { done(err_); } });
- should redirect as GET
- const redirects = []; return request .post(`${base}/movie`) .send({ name: 'Tobi' }) .redirects(2) .on('redirect', (res) => { redirects.push(res.headers.location); }) .then((res) => { redirects.should.eql(['/movies/all/0']); res.text.should.equal('first movie page'); });
- using multipart/form-data should redirect as GET
- const redirects = []; request .post(`${base}/movie`) .type('form') .field('name', 'Tobi') .redirects(2) .on('redirect', (res) => { redirects.push(res.headers.location); }) .then((res) => { redirects.should.eql(['/movies/all/0']); res.text.should.equal('first movie page'); });
on redirect
when relative
req.redirects(n)
on POST
response
- should act as a readable stream
- const req = request.get(base).buffer(false); req.end((err, res) => { if (err) return done(err); let trackEndEvent = 0; let trackCloseEvent = 0; res.on('end', () => { trackEndEvent++; trackEndEvent.should.equal(1); if (!process.env.HTTP2_TEST) { trackCloseEvent.should.equal(0); // close should not have been called } done(); }); res.on('close', () => { trackCloseEvent++; }); (() => { res.pause(); }).should.not.throw(); (() => { res.resume(); }).should.not.throw(); (() => { res.destroy(); }).should.not.throw(); });
req.serialize(fn)
- should take precedence over default parsers
- request .post(`${base}/echo`) .send({ foo: 123 }) .serialize((data) => '{"bar":456}') .end((err, res) => { assert.ifError(err); assert.equal('{"bar":456}', res.text); assert.equal(456, res.body.bar); done(); });
request.get().set()
- should set host header after get()
- app.get('/', (req, res) => { assert.equal(req.hostname, 'example.com'); res.end(); }); server = http.createServer(app); server.listen(0, function listening() { request .get(`http://localhost:${server.address().port}`) .set('host', 'example.com') .then(() => { return request .get(`http://example.com:${server.address().port}`) .connect({ 'example.com': 'localhost', '*': 'fail' }); }) .then(() => done(), done); });
res.toError()
- should return an Error
- request.get(base).end((err, res) => { var err = res.toError(); assert.equal(err.status, 400); assert.equal(err.method, 'GET'); assert.equal(err.path, '/'); assert.equal(err.message, 'cannot GET / (400)'); assert.equal(err.text, 'invalid json'); done(); });
[unix-sockets] http
- path: / (root)
- request.get(`${base}/`).end((err, res) => { assert(res.ok); assert.strictEqual('root ok!', res.text); done(); });
- path: /request/path
- request.get(`${base}/request/path`).end((err, res) => { assert(res.ok); assert.strictEqual('request path ok!', res.text); done(); });
request
[unix-sockets] https
- path: / (root)
- request .get(`${base}/`) .ca(cacert) .end((err, res) => { assert.ifError(err); assert(res.ok); assert.strictEqual('root ok!', res.text); done(); });
- path: /request/path
- request .get(`${base}/request/path`) .ca(cacert) .end((err, res) => { assert.ifError(err); assert(res.ok); assert.strictEqual('request path ok!', res.text); done(); });
request
req.get()
- should not set a default user-agent
- request.get(`${base}/ua`).then((res) => { assert(res.headers); assert(!res.headers['user-agent']); })
utils.type(str)
- should return the mime type
- utils .type('application/json; charset=utf-8') .should.equal('application/json'); utils.type('application/json').should.equal('application/json');
utils.params(str)
- should return the field parameters
- const obj = utils.params('application/json; charset=utf-8; foo = bar'); obj.charset.should.equal('utf-8'); obj.foo.should.equal('bar'); utils.params('application/json').should.eql({});
utils.parseLinks(str)
- should parse links
- const str = '<https://api.github.com/repos/visionmedia/mocha/issues?page=2>; rel="next", <https://api.github.com/repos/visionmedia/mocha/issues?page=5>; rel="last"'; const ret = utils.parseLinks(str); ret.next.should.equal( 'https://api.github.com/repos/visionmedia/mocha/issues?page=2' ); ret.last.should.equal( 'https://api.github.com/repos/visionmedia/mocha/issues?page=5' );
