Skip to content
This repository was archived by the owner on Apr 22, 2023. It is now read-only.

Commit 7ffe2ad

Browse files
camswordsindutny
authored andcommitted
http: parse the status message in a http response.
1 parent a35a2f0 commit 7ffe2ad

File tree

7 files changed

+102
-1
lines changed

7 files changed

+102
-1
lines changed

doc/api/http.markdown

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,12 @@ you can use the `require('querystring').parse` function, or pass
10111011

10121012
The 3-digit HTTP response status code. E.G. `404`.
10131013

1014+
### message.statusMessage
1015+
1016+
**Only valid for response obtained from `http.ClientRequest`.**
1017+
1018+
The HTTP response status message (reason phrase). E.G. `OK` or `Internal Server Error`.
1019+
10141020
### message.socket
10151021

10161022
The `net.Socket` object associated with the connection.

lib/_http_common.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ function parserOnHeadersComplete(info) {
9797
} else {
9898
// client only
9999
parser.incoming.statusCode = info.statusCode;
100-
// CHECKME dead code? we're always a request parser
100+
parser.incoming.statusMessage = info.statusMessage;
101101
}
102102

103103
parser.incoming.upgrade = info.upgrade;

lib/_http_incoming.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ function IncomingMessage(socket) {
6464

6565
// response (client) only
6666
this.statusCode = null;
67+
this.statusMessage = null;
6768
this.client = this.socket;
6869

6970
// flag for backwards compatibility grossness.

src/env.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ namespace node {
119119
V(smalloc_p_string, "_smalloc_p") \
120120
V(sni_context_string, "sni_context") \
121121
V(status_code_string, "statusCode") \
122+
V(status_message_string, "statusMessage") \
122123
V(subject_string, "subject") \
123124
V(subjectaltname_string, "subjectaltname") \
124125
V(syscall_string, "syscall") \

src/node_http_parser.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ class Parser : public BaseObject {
181181
HTTP_CB(on_message_begin) {
182182
num_fields_ = num_values_ = 0;
183183
url_.Reset();
184+
status_message_.Reset();
184185
return 0;
185186
}
186187

@@ -191,6 +192,12 @@ class Parser : public BaseObject {
191192
}
192193

193194

195+
HTTP_DATA_CB(on_status) {
196+
status_message_.Update(at, length);
197+
return 0;
198+
}
199+
200+
194201
HTTP_DATA_CB(on_header_field) {
195202
if (num_fields_ == num_values_) {
196203
// start of new field name
@@ -259,6 +266,8 @@ class Parser : public BaseObject {
259266
if (parser_.type == HTTP_RESPONSE) {
260267
message_info->Set(env()->status_code_string(),
261268
Integer::New(parser_.status_code, node_isolate));
269+
message_info->Set(env()->status_message_string(),
270+
status_message_.ToString());
262271
}
263272

264273
// VERSION
@@ -349,6 +358,7 @@ class Parser : public BaseObject {
349358

350359
void Save() {
351360
url_.Save();
361+
status_message_.Save();
352362

353363
for (int i = 0; i < num_fields_; i++) {
354364
fields_[i].Save();
@@ -515,6 +525,7 @@ class Parser : public BaseObject {
515525
void Init(enum http_parser_type type) {
516526
http_parser_init(&parser_, type);
517527
url_.Reset();
528+
status_message_.Reset();
518529
num_fields_ = 0;
519530
num_values_ = 0;
520531
have_flushed_ = false;
@@ -526,6 +537,7 @@ class Parser : public BaseObject {
526537
StringPtr fields_[32]; // header fields
527538
StringPtr values_[32]; // header values
528539
StringPtr url_;
540+
StringPtr status_message_;
529541
int num_fields_;
530542
int num_values_;
531543
bool have_flushed_;
@@ -540,6 +552,7 @@ class Parser : public BaseObject {
540552
const struct http_parser_settings Parser::settings = {
541553
Parser::on_message_begin,
542554
Parser::on_url,
555+
Parser::on_status,
543556
Parser::on_header_field,
544557
Parser::on_header_value,
545558
Parser::on_headers_complete,

test/simple/test-http-parser.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ function expectBody(expected) {
143143
assert.equal(info.versionMajor, 1);
144144
assert.equal(info.versionMinor, 1);
145145
assert.equal(info.statusCode, 200);
146+
assert.equal(info.statusMessage, "OK");
146147
});
147148

148149
parser[kOnBody] = mustCall(function(buf, start, len) {
@@ -169,6 +170,7 @@ function expectBody(expected) {
169170
assert.equal(info.versionMajor, 1);
170171
assert.equal(info.versionMinor, 0);
171172
assert.equal(info.statusCode, 200);
173+
assert.equal(info.statusMessage, "Connection established");
172174
assert.deepEqual(info.headers || parser.headers, []);
173175
});
174176

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright Joyent, Inc. and other Node contributors.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a
4+
// copy of this software and associated documentation files (the
5+
// "Software"), to deal in the Software without restriction, including
6+
// without limitation the rights to use, copy, modify, merge, publish,
7+
// distribute, sublicense, and/or sell copies of the Software, and to permit
8+
// persons to whom the Software is furnished to do so, subject to the
9+
// following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included
12+
// in all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17+
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18+
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20+
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
22+
var common = require('../common');
23+
var assert = require('assert');
24+
var http = require('http');
25+
var net = require('net');
26+
27+
var testsComplete = 0;
28+
29+
var testCases = [
30+
{ path: "/200", statusMessage: "OK", response: 'HTTP/1.1 200 OK\r\n\r\n' },
31+
{ path: "/500", statusMessage: "Internal Server Error", response: 'HTTP/1.1 500 Internal Server Error\r\n\r\n' },
32+
{ path: "/302", statusMessage: "Moved Temporarily", response: 'HTTP/1.1 302 Moved Temporarily\r\n\r\n' },
33+
{ path: "/missing", statusMessage: "", response: 'HTTP/1.1 200 \r\n\r\n' },
34+
{ path: "/missing-no-space", statusMessage: "", response: 'HTTP/1.1 200\r\n\r\n' }
35+
];
36+
testCases.findByPath = function(path) {
37+
var matching = this.filter(function(testCase) { return testCase.path === path; });
38+
if (matching.length === 0) { throw "failed to find test case with path " + path; }
39+
return matching[0];
40+
};
41+
42+
var server = net.createServer(function(connection) {
43+
connection.on('data', function(data) {
44+
var path = data.toString().match(/GET (.*) HTTP.1.1/)[1];
45+
var testCase = testCases.findByPath(path);
46+
47+
connection.write(testCase.response);
48+
connection.end();
49+
});
50+
});
51+
52+
var runTest = function(testCaseIndex) {
53+
var testCase = testCases[testCaseIndex];
54+
55+
http.get({ port: common.PORT, path: testCase.path }, function(response) {
56+
console.log('client: expected status message: ' + testCase.statusMessage);
57+
console.log('client: actual status message: ' + response.statusMessage);
58+
assert.equal(testCase.statusMessage, response.statusMessage);
59+
60+
response.on('end', function() {
61+
testsComplete++;
62+
63+
if (testCaseIndex + 1 < testCases.length) {
64+
runTest(testCaseIndex + 1);
65+
} else {
66+
server.close();
67+
}
68+
});
69+
70+
response.resume();
71+
});
72+
};
73+
74+
server.listen(common.PORT, function() { runTest(0); });
75+
76+
process.on('exit', function() {
77+
assert.equal(testCases.length, testsComplete);
78+
});

0 commit comments

Comments
 (0)