Convert all files to ES2015 (#182)

Elements of this commit come from #140 by @gwicke.
This commit is contained in:
Timothy Gu 2016-10-10 11:50:04 -07:00 committed by GitHub
parent 993d4cdea1
commit 838071247d
8 changed files with 986 additions and 1004 deletions

View File

@ -6,7 +6,7 @@
"scripts": { "scripts": {
"build": "babel -d lib src", "build": "babel -d lib src",
"prepublish": "npm run build", "prepublish": "npm run build",
"test": "mocha --compilers js:babel-register test/test.js", "test": "mocha --compilers js:babel-polyfill --compilers js:babel-register test/test.js",
"report": "cross-env BABEL_ENV=test nyc --reporter lcov --reporter text mocha -R spec test/test.js", "report": "cross-env BABEL_ENV=test nyc --reporter lcov --reporter text mocha -R spec test/test.js",
"coverage": "cross-env BABEL_ENV=test nyc --reporter lcovonly mocha -R spec test/test.js && cat ./coverage/lcov.info | coveralls" "coverage": "cross-env BABEL_ENV=test nyc --reporter lcovonly mocha -R spec test/test.js && cat ./coverage/lcov.info | coveralls"
}, },
@ -29,6 +29,7 @@
"babel-cli": "^6.16.0", "babel-cli": "^6.16.0",
"babel-plugin-istanbul": "^2.0.1", "babel-plugin-istanbul": "^2.0.1",
"babel-plugin-transform-runtime": "^6.15.0", "babel-plugin-transform-runtime": "^6.15.0",
"babel-polyfill": "^6.16.0",
"babel-preset-es2015": "^6.16.0", "babel-preset-es2015": "^6.16.0",
"babel-register": "^6.16.3", "babel-register": "^6.16.3",
"bluebird": "^3.3.4", "bluebird": "^3.3.4",
@ -44,6 +45,7 @@
"resumer": "0.0.0" "resumer": "0.0.0"
}, },
"dependencies": { "dependencies": {
"babel-runtime": "^6.11.6",
"encoding": "^0.1.11", "encoding": "^0.1.11",
"is-stream": "^1.0.1" "is-stream": "^1.0.1"
}, },
@ -67,6 +69,7 @@
"src/*.js" "src/*.js"
], ],
"require": [ "require": [
"babel-polyfill",
"babel-register" "babel-register"
], ],
"sourceMap": false, "sourceMap": false,

View File

