From 005d607aedf57eac046834060f3f6e8f24817407 Mon Sep 17 00:00:00 2001 From: seebees Date: Fri, 14 Oct 2011 17:10:49 -0700 Subject: [PATCH] http.request(url.parse(x)) http2.js protocols object to store defaults for http and https, and use as a switch for supported protocols. options.hostname > options.host > 'localhost' if I have an options.auth element and I do not have an Authorization header, I do basic auth. http.request collapses to new ClientRequest since the defaults are handled by the protocol object test-http-url.parse* Fixes #1390 Conflicts: lib/http2.js --- lib/http.js | 15 +++- lib/https.js | 6 +- ...p-url.parse-auth-with-header-in-request.js | 51 ++++++++++++ test/simple/test-http-url.parse-auth.js | 46 +++++++++++ test/simple/test-http-url.parse-basic.js | 55 +++++++++++++ .../test-http-url.parse-https.request.js | 57 +++++++++++++ ....parse-only-support-http-https-protocol.js | 82 +++++++++++++++++++ test/simple/test-http-url.parse-path.js | 46 +++++++++++ test/simple/test-http-url.parse-post.js | 52 ++++++++++++ test/simple/test-http-url.parse-search.js | 46 +++++++++++ 10 files changed, 453 insertions(+), 3 deletions(-) create mode 100644 test/simple/test-http-url.parse-auth-with-header-in-request.js create mode 100644 test/simple/test-http-url.parse-auth.js create mode 100644 test/simple/test-http-url.parse-basic.js create mode 100644 test/simple/test-http-url.parse-https.request.js create mode 100644 test/simple/test-http-url.parse-only-support-http-https-protocol.js create mode 100644 test/simple/test-http-url.parse-path.js create mode 100644 test/simple/test-http-url.parse-post.js create mode 100644 test/simple/test-http-url.parse-search.js diff --git a/lib/http.js b/lib/http.js index 829eb2798ca..2d298203a95 100644 --- a/lib/http.js +++ b/lib/http.js @@ -980,6 +980,7 @@ Agent.prototype.removeSocket = function(s, name, host, port) { var globalAgent = new Agent(); exports.globalAgent = globalAgent; + function ClientRequest(options, cb) { var self = this; OutgoingMessage.call(self); @@ -987,7 +988,7 @@ function ClientRequest(options, cb) { options.defaultPort = options.defaultPort || 80; options.port = options.port || options.defaultPort; - options.host = options.host || 'localhost'; + options.host = options.hostname || options.host || 'localhost'; if (options.setHost === undefined) { options.setHost = true; @@ -1018,6 +1019,12 @@ function ClientRequest(options, cb) { } } + if (options.auth && !this.getHeader('Authorization')) { + //basic auth + this.setHeader('Authorization', 'Basic ' + + new Buffer(options.auth).toString('base64')); + } + if (method === 'GET' || method === 'HEAD') { self.useChunkedEncodingByDefault = false; } else { @@ -1276,10 +1283,14 @@ ClientRequest.prototype.pause = function() { exports.request = function(options, cb) { + if (options.protocol && options.protocol !== 'http:') { + throw new Error('Protocol:' + options.protocol + ' not supported.'); + } + if (options.agent === undefined) { options.agent = globalAgent; } - options.defaultPort = options.defaultPort || 80; + return new ClientRequest(options, cb); }; diff --git a/lib/https.js b/lib/https.js index c0394319b7a..1c3d61e1007 100644 --- a/lib/https.js +++ b/lib/https.js @@ -68,12 +68,16 @@ exports.globalAgent = globalAgent; exports.Agent = Agent; exports.request = function(options, cb) { + if (options.protocol && options.protocol !== 'https:') { + throw new Error('Protocol:' + options.protocol + ' not supported.'); + } + if (options.agent === undefined) { options.agent = globalAgent; } options.createConnection = createConnection; options.defaultPort = options.defaultPort || 443; - return http.request(options, cb); + return new http.ClientRequest(options, cb); }; exports.get = function(options, cb) { diff --git a/test/simple/test-http-url.parse-auth-with-header-in-request.js b/test/simple/test-http-url.parse-auth-with-header-in-request.js new file mode 100644 index 00000000000..6abb8f99dee --- /dev/null +++ b/test/simple/test-http-url.parse-auth-with-header-in-request.js @@ -0,0 +1,51 @@ +// 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 https = require('https'); +var url = require('url'); + +var testURL = url.parse('http://asdf:qwer@localhost:' + common.PORT); +// the test here is if you set a specific authorization header in the +// request we should not override that with basic auth +testURL.headers = { + Authorization: 'NoAuthForYOU' +}; + +function check(request) { + // the correct authorization header is be passed + assert.strictEqual(request.headers.authorization, 'NoAuthForYOU'); +} + +var server = http.createServer(function(request, response) { + // run the check function + check.call(this, request, response); + response.writeHead(200, {}); + response.end('ok'); + server.close(); +}); + +server.listen(common.PORT, function () { + // make the request + http.request(testURL).end(); +}); diff --git a/test/simple/test-http-url.parse-auth.js b/test/simple/test-http-url.parse-auth.js new file mode 100644 index 00000000000..0aa43fcae6c --- /dev/null +++ b/test/simple/test-http-url.parse-auth.js @@ -0,0 +1,46 @@ +// 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 https = require('https'); +var url = require('url'); + +var testURL = url.parse('http://asdf:qwer@localhost:' + common.PORT); + +function check(request) { + // the correct authorization header is be passed + assert.strictEqual(request.headers.authorization, 'Basic YXNkZjpxd2Vy'); +} + +var server = http.createServer(function(request, response) { + // run the check function + check.call(this, request, response); + response.writeHead(200, {}); + response.end('ok'); + server.close(); +}); + +server.listen(common.PORT, function () { + // make the request + http.request(testURL).end(); +}); diff --git a/test/simple/test-http-url.parse-basic.js b/test/simple/test-http-url.parse-basic.js new file mode 100644 index 00000000000..8bf12b1c2df --- /dev/null +++ b/test/simple/test-http-url.parse-basic.js @@ -0,0 +1,55 @@ +// 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 url = require('url'); + +var testURL = url.parse('http://localhost:' + common.PORT); + +// make sure the basics work +function check(request) { + // default method should still be get + assert.strictEqual(request.method, 'GET'); + // there are no URL params, so you should not see any + assert.strictEqual(request.url, '/'); + // the host header should use the url.parse.hostname + assert.strictEqual(request.headers.host, + testURL.hostname + ':' + testURL.port); +} + +var server = http.createServer(function(request, response) { + // run the check function + check.call(this, request, response); + response.writeHead(200, {}); + response.end('ok'); + server.close(); +}); + +server.listen(common.PORT, function() { + // make the request + var clientRequest = http.request(testURL); + // since there is a little magic with the agent + // make sure that an http request uses the http.Agent + assert.ok(clientRequest.agent instanceof http.Agent); + clientRequest.end(); +}); diff --git a/test/simple/test-http-url.parse-https.request.js b/test/simple/test-http-url.parse-https.request.js new file mode 100644 index 00000000000..f16646057b4 --- /dev/null +++ b/test/simple/test-http-url.parse-https.request.js @@ -0,0 +1,57 @@ +// 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 https = require('https'); +var url = require('url'); +var fs = require('fs'); +var clientRequest; + +// https options +var httpsOptions = { + key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'), + cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem') +}; + +var testURL = url.parse('https://localhost:' + common.PORT); + +function check(request) { + // assert that I'm https + assert.ok(request.socket.encrypted); +} + +var server = https.createServer(httpsOptions, function(request, response) { + // run the check function + check.call(this, request, response); + response.writeHead(200, {}); + response.end('ok'); + server.close(); +}); + +server.listen(common.PORT, function () { + // make the request + var clientRequest = https.request(testURL); + // since there is a little magic with the agent + // make sure that the request uses the https.Agent + assert.ok(clientRequest.agent instanceof https.Agent); + clientRequest.end(); +}); diff --git a/test/simple/test-http-url.parse-only-support-http-https-protocol.js b/test/simple/test-http-url.parse-only-support-http-https-protocol.js new file mode 100644 index 00000000000..c77df5e20b0 --- /dev/null +++ b/test/simple/test-http-url.parse-only-support-http-https-protocol.js @@ -0,0 +1,82 @@ +// 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 url = require('url'); + + +assert.throws(function() { + http.request(url.parse('file:///whatever')); +}, function(err) { + if (err instanceof Error) { + assert.strictEqual(err.message, 'Protocol:file: not supported.'); + return true; + } +}); + +assert.throws(function() { + http.request(url.parse('mailto:asdf@asdf.com')); +}, function(err) { + if (err instanceof Error) { + assert.strictEqual(err.message, 'Protocol:mailto: not supported.'); + return true; + } +}); + +assert.throws(function() { + http.request(url.parse('ftp://www.example.com')); +}, function(err) { + if (err instanceof Error) { + assert.strictEqual(err.message, 'Protocol:ftp: not supported.'); + return true; + } +}); + +assert.throws(function() { + http.request(url.parse('javascript:alert(\'hello\');')); +}, function(err) { + if (err instanceof Error) { + assert.strictEqual(err.message, 'Protocol:javascript: not supported.'); + return true; + } +}); + +assert.throws(function() { + http.request(url.parse('xmpp:isaacschlueter@jabber.org')); +}, function(err) { + if (err instanceof Error) { + assert.strictEqual(err.message, 'Protocol:xmpp: not supported.'); + return true; + } +}); + +assert.throws(function() { + http.request(url.parse('f://some.host/path')); +}, function(err) { + if (err instanceof Error) { + assert.strictEqual(err.message, 'Protocol:f: not supported.'); + return true; + } +}); + +//TODO do I need to test url.parse(notPrococol.example.com)? diff --git a/test/simple/test-http-url.parse-path.js b/test/simple/test-http-url.parse-path.js new file mode 100644 index 00000000000..ec97d87a4d2 --- /dev/null +++ b/test/simple/test-http-url.parse-path.js @@ -0,0 +1,46 @@ +// 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 https = require('https'); +var url = require('url'); + +var testURL = url.parse('http://localhost:' + common.PORT + '/asdf'); + +function check(request) { + // a path should come over + assert.strictEqual(request.url, '/asdf'); +} + +var server = http.createServer(function(request, response) { + // run the check function + check.call(this, request, response); + response.writeHead(200, {}); + response.end('ok'); + server.close(); +}); + +server.listen(common.PORT, function () { + // make the request + http.request(testURL).end(); +}); diff --git a/test/simple/test-http-url.parse-post.js b/test/simple/test-http-url.parse-post.js new file mode 100644 index 00000000000..a51f061c180 --- /dev/null +++ b/test/simple/test-http-url.parse-post.js @@ -0,0 +1,52 @@ +// 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 https = require('https'); +var url = require('url'); + +var testURL = url.parse('http://localhost:' + common.PORT + '/asdf?qwer=zxcv'); +testURL.method = 'POST'; + +function check(request) { + //url.parse should not mess with the method + assert.strictEqual(request.method, 'POST'); + //everything else should be right + assert.strictEqual(request.url, '/asdf?qwer=zxcv'); + //the host header should use the url.parse.hostname + assert.strictEqual(request.headers.host, + testURL.hostname + ':' + testURL.port); +} + +var server = http.createServer(function(request, response) { + // run the check function + check.call(this, request, response); + response.writeHead(200, {}); + response.end('ok'); + server.close(); +}); + +server.listen(common.PORT, function () { + // make the request + http.request(testURL).end(); +}); diff --git a/test/simple/test-http-url.parse-search.js b/test/simple/test-http-url.parse-search.js new file mode 100644 index 00000000000..2c7ca5c82c7 --- /dev/null +++ b/test/simple/test-http-url.parse-search.js @@ -0,0 +1,46 @@ +// 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 https = require('https'); +var url = require('url'); + +var testURL = url.parse('http://localhost:' + common.PORT + '/asdf?qwer=zxcv'); + +function check(request) { + // a path should come over with params + assert.strictEqual(request.url, '/asdf?qwer=zxcv'); +} + +var server = http.createServer(function(request, response) { + // run the check function + check.call(this, request, response); + response.writeHead(200, {}); + response.end('ok'); + server.close(); +}); + +server.listen(common.PORT, function () { + // make the request + http.request(testURL).end(); +});