http: parse the status message in a http response.
This commit is contained in:
parent
a35a2f0192
commit
7ffe2ad616
@ -1011,6 +1011,12 @@ you can use the `require('querystring').parse` function, or pass
|
||||
|
||||
The 3-digit HTTP response status code. E.G. `404`.
|
||||
|
||||
### message.statusMessage
|
||||
|
||||
**Only valid for response obtained from `http.ClientRequest`.**
|
||||
|
||||
The HTTP response status message (reason phrase). E.G. `OK` or `Internal Server Error`.
|
||||
|
||||
### message.socket
|
||||
|
||||
The `net.Socket` object associated with the connection.
|
||||
|
@ -97,7 +97,7 @@ function parserOnHeadersComplete(info) {
|
||||
} else {
|
||||
// client only
|
||||
parser.incoming.statusCode = info.statusCode;
|
||||
// CHECKME dead code? we're always a request parser
|
||||
parser.incoming.statusMessage = info.statusMessage;
|
||||
}
|
||||
|
||||
parser.incoming.upgrade = info.upgrade;
|
||||
|
@ -64,6 +64,7 @@ function IncomingMessage(socket) {
|
||||
|
||||
// response (client) only
|
||||
this.statusCode = null;
|
||||
this.statusMessage = null;
|
||||
this.client = this.socket;
|
||||
|
||||
// flag for backwards compatibility grossness.
|
||||
|
@ -119,6 +119,7 @@ namespace node {
|
||||
V(smalloc_p_string, "_smalloc_p") \
|
||||
V(sni_context_string, "sni_context") \
|
||||
V(status_code_string, "statusCode") \
|
||||
V(status_message_string, "statusMessage") \
|
||||
V(subject_string, "subject") \
|
||||
V(subjectaltname_string, "subjectaltname") \
|
||||
V(syscall_string, "syscall") \
|
||||
|
@ -181,6 +181,7 @@ class Parser : public BaseObject {
|
||||
HTTP_CB(on_message_begin) {
|
||||
num_fields_ = num_values_ = 0;
|
||||
url_.Reset();
|
||||
status_message_.Reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -191,6 +192,12 @@ class Parser : public BaseObject {
|
||||
}
|
||||
|
||||
|
||||
HTTP_DATA_CB(on_status) {
|
||||
status_message_.Update(at, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
HTTP_DATA_CB(on_header_field) {
|
||||
if (num_fields_ == num_values_) {
|
||||
// start of new field name
|
||||
@ -259,6 +266,8 @@ class Parser : public BaseObject {
|
||||
if (parser_.type == HTTP_RESPONSE) {
|
||||
message_info->Set(env()->status_code_string(),
|
||||
Integer::New(parser_.status_code, node_isolate));
|
||||
message_info->Set(env()->status_message_string(),
|
||||
status_message_.ToString());
|
||||
}
|
||||
|
||||
// VERSION
|
||||
@ -349,6 +358,7 @@ class Parser : public BaseObject {
|
||||
|
||||
void Save() {
|
||||
url_.Save();
|
||||
status_message_.Save();
|
||||
|
||||
for (int i = 0; i < num_fields_; i++) {
|
||||
fields_[i].Save();
|
||||
@ -515,6 +525,7 @@ class Parser : public BaseObject {
|
||||
void Init(enum http_parser_type type) {
|
||||
http_parser_init(&parser_, type);
|
||||
url_.Reset();
|
||||
status_message_.Reset();
|
||||
num_fields_ = 0;
|
||||
num_values_ = 0;
|
||||
have_flushed_ = false;
|
||||
@ -526,6 +537,7 @@ class Parser : public BaseObject {
|
||||
StringPtr fields_[32]; // header fields
|
||||
StringPtr values_[32]; // header values
|
||||
StringPtr url_;
|
||||
StringPtr status_message_;
|
||||
int num_fields_;
|
||||
int num_values_;
|
||||
bool have_flushed_;
|
||||
@ -540,6 +552,7 @@ class Parser : public BaseObject {
|
||||
const struct http_parser_settings Parser::settings = {
|
||||
Parser::on_message_begin,
|
||||
Parser::on_url,
|
||||
Parser::on_status,
|
||||
Parser::on_header_field,
|
||||
Parser::on_header_value,
|
||||
Parser::on_headers_complete,
|
||||
|
@ -143,6 +143,7 @@ function expectBody(expected) {
|
||||
assert.equal(info.versionMajor, 1);
|
||||
assert.equal(info.versionMinor, 1);
|
||||
assert.equal(info.statusCode, 200);
|
||||
assert.equal(info.statusMessage, "OK");
|
||||
});
|
||||
|
||||
parser[kOnBody] = mustCall(function(buf, start, len) {
|
||||
@ -169,6 +170,7 @@ function expectBody(expected) {
|
||||
assert.equal(info.versionMajor, 1);
|
||||
assert.equal(info.versionMinor, 0);
|
||||
assert.equal(info.statusCode, 200);
|
||||
assert.equal(info.statusMessage, "Connection established");
|
||||
assert.deepEqual(info.headers || parser.headers, []);
|
||||
});
|
||||
|
||||
|
78
test/simple/test-http-response-status-message.js
Normal file
78
test/simple/test-http-response-status-message.js
Normal file
@ -0,0 +1,78 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var http = require('http');
|
||||
var net = require('net');
|
||||
|
||||
var testsComplete = 0;
|
||||
|
||||
var testCases = [
|
||||
{ path: "/200", statusMessage: "OK", response: 'HTTP/1.1 200 OK\r\n\r\n' },
|
||||
{ path: "/500", statusMessage: "Internal Server Error", response: 'HTTP/1.1 500 Internal Server Error\r\n\r\n' },
|
||||
{ path: "/302", statusMessage: "Moved Temporarily", response: 'HTTP/1.1 302 Moved Temporarily\r\n\r\n' },
|
||||
{ path: "/missing", statusMessage: "", response: 'HTTP/1.1 200 \r\n\r\n' },
|
||||
{ path: "/missing-no-space", statusMessage: "", response: 'HTTP/1.1 200\r\n\r\n' }
|
||||
];
|
||||
testCases.findByPath = function(path) {
|
||||
var matching = this.filter(function(testCase) { return testCase.path === path; });
|
||||
if (matching.length === 0) { throw "failed to find test case with path " + path; }
|
||||
return matching[0];
|
||||
};
|
||||
|
||||
var server = net.createServer(function(connection) {
|
||||
connection.on('data', function(data) {
|
||||
var path = data.toString().match(/GET (.*) HTTP.1.1/)[1];
|
||||
var testCase = testCases.findByPath(path);
|
||||
|
||||
connection.write(testCase.response);
|
||||
connection.end();
|
||||
});
|
||||
});
|
||||
|
||||
var runTest = function(testCaseIndex) {
|
||||
var testCase = testCases[testCaseIndex];
|
||||
|
||||
http.get({ port: common.PORT, path: testCase.path }, function(response) {
|
||||
console.log('client: expected status message: ' + testCase.statusMessage);
|
||||
console.log('client: actual status message: ' + response.statusMessage);
|
||||
assert.equal(testCase.statusMessage, response.statusMessage);
|
||||
|
||||
response.on('end', function() {
|
||||
testsComplete++;
|
||||
|
||||
if (testCaseIndex + 1 < testCases.length) {
|
||||
runTest(testCaseIndex + 1);
|
||||
} else {
|
||||
server.close();
|
||||
}
|
||||
});
|
||||
|
||||
response.resume();
|
||||
});
|
||||
};
|
||||
|
||||
server.listen(common.PORT, function() { runTest(0); });
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.equal(testCases.length, testsComplete);
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user