@ -5,12 +5,17 @@
* Body interface provides common methods for Request and Response * Body interface provides common methods for Request and Response
*/ */
var convert = require('encoding').convert; import {convert} from 'encoding';
var bodyStream = require('is-stream'); import bodyStream from 'is-stream';
var PassThrough = require('stream').PassThrough; import {PassThrough} from 'stream';
var FetchError = require('./fetch-error'); import FetchError from './fetch-error.js';
module.exports = Body; const DISTURBED = Symbol('disturbed');
const BYTES = Symbol('bytes');
const RAW = Symbol('raw');
const ABORT = Symbol('abort');
const CONVERT = Symbol('convert');
const DECODE = Symbol('decode');
/** /**
* Body class * Body class
@ -19,17 +24,22 @@ module.exports = Body;
* @param Object opts Response options * @param Object opts Response options
* @return Void * @return Void
*/ */
function Body(body, opts) { export default class Body {
constructor(body, {
opts = opts || {}; size = 0,
timeout = 0
} = {}) {
this.body = body; this.body = body;
this.bodyUsed = false; this[DISTURBED] = false;
this.size = opts.size || 0; this.size = size;
this.timeout = opts.timeout || 0; this[BYTES] = 0;
this._raw = []; this.timeout = timeout;
this._abort = false; this[RAW] = [];
this[ABORT] = false;
}
get bodyUsed() {
return this[DISTURBED];
} }
/** /**
@ -37,118 +47,104 @@ function Body(body, opts) {
* *
* @return Promise * @return Promise
*/ */
Body.prototype.json = function() { json() {
// for 204 No Content response, buffer will be empty, parsing it will throw error // for 204 No Content response, buffer will be empty, parsing it will throw error
if (this.status === 204) { if (this.status === 204) {
return Body.Promise.resolve({}); return Body.Promise.resolve({});
} }
return this._decode().then(function(buffer) { return this[DECODE]().then(buffer => JSON.parse(buffer.toString()));
return JSON.parse(buffer.toString()); }
});
};
/** /**
* Decode response as text * Decode response as text
* *
* @return Promise * @return Promise
*/ */
Body.prototype.text = function() { text() {
return this[DECODE]().then(buffer => buffer.toString());
return this._decode().then(function(buffer) { }
return buffer.toString();
});
};
/** /**
* Decode response as buffer (non-spec api) * Decode response as buffer (non-spec api)
* *
* @return Promise * @return Promise
*/ */
Body.prototype.buffer = function() { buffer() {
return this[DECODE]();
return this._decode(); }
};
/** /**
* Decode buffers into utf-8 string * Decode buffers into utf-8 string
* *
* @return Promise * @return Promise
*/ */
Body.prototype._decode = function() { [DECODE]() {
if (this[DISTURBED]) {
var self = this; return Body.Promise.reject(new Error(`body used already for: ${this.url}`));
if (this.bodyUsed) {
return Body.Promise.reject(new Error('body used already for: ' + this.url));
} }
this.bodyUsed = true; this[DISTURBED] = true;
this._bytes = 0; this[BYTES] = 0;
this._abort = false; this[ABORT] = false;
this._raw = []; this[RAW] = [];
return new Body.Promise(function(resolve, reject) { return new Body.Promise((resolve, reject) => {
var resTimeout; let resTimeout;
// body is string // body is string
if (typeof self.body === 'string') { if (typeof this.body === 'string') {
self._bytes = self.body.length; this[BYTES] = this.body.length;
self._raw = [new Buffer(self.body)]; this[RAW] = [new Buffer(this.body)];
return resolve(self._convert()); return resolve(this[CONVERT]());
} }
// body is buffer // body is buffer
if (self.body instanceof Buffer) { if (this.body instanceof Buffer) {
self._bytes = self.body.length; this[BYTES] = this.body.length;
self._raw = [self.body]; this[RAW] = [this.body];
return resolve(self._convert()); return resolve(this[CONVERT]());
} }
// allow timeout on slow response body // allow timeout on slow response body
if (self.timeout) { if (this.timeout) {
resTimeout = setTimeout(function() { resTimeout = setTimeout(() => {
self._abort = true; this[ABORT] = true;
reject(new FetchError('response timeout at ' + self.url + ' over limit: ' + self.timeout, 'body-timeout')); reject(new FetchError('response timeout at ' + this.url + ' over limit: ' + this.timeout, 'body-timeout'));
}, self.timeout); }, this.timeout);
} }
// handle stream error, such as incorrect content-encoding // handle stream error, such as incorrect content-encoding
self.body.on('error', function(err) { this.body.on('error', err => {
reject(new FetchError('invalid response body at: ' + self.url + ' reason: ' + err.message, 'system', err)); reject(new FetchError('invalid response body at: ' + this.url + ' reason: ' + err.message, 'system', err));
}); });
// body is stream // body is stream
self.body.on('data', function(chunk) { this.body.on('data', chunk => {
if (self._abort || chunk === null) { if (this[ABORT] || chunk === null) {
return; return;
} }
if (self.size && self._bytes + chunk.length > self.size) { if (this.size && this[BYTES] + chunk.length > this.size) {
self._abort = true; this[ABORT] = true;
reject(new FetchError('content size at ' + self.url + ' over limit: ' + self.size, 'max-size')); reject(new FetchError(`content size at ${this.url} over limit: ${this.size}`, 'max-size'));
return; return;
} }
self._bytes += chunk.length; this[BYTES] += chunk.length;
self._raw.push(chunk); this[RAW].push(chunk);
}); });
self.body.on('end', function() { this.body.on('end', () => {
if (self._abort) { if (this[ABORT]) {
return; return;
} }
clearTimeout(resTimeout); clearTimeout(resTimeout);
resolve(self._convert()); resolve(this[CONVERT]());
}); });
}); });
}
};
/** /**
* Detect buffer encoding and convert to target encoding * Detect buffer encoding and convert to target encoding
@ -157,28 +153,25 @@ Body.prototype._decode = function() {
* @param String encoding Target encoding * @param String encoding Target encoding
* @return String * @return String
*/ */
Body.prototype._convert = function(encoding) { [CONVERT](encoding = 'utf-8') {
const ct = this.headers.get('content-type');
encoding = encoding || 'utf-8'; let charset = 'utf-8';
let res, str;
var ct = this.headers.get('content-type');
var charset = 'utf-8';
var res, str;
// header // header
if (ct) { if (ct) {
// skip encoding detection altogether if not html/xml/plain text // skip encoding detection altogether if not html/xml/plain text
if (!/text\/html|text\/plain|\+xml|\/xml/i.test(ct)) { if (!/text\/html|text\/plain|\+xml|\/xml/i.test(ct)) {
return Buffer.concat(this._raw); return Buffer.concat(this[RAW]);
} }
res = /charset=([^;]*)/i.exec(ct); res = /charset=([^;]*)/i.exec(ct);
} }
// no charset in content type, peek at response body for at most 1024 bytes // no charset in content type, peek at response body for at most 1024 bytes
if (!res && this._raw.length > 0) { if (!res && this[RAW].length > 0) {
for (var i = 0; i < this._raw.length; i++) { for (let i = 0; i < this[RAW].length; i++) {
str += this._raw[i].toString() str += this[RAW][i].toString()
if (str.length > 1024) { if (str.length > 1024) {
break; break;
} }
@ -218,12 +211,13 @@ Body.prototype._convert = function(encoding) {
// turn raw buffers into a single utf-8 buffer // turn raw buffers into a single utf-8 buffer
return convert( return convert(
Buffer.concat(this._raw) Buffer.concat(this[RAW])
, encoding , encoding
, charset , charset
); );
}
}; }
/** /**
* Clone body given Res/Req instance * Clone body given Res/Req instance
@ -231,9 +225,9 @@ Body.prototype._convert = function(encoding) {
* @param Mixed instance Response or Request instance * @param Mixed instance Response or Request instance
* @return Mixed * @return Mixed
*/ */
Body.prototype._clone = function(instance) { export function clone(instance) {
var p1, p2; let p1, p2;
var body = instance.body; let body = instance.body;
// don't allow cloning a used body // don't allow cloning a used body
if (instance.bodyUsed) { if (instance.bodyUsed) {

View File

@ -5,8 +5,6 @@
* FetchError interface for operational errors * FetchError interface for operational errors
*/ */
module.exports = FetchError;
/** /**
* Create FetchError instance * Create FetchError instance
* *
@ -15,7 +13,7 @@ module.exports = FetchError;
* @param String systemError For Node.js system error * @param String systemError For Node.js system error
* @return FetchError * @return FetchError
*/ */
function FetchError(message, type, systemError) { export default function FetchError(message, type, systemError) {
// hide custom error implementation details from end-users // hide custom error implementation details from end-users
Error.captureStackTrace(this, this.constructor); Error.captureStackTrace(this, this.constructor);

View File

@ -5,50 +5,38 @@
* a request API compatible with window.fetch * a request API compatible with window.fetch
*/ */
var parse_url = require('url').parse; import {resolve as resolve_url} from 'url';
var resolve_url = require('url').resolve; import * as http from 'http';
var http = require('http'); import * as https from 'https';
var https = require('https'); import * as zlib from 'zlib';
var zlib = require('zlib'); import {PassThrough} from 'stream';
var stream = require('stream');
var Body = require('./body'); import Body from './body';
var Response = require('./response'); import Response from './response';
import Headers from './headers'; import Headers from './headers';
var Request = require('./request'); import Request from './request';
var FetchError = require('./fetch-error'); import FetchError from './fetch-error';
// commonjs
module.exports = Fetch;
// es6 default export compatibility
module.exports.default = module.exports;
/** /**
* Fetch class * Fetch function
* *
* @param Mixed url Absolute url or Request instance * @param Mixed url Absolute url or Request instance
* @param Object opts Fetch options * @param Object opts Fetch options
* @return Promise * @return Promise
*/ */
function Fetch(url, opts) { function fetch(url, opts) {
// allow call as function
if (!(this instanceof Fetch))
return new Fetch(url, opts);
// allow custom promise // allow custom promise
if (!Fetch.Promise) { if (!fetch.Promise) {
throw new Error('native promise missing, set Fetch.Promise to your favorite alternative'); throw new Error('native promise missing, set fetch.Promise to your favorite alternative');
} }
Body.Promise = Fetch.Promise; Body.Promise = fetch.Promise;
var self = this;
// wrap http.request into fetch // wrap http.request into fetch
return new Fetch.Promise(function(resolve, reject) { return new fetch.Promise((resolve, reject) => {
// build request object // build request object
var options = new Request(url, opts); const options = new Request(url, opts);
if (!options.protocol || !options.hostname) { if (!options.protocol || !options.hostname) {
throw new Error('only absolute urls are supported'); throw new Error('only absolute urls are supported');
@ -58,15 +46,10 @@ function Fetch(url, opts) {
throw new Error('only http(s) protocols are supported'); throw new Error('only http(s) protocols are supported');
} }
var send; const send = (options.protocol === 'https:' ? https : http).request;
if (options.protocol === 'https:') {
send = https.request;
} else {
send = http.request;
}
// normalize headers // normalize headers
var headers = new Headers(options.headers); const headers = new Headers(options.headers);
if (options.compress) { if (options.compress) {
headers.set('accept-encoding', 'gzip,deflate'); headers.set('accept-encoding', 'gzip,deflate');
@ -86,7 +69,7 @@ function Fetch(url, opts) {
// detect form data input from form-data module, this hack avoid the need to pass multipart header manually // detect form data input from form-data module, this hack avoid the need to pass multipart header manually
if (!headers.has('content-type') && options.body && typeof options.body.getBoundary === 'function') { if (!headers.has('content-type') && options.body && typeof options.body.getBoundary === 'function') {
headers.set('content-type', 'multipart/form-data; boundary=' + options.body.getBoundary()); headers.set('content-type', `multipart/form-data; boundary=${options.body.getBoundary()}`);
} }
// bring node-fetch closer to browser behavior by setting content-length automatically // bring node-fetch closer to browser behavior by setting content-length automatically
@ -116,40 +99,40 @@ function Fetch(url, opts) {
} }
// send request // send request
var req = send(options); const req = send(options);
var reqTimeout; let reqTimeout;
if (options.timeout) { if (options.timeout) {
req.once('socket', function(socket) { req.once('socket', socket => {
reqTimeout = setTimeout(function() { reqTimeout = setTimeout(() => {
req.abort(); req.abort();
reject(new FetchError('network timeout at: ' + options.url, 'request-timeout')); reject(new FetchError(`network timeout at: ${options.url}`, 'request-timeout'));
}, options.timeout); }, options.timeout);
}); });
} }
req.on('error', function(err) { req.on('error', err => {
clearTimeout(reqTimeout); clearTimeout(reqTimeout);
reject(new FetchError('request to ' + options.url + ' failed, reason: ' + err.message, 'system', err)); reject(new FetchError(`request to ${options.url} failed, reason: ${err.message}`, 'system', err));
}); });
req.on('response', function(res) { req.on('response', res => {
clearTimeout(reqTimeout); clearTimeout(reqTimeout);
// handle redirect // handle redirect
if (self.isRedirect(res.statusCode) && options.redirect !== 'manual') { if (fetch.isRedirect(res.statusCode) && options.redirect !== 'manual') {
if (options.redirect === 'error') { if (options.redirect === 'error') {
reject(new FetchError('redirect mode is set to error: ' + options.url, 'no-redirect')); reject(new FetchError(`redirect mode is set to error: ${options.url}`, 'no-redirect'));
return; return;
} }
if (options.counter >= options.follow) { if (options.counter >= options.follow) {
reject(new FetchError('maximum redirect reached at: ' + options.url, 'max-redirect')); reject(new FetchError(`maximum redirect reached at: ${options.url}`, 'max-redirect'));
return; return;
} }
if (!res.headers.location) { if (!res.headers.location) {
reject(new FetchError('redirect location header missing at: ' + options.url, 'invalid-redirect')); reject(new FetchError(`redirect location header missing at: ${options.url}`, 'invalid-redirect'));
return; return;
} }
@ -164,19 +147,19 @@ function Fetch(url, opts) {
options.counter++; options.counter++;
resolve(Fetch(resolve_url(options.url, res.headers.location), options)); resolve(fetch(resolve_url(options.url, res.headers.location), options));
return; return;
} }
// normalize location header for manual redirect mode // normalize location header for manual redirect mode
var headers = new Headers(res.headers); const headers = new Headers(res.headers);
if (options.redirect === 'manual' && headers.has('location')) { if (options.redirect === 'manual' && headers.has('location')) {
headers.set('location', resolve_url(options.url, headers.get('location'))); headers.set('location', resolve_url(options.url, headers.get('location')));
} }
// prepare response // prepare response
var body = res.pipe(new stream.PassThrough()); let body = res.pipe(new PassThrough());
var response_options = { const response_options = {
url: options.url url: options.url
, status: res.statusCode , status: res.statusCode
, statusText: res.statusMessage , statusText: res.statusMessage
@ -186,7 +169,7 @@ function Fetch(url, opts) {
}; };
// response object // response object
var output; let output;
// in following scenarios we ignore compression support // in following scenarios we ignore compression support
// 1. compression support is disabled // 1. compression support is disabled
@ -201,7 +184,7 @@ function Fetch(url, opts) {
} }
// otherwise, check for gzip or deflate // otherwise, check for gzip or deflate
var name = headers.get('content-encoding'); let name = headers.get('content-encoding');
// for gzip // for gzip
if (name == 'gzip' || name == 'x-gzip') { if (name == 'gzip' || name == 'x-gzip') {
@ -214,8 +197,8 @@ function Fetch(url, opts) {
} else if (name == 'deflate' || name == 'x-deflate') { } else if (name == 'deflate' || name == 'x-deflate') {
// handle the infamous raw deflate response from old servers // handle the infamous raw deflate response from old servers
// a hack for old IIS and Apache servers // a hack for old IIS and Apache servers
var raw = res.pipe(new stream.PassThrough()); const raw = res.pipe(new PassThrough());
raw.once('data', function(chunk) { raw.once('data', chunk => {
// see http://stackoverflow.com/questions/37519828 // see http://stackoverflow.com/questions/37519828
if ((chunk[0] & 0x0F) === 0x08) { if ((chunk[0] & 0x0F) === 0x08) {
body = body.pipe(zlib.createInflate()); body = body.pipe(zlib.createInflate());
@ -254,18 +237,18 @@ function Fetch(url, opts) {
}; };
module.exports = fetch;
/** /**
* Redirect code matching * Redirect code matching
* *
* @param Number code Status code * @param Number code Status code
* @return Boolean * @return Boolean
*/ */
Fetch.prototype.isRedirect = function(code) { fetch.isRedirect = code => code === 301 || code === 302 || code === 303 || code === 307 || code === 308;
return code === 301 || code === 302 || code === 303 || code === 307 || code === 308;
}
// expose Promise // expose Promise
Fetch.Promise = global.Promise; fetch.Promise = global.Promise;
Fetch.Response = Response; fetch.Response = Response;
Fetch.Headers = Headers; fetch.Headers = Headers;
Fetch.Request = Request; fetch.Request = Request;

View File

@ -5,11 +5,9 @@
* Request class contains server only options * Request class contains server only options
*/ */
var parse_url = require('url').parse; import { parse as parse_url } from 'url';
import Headers from './headers'; import Headers from './headers.js';
var Body = require('./body'); import Body, { clone } from './body';
module.exports = Request;
/** /**
* Request class * Request class
@ -18,8 +16,9 @@ module.exports = Request;
* @param Object init Custom options * @param Object init Custom options
* @return Void * @return Void
*/ */
function Request(input, init) { export default class Request extends Body {
var url, url_parsed; constructor(input, init = {}) {
let url, url_parsed;
// normalize input // normalize input
if (!(input instanceof Request)) { if (!(input instanceof Request)) {
@ -31,8 +30,10 @@ function Request(input, init) {
url_parsed = parse_url(url); url_parsed = parse_url(url);
} }
// normalize init super(init.body || clone(input), {
init = init || {}; timeout: init.timeout || input.timeout || 0,
size: init.size || input.size || 0
});
// fetch spec options // fetch spec options
this.method = init.method || input.method || 'GET'; this.method = init.method || input.method || 'GET';
@ -50,11 +51,6 @@ function Request(input, init) {
this.counter = init.counter || input.counter || 0; this.counter = init.counter || input.counter || 0;
this.agent = init.agent || input.agent; this.agent = init.agent || input.agent;
Body.call(this, init.body || this._clone(input), {
timeout: init.timeout || input.timeout || 0,
size: init.size || input.size || 0
});
// server request options // server request options
this.protocol = url_parsed.protocol; this.protocol = url_parsed.protocol;
this.hostname = url_parsed.hostname; this.hostname = url_parsed.hostname;
@ -63,13 +59,19 @@ function Request(input, init) {
this.auth = url_parsed.auth; this.auth = url_parsed.auth;
} }
Request.prototype = Object.create(Body.prototype);
/** /**
* Clone this request * Clone this request
* *
* @return Request * @return Request
*/ */
Request.prototype.clone = function() { clone() {
return new Request(this); return new Request(this);
}; }
/**
* Tag used by `Object.prototype.toString()`.
*/
get [Symbol.toStringTag]() {
return 'Request';
}
}

View File

@ -5,11 +5,9 @@
* Response class provides content decoding * Response class provides content decoding
*/ */
var http = require('http'); import { STATUS_CODES } from 'http';
import Headers from './headers'; import Headers from './headers.js';
var Body = require('./body'); import Body, { clone } from './body';
module.exports = Response;
/** /**
* Response class * Response class
@ -18,33 +16,44 @@ module.exports = Response;
* @param Object opts Response options * @param Object opts Response options
* @return Void * @return Void
*/ */
function Response(body, opts) { export default class Response extends Body {
constructor(body, opts = {}) {
opts = opts || {}; super(body, opts);
this.url = opts.url; this.url = opts.url;
this.status = opts.status || 200; this.status = opts.status || 200;
this.statusText = opts.statusText || http.STATUS_CODES[this.status]; this.statusText = opts.statusText || STATUS_CODES[this.status];
this.headers = new Headers(opts.headers); this.headers = new Headers(opts.headers);
this.ok = this.status >= 200 && this.status < 300;
Body.call(this, body, opts);
} }
Response.prototype = Object.create(Body.prototype); /**
* Convenience property representing if the request ended normally
*/
get ok() {
return this.status >= 200 && this.status < 300;
}
/** /**
* Clone this response * Clone this response
* *
* @return Response * @return Response
*/ */
Response.prototype.clone = function() { clone() {
return new Response(this._clone(this), {
return new Response(clone(this), {
url: this.url url: this.url
, status: this.status , status: this.status
, statusText: this.statusText , statusText: this.statusText
, headers: this.headers , headers: this.headers
, ok: this.ok , ok: this.ok
}); });
};
}
/**
* Tag used by `Object.prototype.toString()`.
*/
get [Symbol.toStringTag]() {
return 'Response';
}
}

View File

@ -1,14 +1,13 @@
import 'babel-polyfill';
import * as http from 'http';
import { parse } from 'url';
import * as zlib from 'zlib';
import * as stream from 'stream';
import { convert } from 'encoding';
import { multipart as Multipart } from 'parted';
var http = require('http'); export default class TestServer {
var parse = require('url').parse; constructor() {
var zlib = require('zlib');
var stream = require('stream');
var convert = require('encoding').convert;
var Multipart = require('parted').multipart;
module.exports = TestServer;
function TestServer() {
this.server = http.createServer(this.router); this.server = http.createServer(this.router);
this.port = 30001; this.port = 30001;
this.hostname = 'localhost'; this.hostname = 'localhost';
@ -20,17 +19,16 @@ function TestServer() {
}); });
} }
TestServer.prototype.start = function(cb) { start(cb) {
this.server.listen(this.port, this.hostname, cb); this.server.listen(this.port, this.hostname, cb);
} }
TestServer.prototype.stop = function(cb) { stop(cb) {
this.server.close(cb); this.server.close(cb);
} }
TestServer.prototype.router = function(req, res) { router(req, res) {
let p = parse(req.url).pathname;
var p = parse(req.url).pathname;
if (p === '/hello') { if (p === '/hello') {
res.statusCode = 200; res.statusCode = 200;
@ -190,10 +188,8 @@ TestServer.prototype.router = function(req, res) {
res.statusCode = 200; res.statusCode = 200;
res.setHeader('Content-Type', 'text/html'); res.setHeader('Content-Type', 'text/html');
res.setHeader('Transfer-Encoding', 'chunked'); res.setHeader('Transfer-Encoding', 'chunked');
var padding = 'a'; const padding = 'a';
for (var i = 0; i < 10; i++) { res.write(padding.repeat(10));
res.write(padding);
}
res.end(convert('<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS" /><div>日本語</div>', 'Shift_JIS')); res.end(convert('<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS" /><div>日本語</div>', 'Shift_JIS'));
} }
@ -201,11 +197,8 @@ TestServer.prototype.router = function(req, res) {
res.statusCode = 200; res.statusCode = 200;
res.setHeader('Content-Type', 'text/html'); res.setHeader('Content-Type', 'text/html');
res.setHeader('Transfer-Encoding', 'chunked'); res.setHeader('Transfer-Encoding', 'chunked');
// because node v0.12 doesn't have str.repeat const padding = 'a'.repeat(120);
var padding = new Array(120 + 1).join('a'); res.write(padding.repeat(10));
for (var i = 0; i < 10; i++) {
res.write(padding);
}
res.end(convert('中文', 'gbk')); res.end(convert('中文', 'gbk'));
} }
@ -304,14 +297,14 @@ TestServer.prototype.router = function(req, res) {
if (p === '/inspect') { if (p === '/inspect') {
res.statusCode = 200; res.statusCode = 200;
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
var body = ''; let body = '';
req.on('data', function(c) { body += c }); req.on('data', function(c) { body += c });
req.on('end', function() { req.on('end', function() {
res.end(JSON.stringify({ res.end(JSON.stringify({
method: req.method, method: req.method,
url: req.url, url: req.url,
headers: req.headers, headers: req.headers,
body: body body
})); }));
}); });
} }
@ -319,8 +312,8 @@ TestServer.prototype.router = function(req, res) {
if (p === '/multipart') { if (p === '/multipart') {
res.statusCode = 200; res.statusCode = 200;
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
var parser = new Multipart(req.headers['content-type']); const parser = new Multipart(req.headers['content-type']);
var body = ''; let body = '';
parser.on('part', function(field, part) { parser.on('part', function(field, part) {
body += field + '=' + part; body += field + '=' + part;
}); });
@ -335,3 +328,4 @@ TestServer.prototype.router = function(req, res) {
req.pipe(parser); req.pipe(parser);
} }
} }
}

File diff suppressed because it is too large Load Diff