Skip to content

Commit 89d45c8

Browse files
committedAug 2, 2017
Fix the bunyan CLI to not duplicate the "HTTP/1.1 ..." status line when serializing a "res" field. (#444)
1 parent 10d1273 commit 89d45c8

File tree

5 files changed

+95
-12
lines changed

5 files changed

+95
-12
lines changed
 

‎CHANGES.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ Known issues:
77

88
## not yet released
99

10-
(nothing yet)
10+
- [issue #444] Fix the `bunyan` CLI to not duplicate the "HTTP/1.1 ..." status
11+
line when serializing a "res" field.
1112

1213

1314
## 1.8.11

‎bin/bunyan

+30-11
Original file line numberDiff line numberDiff line change
@@ -979,17 +979,21 @@ function emitRecord(rec, line, opts, stylize) {
979979

980980
function _res(res) {
981981
var s = '';
982-
if (res.statusCode !== undefined) {
983-
s += format('HTTP/1.1 %s %s\n', res.statusCode,
984-
http.STATUS_CODES[res.statusCode]);
985-
delete res.statusCode;
986-
}
987-
// Handle `res.header` or `res.headers` as either a string or
988-
// and object of header key/value pairs. Prefer `res.header` if set
989-
// (TODO: Why? I don't recall. Typical of restify serializer?
990-
// Typical JSON.stringify of a core node HttpResponse?)
982+
983+
/*
984+
* Handle `res.header` or `res.headers` as either a string or
985+
* an object of header key/value pairs. Prefer `res.header` if set,
986+
* because that's what Bunyan's own `res` serializer specifies,
987+
* because that's the value in Node.js's core HTTP server response
988+
* implementation that has all the implicit headers.
989+
*
990+
* Note: `res.header` (string) typically includes the 'HTTP/1.1 ...'
991+
* status line.
992+
*/
991993
var headerTypes = {string: true, object: true};
992994
var headers;
995+
var headersStr = '';
996+
var headersHaveStatusLine = false;
993997
if (res.header && headerTypes[typeof (res.header)]) {
994998
headers = res.header;
995999
delete res.header;
@@ -1000,11 +1004,26 @@ function emitRecord(rec, line, opts, stylize) {
10001004
if (headers === undefined) {
10011005
/* pass through */
10021006
} else if (typeof (headers) === 'string') {
1003-
s += headers.trimRight();
1007+
headersStr = headers.trimRight(); // Trim the CRLF.
1008+
if (headersStr.slice(0, 5) === 'HTTP/') {
1009+
headersHaveStatusLine = true;
1010+
}
10041011
} else {
1005-
s += Object.keys(headers).map(
1012+
headersStr += Object.keys(headers).map(
10061013
function (h) { return h + ': ' + headers[h]; }).join('\n');
10071014
}
1015+
1016+
/*
1017+
* Add a 'HTTP/1.1 ...' status line if the headers didn't already
1018+
* include it.
1019+
*/
1020+
if (!headersHaveStatusLine && res.statusCode !== undefined) {
1021+
s += format('HTTP/1.1 %s %s\n', res.statusCode,
1022+
http.STATUS_CODES[res.statusCode]);
1023+
}
1024+
delete res.statusCode;
1025+
s += headersStr;
1026+
10081027
if (res.body !== undefined) {
10091028
var body = (typeof (res.body) === 'object'
10101029
? JSON.stringify(res.body, null, 2) : res.body);

‎test/cli-res.test.js

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (c) 2017, Trent Mick.
3+
*
4+
* Test the bunyan CLI's handling of the "res" field.
5+
*/
6+
7+
var exec = require('child_process').exec;
8+
var fs = require('fs');
9+
var path = require('path');
10+
var _ = require('util').format;
11+
var vasync = require('vasync');
12+
13+
// node-tap API
14+
if (require.cache[__dirname + '/tap4nodeunit.js'])
15+
delete require.cache[__dirname + '/tap4nodeunit.js'];
16+
var tap4nodeunit = require('./tap4nodeunit.js');
17+
var after = tap4nodeunit.after;
18+
var before = tap4nodeunit.before;
19+
var test = tap4nodeunit.test;
20+
21+
22+
// ---- globals
23+
24+
var BUNYAN = path.resolve(__dirname, '../bin/bunyan');
25+
26+
27+
// ---- tests
28+
29+
test('res with "header" string (issue #444)', function (t) {
30+
var expect = [
31+
/* BEGIN JSSTYLED */
32+
'[2017-08-02T22:37:34.798Z] INFO: res-header/76488 on danger0.local: response sent',
33+
' HTTP/1.1 200 OK',
34+
' Foo: bar',
35+
' Date: Wed, 02 Aug 2017 22:37:34 GMT',
36+
' Connection: keep-alive',
37+
' Content-Length: 21'
38+
/* END JSSTYLED */
39+
].join('\n') + '\n';
40+
exec(_('%s %s/corpus/res-header.log', BUNYAN, __dirname),
41+
function (err, stdout, stderr) {
42+
t.ifError(err);
43+
t.equal(stdout, expect);
44+
t.end();
45+
});
46+
});
47+
48+
test('res without "header"', function (t) {
49+
var expect = [
50+
/* BEGIN JSSTYLED */
51+
'[2017-08-02T22:37:34.798Z] INFO: res-header/76488 on danger0.local: response sent',
52+
' HTTP/1.1 200 OK'
53+
/* END JSSTYLED */
54+
].join('\n') + '\n';
55+
exec(_('%s %s/corpus/res-without-header.log', BUNYAN, __dirname),
56+
function (err, stdout, stderr) {
57+
t.ifError(err);
58+
t.equal(stdout, expect);
59+
t.end();
60+
});
61+
});

‎test/corpus/res-header.log

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"name":"res-header","hostname":"danger0.local","pid":76488,"level":30,"res":{"statusCode":200,"header":"HTTP/1.1 200 OK\r\nFoo: bar\r\nDate: Wed, 02 Aug 2017 22:37:34 GMT\r\nConnection: keep-alive\r\nContent-Length: 21\r\n\r\n"},"msg":"response sent","time":"2017-08-02T22:37:34.798Z","v":0}

‎test/corpus/res-without-header.log

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"name":"res-header","hostname":"danger0.local","pid":76488,"level":30,"res":{"statusCode":200},"msg":"response sent","time":"2017-08-02T22:37:34.798Z","v":0}

0 commit comments

Comments
 (0)
Please sign in to comment.