Skip to content

Commit b1c2d9d

Browse files
committed
Merge pull request #576 from flovilmart/httpRequest-tests
improves coverage and API of httpRequest
2 parents 1f707a9 + b6223f5 commit b1c2d9d

File tree

2 files changed

+212
-10
lines changed

2 files changed

+212
-10
lines changed

spec/HTTPRequest.spec.js

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
var httpRequest = require("../src/httpRequest"),
2+
bodyParser = require('body-parser'),
3+
express = require("express");
4+
5+
var port = 13371;
6+
var httpRequestServer = "http://localhost:"+port;
7+
8+
var app = express();
9+
app.use(bodyParser.json({ 'type': '*/*' }));
10+
app.get("/hello", function(req, res){
11+
res.json({response: "OK"});
12+
});
13+
14+
app.get("/404", function(req, res){
15+
res.status(404);
16+
res.send("NO");
17+
});
18+
19+
app.get("/301", function(req, res){
20+
res.status(301);
21+
res.location("/hello");
22+
res.send();
23+
});
24+
25+
app.post('/echo', function(req, res){
26+
res.json(req.body);
27+
})
28+
29+
app.listen(13371);
30+
31+
32+
describe("httpRequest", () => {
33+
34+
it("should do /hello", (done) => {
35+
httpRequest({
36+
url: httpRequestServer+"/hello"
37+
}).then(function(httpResponse){
38+
expect(httpResponse.status).toBe(200);
39+
expect(httpResponse.buffer).toEqual(new Buffer('{"response":"OK"}'));
40+
expect(httpResponse.text).toEqual('{"response":"OK"}');
41+
expect(httpResponse.data.response).toEqual("OK");
42+
done();
43+
}, function(){
44+
fail("should not fail");
45+
done();
46+
})
47+
});
48+
49+
it("should do /hello with callback and promises", (done) => {
50+
var calls = 0;
51+
httpRequest({
52+
url: httpRequestServer+"/hello",
53+
success: function() { calls++; },
54+
error: function() { calls++; }
55+
}).then(function(httpResponse){
56+
expect(calls).toBe(1);
57+
expect(httpResponse.status).toBe(200);
58+
expect(httpResponse.buffer).toEqual(new Buffer('{"response":"OK"}'));
59+
expect(httpResponse.text).toEqual('{"response":"OK"}');
60+
expect(httpResponse.data.response).toEqual("OK");
61+
done();
62+
}, function(){
63+
fail("should not fail");
64+
done();
65+
})
66+
});
67+
68+
it("should do not follow redirects by default", (done) => {
69+
70+
httpRequest({
71+
url: httpRequestServer+"/301"
72+
}).then(function(httpResponse){
73+
expect(httpResponse.status).toBe(301);
74+
done();
75+
}, function(){
76+
fail("should not fail");
77+
done();
78+
})
79+
});
80+
81+
it("should follow redirects when set", (done) => {
82+
83+
httpRequest({
84+
url: httpRequestServer+"/301",
85+
followRedirects: true
86+
}).then(function(httpResponse){
87+
expect(httpResponse.status).toBe(200);
88+
expect(httpResponse.buffer).toEqual(new Buffer('{"response":"OK"}'));
89+
expect(httpResponse.text).toEqual('{"response":"OK"}');
90+
expect(httpResponse.data.response).toEqual("OK");
91+
done();
92+
}, function(){
93+
fail("should not fail");
94+
done();
95+
})
96+
});
97+
98+
it("should fail on 404", (done) => {
99+
var calls = 0;
100+
httpRequest({
101+
url: httpRequestServer+"/404",
102+
success: function() {
103+
calls++;
104+
fail("should not succeed");
105+
done();
106+
},
107+
error: function(httpResponse) {
108+
calls++;
109+
expect(calls).toBe(1);
110+
expect(httpResponse.status).toBe(404);
111+
expect(httpResponse.buffer).toEqual(new Buffer('NO'));
112+
expect(httpResponse.text).toEqual('NO');
113+
expect(httpResponse.data).toBe(undefined);
114+
done();
115+
}
116+
});
117+
})
118+
119+
it("should fail on 404", (done) => {
120+
httpRequest({
121+
url: httpRequestServer+"/404",
122+
}).then(function(httpResponse){
123+
fail("should not succeed");
124+
done();
125+
}, function(httpResponse){
126+
expect(httpResponse.status).toBe(404);
127+
expect(httpResponse.buffer).toEqual(new Buffer('NO'));
128+
expect(httpResponse.text).toEqual('NO');
129+
expect(httpResponse.data).toBe(undefined);
130+
done();
131+
})
132+
})
133+
134+
it("should post on echo", (done) => {
135+
var calls = 0;
136+
httpRequest({
137+
method: "POST",
138+
url: httpRequestServer+"/echo",
139+
body: {
140+
foo: "bar"
141+
},
142+
headers: {
143+
'Content-Type': 'application/json'
144+
},
145+
success: function() { calls++; },
146+
error: function() { calls++; }
147+
}).then(function(httpResponse){
148+
expect(calls).toBe(1);
149+
expect(httpResponse.status).toBe(200);
150+
expect(httpResponse.data).toEqual({foo: "bar"});
151+
done();
152+
}, function(httpResponse){
153+
fail("should not fail");
154+
done();
155+
})
156+
});
157+
it("should encode a JSON body", (done) => {
158+
159+
var result = httpRequest.encodeBody({"foo": "bar"}, {'Content-Type': 'application/json'});
160+
expect(result).toEqual('{"foo":"bar"}');
161+
done();
162+
163+
})
164+
it("should encode a www-form body", (done) => {
165+
166+
var result = httpRequest.encodeBody({"foo": "bar", "bar": "baz"}, {'cOntent-tYpe': 'application/x-www-form-urlencoded'});
167+
expect(result).toEqual("foo=bar&bar=baz");
168+
done();
169+
});
170+
it("should not encode a wrong content type", (done) => {
171+
172+
var result = httpRequest.encodeBody({"foo": "bar", "bar": "baz"}, {'cOntent-tYpe': 'mime/jpeg'});
173+
expect(result).toEqual({"foo": "bar", "bar": "baz"});
174+
done();
175+
});
176+
it("should not encode when missing content type", (done) => {
177+
var result = httpRequest.encodeBody({"foo": "bar", "bar": "baz"}, {'X-Custom-Header': 'my-header'});
178+
expect(result).toEqual({"foo": "bar", "bar": "baz"});
179+
done();
180+
})
181+
});

src/httpRequest.js

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,27 @@
11
var request = require("request"),
22
Parse = require('parse/node').Parse;
33

4+
var encodeBody = function(body, headers = {}) {
5+
if (typeof body !== 'object') {
6+
return body;
7+
}
8+
var contentTypeKeys = Object.keys(headers).filter((key) => {
9+
return key.match(/content-type/i) != null;
10+
});
11+
12+
if (contentTypeKeys.length == 1) {
13+
var contentType = contentTypeKeys[0];
14+
if (headers[contentType].match(/application\/json/i)) {
15+
body = JSON.stringify(body);
16+
} else if(headers[contentType].match(/application\/x-www-form-urlencoded/i)) {
17+
body = Object.keys(body).map(function(key){
18+
return `${key}=${encodeURIComponent(body[key])}`
19+
}).join("&");
20+
}
21+
}
22+
return body;
23+
}
24+
425
module.exports = function(options) {
526
var promise = new Parse.Promise();
627
var callbacks = {
@@ -9,13 +30,11 @@ module.exports = function(options) {
930
};
1031
delete options.success;
1132
delete options.error;
12-
if (options.uri && !options.url) {
13-
options.uri = options.url;
14-
delete options.url;
15-
}
16-
if (typeof options.body === 'object') {
17-
options.body = JSON.stringify(options.body);
18-
}
33+
delete options.uri; // not supported
34+
options.body = encodeBody(options.body, options.headers);
35+
// set follow redirects to false by default
36+
options.followRedirect = options.followRedirects == true;
37+
1938
request(options, (error, response, body) => {
2039
var httpResponse = {};
2140
httpResponse.status = response.statusCode;
@@ -29,15 +48,17 @@ module.exports = function(options) {
2948
// Consider <200 && >= 400 as errors
3049
if (error || httpResponse.status <200 || httpResponse.status >=400) {
3150
if (callbacks.error) {
32-
return callbacks.error(httpResponse);
51+
callbacks.error(httpResponse);
3352
}
3453
return promise.reject(httpResponse);
3554
} else {
3655
if (callbacks.success) {
37-
return callbacks.success(httpResponse);
56+
callbacks.success(httpResponse);
3857
}
3958
return promise.resolve(httpResponse);
4059
}
4160
});
4261
return promise;
43-
};
62+
};
63+
64+
module.exports.encodeBody = encodeBody;

0 commit comments

Comments
 (0)