diff --git a/.travis.yml b/.travis.yml index 0988483f3..b67e2afba 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,6 @@ language: node_js node_js: - - "0.8" - "0.10" -before_install: npm install -g npm@~1.4.6 after_script: ./node_modules/.bin/istanbul cover ./node_modules/tape/bin/tape tests/test-*.js --report lcovonly && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js --verbose webhooks: urls: https://webhooks.gitter.im/e/237280ed4796c19cc626 diff --git a/README.md b/README.md index d5aeec375..00f4b17d6 100644 --- a/README.md +++ b/README.md @@ -633,6 +633,7 @@ The first argument can be either a `url` or an `options` object. The only requir tunneling proxy. * `proxyHeaderExclusiveList` - A whitelist of headers to send exclusively to a tunneling proxy and not to destination. +* `removeRefererHeader` - removes the referer header when a redirect happens (default: `false`). The callback argument gets 3 arguments: diff --git a/index.js b/index.js index 3581b83b4..f8b35150e 100755 --- a/index.js +++ b/index.js @@ -47,56 +47,23 @@ function request (uri, options, callback) { options.callback = params.callback options.uri = params.uri - return new request.Request(options) -} - -function requester(params) { - if(typeof params.options._requester === 'function') { - return params.options._requester - } - return request -} - -request.get = function (uri, options, callback) { - var params = initParams(uri, options, callback) - params.options.method = 'GET' - return requester(params)(params.uri || null, params.options, params.callback) -} - -request.head = function (uri, options, callback) { - var params = initParams(uri, options, callback) - params.options.method = 'HEAD' - - if (paramsHaveRequestBody(params)) { + if (params.options.method === 'HEAD' && paramsHaveRequestBody(params)) { throw new Error('HTTP HEAD requests MUST NOT include a request body.') } - return requester(params)(params.uri || null, params.options, params.callback) -} - -request.post = function (uri, options, callback) { - var params = initParams(uri, options, callback) - params.options.method = 'POST' - return requester(params)(params.uri || null, params.options, params.callback) + return new request.Request(options) } -request.put = function (uri, options, callback) { - var params = initParams(uri, options, callback) - params.options.method = 'PUT' - return requester(params)(params.uri || null, params.options, params.callback) -} +var verbs = ['get', 'head', 'post', 'put', 'patch', 'del'] -request.patch = function (uri, options, callback) { - var params = initParams(uri, options, callback) - params.options.method = 'PATCH' - return requester(params)(params.uri || null, params.options, params.callback) -} - -request.del = function (uri, options, callback) { - var params = initParams(uri, options, callback) - params.options.method = 'DELETE' - return requester(params)(params.uri || null, params.options, params.callback) -} +verbs.forEach(function(verb){ + var method = verb === 'del' ? 'DELETE' : verb.toUpperCase() + request[verb] = function(uri, options, callback){ + var params = initParams(uri, options, callback) + params.options.method = method + return this(params.uri || null, params.options, params.callback) + } +}) request.jar = function (store) { return cookies.jar(store) @@ -107,6 +74,12 @@ request.cookie = function (str) { } request.defaults = function (options, requester) { + + if (typeof options === 'function') { + requester = options + options = {} + } + var self = this var wrap = function (method) { var headerlessOptions = function (options) { @@ -131,11 +104,7 @@ request.defaults = function (options, requester) { } if (isFunction(requester)) { - if (method === self) { - method = requester - } else { - params.options._requester = requester - } + method = requester } return method(params.options, params.callback) @@ -143,13 +112,13 @@ request.defaults = function (options, requester) { } var defaults = wrap(self) - defaults.get = wrap(self.get) - defaults.patch = wrap(self.patch) - defaults.post = wrap(self.post) - defaults.put = wrap(self.put) - defaults.head = wrap(self.head) - defaults.del = wrap(self.del) - defaults.cookie = wrap(self.cookie) + defaults.get = self.get + defaults.patch = self.patch + defaults.post = self.post + defaults.put = self.put + defaults.head = self.head + defaults.del = self.del + defaults.cookie = self.cookie defaults.jar = self.jar defaults.defaults = self.defaults return defaults diff --git a/lib/multipart.js b/lib/multipart.js index cddd8d392..390a7f2d1 100644 --- a/lib/multipart.js +++ b/lib/multipart.js @@ -21,14 +21,14 @@ Multipart.prototype.isChunked = function (options) { throw new Error('Argument error, options.multipart.') } - if (self.request.getHeader('transfer-encoding') === 'chunked') { - chunked = true - } - if (options.chunked !== undefined) { chunked = options.chunked } + if (self.request.getHeader('transfer-encoding') === 'chunked') { + chunked = true + } + if (!chunked) { parts.forEach(function (part) { if(typeof part.body === 'undefined') { @@ -51,11 +51,16 @@ Multipart.prototype.setHeaders = function (chunked) { } var header = self.request.getHeader('content-type') - var contentType = (!header || header.indexOf('multipart') === -1) - ? 'multipart/related' - : header.split(';')[0] - self.request.setHeader('content-type', contentType + '; boundary=' + self.boundary) + if (!header || header.indexOf('multipart') === -1) { + self.request.setHeader('content-type', 'multipart/related; boundary=' + self.boundary) + } else { + if (header.indexOf('boundary') !== -1) { + self.boundary = header.replace(/.*boundary=([^\s;])+.*/, '$1') + } else { + self.request.setHeader('content-type', header + '; boundary=' + self.boundary) + } + } } Multipart.prototype.build = function (parts, chunked) { diff --git a/lib/redirect.js b/lib/redirect.js index 2d9a9d518..7dd6c254c 100644 --- a/lib/redirect.js +++ b/lib/redirect.js @@ -12,6 +12,7 @@ function Redirect (request) { this.maxRedirects = 10 this.redirects = [] this.redirectsFollowed = 0 + this.removeRefererHeader = false } Redirect.prototype.onRequest = function () { @@ -33,6 +34,9 @@ Redirect.prototype.onRequest = function () { if (self.followRedirects || self.followAllRedirects) { self.redirects = self.redirects || [] } + if (request.removeRefererHeader !== undefined) { + self.removeRefererHeader = request.removeRefererHeader + } } Redirect.prototype.redirectTo = function (response) { @@ -136,6 +140,10 @@ Redirect.prototype.onResponse = function (response) { } } + if (!self.removeRefererHeader) { + request.setHeader('referer', request.uri.href) + } + request.emit('redirect') request.init() diff --git a/tests/ssl/ca/client-enc.key b/tests/ssl/ca/client-enc.key index 8875c9ffc..f486c14a7 100644 --- a/tests/ssl/ca/client-enc.key +++ b/tests/ssl/ca/client-enc.key @@ -1,30 +1,30 @@ -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED -DEK-Info: AES-128-CBC,E95AEBB470632DA50EC1ABAB7F2D7A2A +DEK-Info: AES-128-CBC,849C363BAF8E1693D5464248A4AFD61A -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 -----END RSA PRIVATE KEY----- diff --git a/tests/ssl/ca/client.crt b/tests/ssl/ca/client.crt index 338387b9e..18f59f5b2 100644 --- a/tests/ssl/ca/client.crt +++ b/tests/ssl/ca/client.crt @@ -1,20 +1,20 @@ -----BEGIN CERTIFICATE----- -MIIDLjCCApcCCQCt9iAWqkDJwzANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMC +MIIDLjCCApcCCQCt9iAWqkDJwzANBgkqhkiG9w0BAQsFADCBojELMAkGA1UEBhMC VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMRAwDgYDVQQKEwdyZXF1 ZXN0MSYwJAYDVQQLEx1yZXF1ZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTESMBAG A1UEAxMJcmVxdWVzdENBMSYwJAYJKoZIhvcNAQkBFhdtaWtlYWxAbWlrZWFscm9n -ZXJzLmNvbTAeFw0xNTAxMjYyMTAxMjNaFw0xNTAyMjUyMTAxMjNaMIGPMQswCQYD +ZXJzLmNvbTAeFw0xNTAyMjQwMzIwNDNaFw0xNTAzMjYwMzIwNDNaMIGPMQswCQYD VQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNVBAcTB09ha2xhbmQxEDAOBgNVBAoT B3JlcXVlc3QxGjAYBgNVBAsUEXJlcXVlc3RAbG9jYWxob3N0MRMwEQYDVQQDEwpU ZXN0Q2xpZW50MR4wHAYJKoZIhvcNAQkBFg9kby5ub3RAZW1haWwubWUwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJDnEzgWpgsEyQcMQnkTTm7uFNKYOM -76RID4bdK2pHbFlW4ZEWC//RFee4XkAzI4Yqa0thSaQBlm/ZrQD5w82XlHNUMtAu -CJPfIMGKUYSBv8L26Bj23X8Hju1n8bdvyqAmLh0rvLvHF0g8AitpiQvn+DAhnV7A -st5a87mUbCoBtETmnOZ1HQk8eIJ+3kZ0WaTmJy3WY8lP+LA64qLOC7kpIKkeBJUT -ndnedd8gnq87Ale1XwLILUxN1hEfbBXLG2qxr8YDyUzntQMAEDNwJP8ikCcm8Yia -+Ftp7vuioVtwR9G4lTn+3LYwDV2mki2IAjZ0bTVowJXFu6Aw9uLmm9NpAgMBAAEw -DQYJKoZIhvcNAQEFBQADgYEAsmRaJf+axYufn9vLB5nh94vRsMSSLe5ARrWl0btT -BZil51V0zvBwU502AVjxhzYmWGwEJuuChsnOv3rf/km5EmDo/yYN1ZEIZZEKGPQ1 -U7GMMJkrT1aBplPI/97CjuZkJYhBKpXMvi0yb4leJfYIORSyegPsDOEpaKMKDcDO -QWw= +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDedUp5BgI+5UwtA8dk05fri2NJTQT8 +/v3gdzA/6mqSZENquJGV4230iay6JDiJRNnID/0cYQrjx+LtxoOcSWcuRYzIIIPr +rlcg6EdukPMky0S6ToOZ+BEgpyqDno2NenIPBfx1B51qdz00NcbZ8X4KPhBa+sx6 +ituNVWHPusSKfgeC59NmX/3XQTM6qT8fo0wiOY8XOBJ/tDI+A6EsaIhnhtX/ZwNA +8EbMDv924Y5QsJv29FAclLNnFV8UDlzWM3v00SWnWL2XWkNZiTKQF2dfcQnSHLaq +HgqA7NJlxkh4uEu57f8B3CuF4V7Qw+1uHbSUjv6P97YWFHHaggaYtQunAgMBAAEw +DQYJKoZIhvcNAQELBQADgYEAqtIehtQ+wfpOlF9inePBMmuMpd/VQ5Z1tQ25mqfo +NbmV6M6BEd26IVn+CAUmy+Gyh4PZXd03jp74HkSkMmdsIuva7n1/6SQ9O1ssqj/r +p+y8pzgabMId+WfBxpQkLzGDjNY8UPogARO1FcOog/81s0HbhLug098LaIIWjIl9 +d/w= -----END CERTIFICATE----- diff --git a/tests/ssl/ca/client.csr b/tests/ssl/ca/client.csr index 2186fe53d..4dd03c3a3 100644 --- a/tests/ssl/ca/client.csr +++ b/tests/ssl/ca/client.csr @@ -2,17 +2,17 @@ MIIC+DCCAeACAQAwgY8xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UE BxMHT2FrbGFuZDEQMA4GA1UEChMHcmVxdWVzdDEaMBgGA1UECxQRcmVxdWVzdEBs b2NhbGhvc3QxEzARBgNVBAMTClRlc3RDbGllbnQxHjAcBgkqhkiG9w0BCQEWD2Rv -Lm5vdEBlbWFpbC5tZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMkO -cTOBamCwTJBwxCeRNObu4U0pg4zvpEgPht0rakdsWVbhkRYL/9EV57heQDMjhipr -S2FJpAGWb9mtAPnDzZeUc1Qy0C4Ik98gwYpRhIG/wvboGPbdfweO7Wfxt2/KoCYu -HSu8u8cXSDwCK2mJC+f4MCGdXsCy3lrzuZRsKgG0ROac5nUdCTx4gn7eRnRZpOYn -LdZjyU/4sDrios4LuSkgqR4ElROd2d513yCerzsCV7VfAsgtTE3WER9sFcsbarGv -xgPJTOe1AwAQM3Ak/yKQJybxiJr4W2nu+6KhW3BH0biVOf7ctjANXaaSLYgCNnRt -NWjAlcW7oDD24uab02kCAwEAAaAjMCEGCSqGSIb3DQEJBzEUExJwYXNzd29yZCBj -aGFsbGVuZ2UwDQYJKoZIhvcNAQELBQADggEBACEqC+TJTli7enf064IaIbaJvN2+ -KyHgOmWvjI3B/Sswb2E8gm2d5epPTH1BD62wv2TowHI9NvRwa6MVb1xrdDs5WAck -EDvw9hUlv+9t5OXQXd0LmAzFVga3EjYCSdECKjiyTP71irBjmnxAYI/2cqE39xfw -rGLXI1qOs+ivptaCAIJeHkNjf/z6EHQJE9F6OyGI6Mhg8GcoufI5xfV8FXjy8RBd -Cz7uLocFxiQk9lwNwfL0ki5nrSWJOaa/1rY0q/sK/yHFLfapXEcE70vVr/hf05B/ -w8q4LgqU2PCELrFb0JKpT1L3lSXe17+AeYk2fi/SbHyVe53VY6rep/Y9yQ8= +Lm5vdEBlbWFpbC5tZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN51 +SnkGAj7lTC0Dx2TTl+uLY0lNBPz+/eB3MD/qapJkQ2q4kZXjbfSJrLokOIlE2cgP +/RxhCuPH4u3Gg5xJZy5FjMggg+uuVyDoR26Q8yTLRLpOg5n4ESCnKoOejY16cg8F +/HUHnWp3PTQ1xtnxfgo+EFr6zHqK241VYc+6xIp+B4Ln02Zf/ddBMzqpPx+jTCI5 +jxc4En+0Mj4DoSxoiGeG1f9nA0DwRswO/3bhjlCwm/b0UByUs2cVXxQOXNYze/TR +JadYvZdaQ1mJMpAXZ19xCdIctqoeCoDs0mXGSHi4S7nt/wHcK4XhXtDD7W4dtJSO +/o/3thYUcdqCBpi1C6cCAwEAAaAjMCEGCSqGSIb3DQEJBzEUExJwYXNzd29yZCBj +aGFsbGVuZ2UwDQYJKoZIhvcNAQELBQADggEBAH7qX1qNCZuW2xgD9+NqqkfFvNKQ +SVWebn4VaMRg2O+1X8jN+e3pX+hmRiOOZNXzFNG9nkYbxFGM+Y3fNDleS0Hg9Vwq +g4+cw2OGy2Uhhecr7sfvlG7/SgVZ/lN5UXcbM3eNb+/6GFRVzLoEWj8wmOpySI7k +Io4oHLsusDNIpGEXz4yIv6R5PApjmd9TEGo7QEhYc+3KfDlp0v6YZFJHJdur1cxu +GuaVagpI0bJzRmqGzad6P0bI7hLtv+lyUZlNA6g3aBEI7WmSoC91Gu2g4Kao19XD +EeXjPL81D6Q8vhSEcq4Rdg7SEobpPUbREizBblHwXGavCRiBWsGE1AHyjeI= -----END CERTIFICATE REQUEST----- diff --git a/tests/ssl/ca/client.key b/tests/ssl/ca/client.key index a61e755cf..b1adfee13 100644 --- a/tests/ssl/ca/client.key +++ b/tests/ssl/ca/client.key @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- diff --git a/tests/ssl/ca/gen-client.sh b/tests/ssl/ca/gen-client.sh index 953223ef4..c0f6d3be6 100755 --- a/tests/ssl/ca/gen-client.sh +++ b/tests/ssl/ca/gen-client.sh @@ -20,4 +20,4 @@ openssl x509 -req \ -out client.crt # Encrypt with password -openssl rsa -aes128 -in client.key -out client-enc.key -passout 'password' +openssl rsa -aes128 -in client.key -out client-enc.key -passout 'pass:password' diff --git a/tests/ssl/ca/localhost.crt b/tests/ssl/ca/localhost.crt index 7c8ad98c8..7c3d2fe6c 100644 --- a/tests/ssl/ca/localhost.crt +++ b/tests/ssl/ca/localhost.crt @@ -3,18 +3,18 @@ MIIDLTCCApYCCQCt9iAWqkDJwzANBgkqhkiG9w0BAQsFADCBojELMAkGA1UEBhMC VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMRAwDgYDVQQKEwdyZXF1 ZXN0MSYwJAYDVQQLEx1yZXF1ZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTESMBAG A1UEAxMJcmVxdWVzdENBMSYwJAYJKoZIhvcNAQkBFhdtaWtlYWxAbWlrZWFscm9n -ZXJzLmNvbTAeFw0xNTAxMjQwNDEzMzVaFw0xNTAyMjMwNDEzMzVaMIGOMQswCQYD +ZXJzLmNvbTAeFw0xNTAyMjQwMzA4MTFaFw0xNTAzMjYwMzA4MTFaMIGOMQswCQYD VQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNVBAcTB09ha2xhbmQxEDAOBgNVBAoT B3JlcXVlc3QxGjAYBgNVBAsUEXJlcXVlc3RAbG9jYWxob3N0MRIwEAYDVQQDEwls b2NhbGhvc3QxHjAcBgkqhkiG9w0BCQEWD2RvLm5vdEBlbWFpbC5tZTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ8rQcGbUWXLZZ0XAq0A5OSG/yunu0D5 -x5GcgArmiWo2EwgkdGGd3DrECmsXAqg05LDTP8LjN5wdvtdEXc4R+vf54VN/CD31 -AtFXILfGEQZioWtdni+T9K0jEcVukdklAwCC1jjplJ8MxTXyJ9pEVoyv/tX4EFMf -+ayUsDUCSrJQLW069iV4GXQglZr6UVfSG3ip4+1JDvP0MKUhitfWkrAYtb8m30AS -fRj2Le/9HhhBWwxLDK1G23TqC86Sqe0Mhk5a1V5DKZPanDld5jVNKlrXTUMU4OcL -b3mdidAy5kSFmRSJJdficeXnp6eBGK5kOFoRIyjeJ0Ut/ntw2c7WcLsCAwEAATAN -BgkqhkiG9w0BAQsFAAOBgQAgie0OE8U3w4w2cGgCa8qqraOezz961/i/6zNLamMn -XSjoIpB8syOgXzPTwk/pR1OPOIfv2C06usqTR31r/zAN63Ev+wqBW4RIQ6mD1J0O -WxmuY7pYyISD+5CXGMoxmM4Mh78GBQaUWTwhbsZr+vNSgEWwJfEvoh2BAVUgqjHh -ug== +KoZIhvcNAQEBBQADggEPADCCAQoCggEBAK2Gf9cnN22CchHhbKUGL0EImozz7D30 +C1IwoOnaJ/kTXWbRDQaF7Crycxd5eo1b/GyKvQW7+e4uDAilyUN/LR3zlBaGFODG ++EnQKo0cDlDiqCxH98dNmifZ5D9OrNjFVWgA1taKv3x3vsBeaP0oafeUAyx3ib6l +OgqcjI2nMNwWfilDZps2YTTcIDBQF8NXB0bgspDxsy3bBObEfnMlCd7N2daAQMV0 +vIf7GhIgO8+3aW8kAGh5KkwSG4ByYNXmQCtqoebpwFCnCTxLp4voAgSjGmc9KNfh +ga2wXDFeX4aMyHXNVx4KQeFvx2p5p1NfhIGPS83I79YDr5LAMso2QkECAwEAATAN +BgkqhkiG9w0BAQsFAAOBgQCJdR6oEMXPpsZ37N2V++WreQrj79RozT0p9yKy6Qjr +ynpgQDQyf9Lf+D1KPmjMHocy01prPiLuR5x3vbVtq/NGp+7zAJWBbQOhXBOz90JP +1gg7iFANrnDQCOKI9sW1+W/+1VwNYNSHfQL99lESBXm/lPRfF9/9nUkqj8FdOxu4 +SA== -----END CERTIFICATE----- diff --git a/tests/ssl/ca/localhost.csr b/tests/ssl/ca/localhost.csr index a74907d20..34c9be6ae 100644 --- a/tests/ssl/ca/localhost.csr +++ b/tests/ssl/ca/localhost.csr @@ -2,17 +2,17 @@ MIIC9zCCAd8CAQAwgY4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UE BxMHT2FrbGFuZDEQMA4GA1UEChMHcmVxdWVzdDEaMBgGA1UECxQRcmVxdWVzdEBs b2NhbGhvc3QxEjAQBgNVBAMTCWxvY2FsaG9zdDEeMBwGCSqGSIb3DQEJARYPZG8u -bm90QGVtYWlsLm1lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnytB -wZtRZctlnRcCrQDk5Ib/K6e7QPnHkZyACuaJajYTCCR0YZ3cOsQKaxcCqDTksNM/ -wuM3nB2+10RdzhH69/nhU38IPfUC0Vcgt8YRBmKha12eL5P0rSMRxW6R2SUDAILW -OOmUnwzFNfIn2kRWjK/+1fgQUx/5rJSwNQJKslAtbTr2JXgZdCCVmvpRV9IbeKnj -7UkO8/QwpSGK19aSsBi1vybfQBJ9GPYt7/0eGEFbDEsMrUbbdOoLzpKp7QyGTlrV -XkMpk9qcOV3mNU0qWtdNQxTg5wtveZ2J0DLmRIWZFIkl1+Jx5eenp4EYrmQ4WhEj -KN4nRS3+e3DZztZwuwIDAQABoCMwIQYJKoZIhvcNAQkHMRQTEnBhc3N3b3JkIGNo -YWxsZW5nZTANBgkqhkiG9w0BAQsFAAOCAQEAQBSAV6pyGnm1+EsDku9sKWy1ZhM8 -75+nQ2rJvAtmcLE7mAzJ5QEB8MfGELfPbpKJEHi/TUHvONyrIyml9zy1+0+fkxRx -5gXZ6Ggw64t5OpNgEc2EtJta+dua+W7gNeGFWPJ36iAHlkRIgK4PxttM7YV4hEwQ -kJ5jWmNPj/e033kPShBAnWPGFdFTG92oq9Xb0+yF4a1ff4PpQLVivj5tDzs80B5M -Khm38sQOK7qPR4IdugoJHkRtBcXQKNmeSXhYPl+0FYIFpvPd+E8DKWEOfR6LjQ9J -WBLLMvr4B8BXnoJu4uHzJln6uVWFxizfa+u9LRIrL7CjxgAupKQ6kRprgQ== +bm90QGVtYWlsLm1lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArYZ/ +1yc3bYJyEeFspQYvQQiajPPsPfQLUjCg6don+RNdZtENBoXsKvJzF3l6jVv8bIq9 +Bbv57i4MCKXJQ38tHfOUFoYU4Mb4SdAqjRwOUOKoLEf3x02aJ9nkP06s2MVVaADW +1oq/fHe+wF5o/Shp95QDLHeJvqU6CpyMjacw3BZ+KUNmmzZhNNwgMFAXw1cHRuCy +kPGzLdsE5sR+cyUJ3s3Z1oBAxXS8h/saEiA7z7dpbyQAaHkqTBIbgHJg1eZAK2qh +5unAUKcJPEuni+gCBKMaZz0o1+GBrbBcMV5fhozIdc1XHgpB4W/HanmnU1+EgY9L +zcjv1gOvksAyyjZCQQIDAQABoCMwIQYJKoZIhvcNAQkHMRQTEnBhc3N3b3JkIGNo +YWxsZW5nZTANBgkqhkiG9w0BAQsFAAOCAQEAGCO0mzEnAaOfRfLoEx9HpXZv/wSN +TAleGAf7Eliu6MbOcd6z7xGvhHapynPeNaWnBv3QruEt/pc08OdhuobqoCccwvQ1 +vqczzjoVFZQcaHaISGGEj3oQlliPgbwWZyAzBT9MLS8qlhSdUhZ0WwMDv8QPzb3/ +xBTHn8twEU5NbGi3wEFuhCInJOaIT42kTWj8USGSVZY2Nt7YdkNjSM24qLzwE23v ++awtVA2u0ftMXf+wC4C5E/d9xRz8dWbc474DuvdAWBm57KEW/KjbVEc7qaM3WVz6 +UYaP0v65benTmoOpbNPjTKxpgB/CGFgtC9VKX8+wmIC9IOmfk0FYt/6Sow== -----END CERTIFICATE REQUEST----- diff --git a/tests/ssl/ca/localhost.key b/tests/ssl/ca/localhost.key index 2cfeaf458..f10bd2604 100644 --- a/tests/ssl/ca/localhost.key +++ b/tests/ssl/ca/localhost.key @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- diff --git a/tests/test-defaults.js b/tests/test-defaults.js index ec827be68..09131a172 100644 --- a/tests/test-defaults.js +++ b/tests/test-defaults.js @@ -213,6 +213,35 @@ tape('recursive defaults', function(t) { }) }) +tape('recursive defaults requester', function(t) { + t.plan(4) + + var defaultsOne = request.defaults({}, function(options, callback) { + var headers = options.headers || {} + headers.foo = 'bar1' + options.headers = headers + + request(options, callback) + }) + , defaultsTwo = defaultsOne.defaults({}, function(options, callback) { + var headers = options.headers || {} + headers.baz = 'bar2' + options.headers = headers + + defaultsOne(options, callback) + }) + + defaultsOne.get(s.url + '/get_recursive1', function (e, r, b) { + t.equal(e, null) + t.equal(b, 'TESTING!') + }) + + defaultsTwo.get(s.url + '/get_recursive2', function (e, r, b) { + t.equal(e, null) + t.equal(b, 'TESTING!') + }) +}) + tape('test custom request handler function', function(t) { t.plan(2) @@ -237,6 +266,23 @@ tape('test custom request handler function', function(t) { }) }) +tape('test custom request handler function without options', function(t) { + t.plan(1) + + var customHandlerWithoutOptions = request.defaults(function(uri, options, callback) { + var params = request.initParams(uri, options, callback) + var headers = params.options.headers || {} + headers.x = 'y' + headers.foo = 'bar' + params.options.headers = headers + return request(params.uri, params.options, params.callback) + }) + + customHandlerWithoutOptions.get(s.url + '/get_custom', function(e, r, b) { + t.equal(e, null) + }) +}) + tape('test only setting undefined properties', function(t) { request.defaults({ method: 'post', diff --git a/tests/test-errors.js b/tests/test-errors.js index fde97fefe..bb5ab7ccc 100644 --- a/tests/test-errors.js +++ b/tests/test-errors.js @@ -77,3 +77,22 @@ tape('multipart without body 2', function(t) { }, /^Error: Body attribute missing in multipart\.$/) t.end() }) + +tape('head method with a body', function(t) { + t.throws(function() { + request(local, { + method: 'HEAD', + body: 'foo' + }) + }, /HTTP HEAD requests MUST NOT include a request body/) + t.end() +}) + +tape('head method with a body 2', function(t) { + t.throws(function() { + request.head(local, { + body: 'foo' + }) + }, /HTTP HEAD requests MUST NOT include a request body/) + t.end() +}) diff --git a/tests/test-multipart-encoding.js b/tests/test-multipart-encoding.js new file mode 100644 index 000000000..4c8383489 --- /dev/null +++ b/tests/test-multipart-encoding.js @@ -0,0 +1,149 @@ +'use strict' + +var http = require('http') + , path = require('path') + , request = require('../index') + , fs = require('fs') + , tape = require('tape') + + +var localFile = path.join(__dirname, 'unicycle.jpg') +var cases = { + // based on body type + '+array -stream': { + options: { + multipart: [{name: 'field', body: 'value'}] + }, + expected: {chunked: false} + }, + '+array +stream': { + options: { + multipart: [{name: 'file', body: null}] + }, + expected: {chunked: true} + }, + // encoding overrides body value + '+array +encoding': { + options: { + headers: {'transfer-encoding': 'chunked'}, + multipart: [{name: 'field', body: 'value'}] + }, + expected: {chunked: true} + }, + + // based on body type + '+object -stream': { + options: { + multipart: {data: [{name: 'field', body: 'value'}]} + }, + expected: {chunked: false} + }, + '+object +stream': { + options: { + multipart: {data: [{name: 'file', body: null}]} + }, + expected: {chunked: true} + }, + // encoding overrides body value + '+object +encoding': { + options: { + headers: {'transfer-encoding': 'chunked'}, + multipart: {data: [{name: 'field', body: 'value'}]} + }, + expected: {chunked: true} + }, + + // based on body type + '+object -chunked -stream': { + options: { + multipart: {chunked: false, data: [{name: 'field', body: 'value'}]} + }, + expected: {chunked: false} + }, + '+object -chunked +stream': { + options: { + multipart: {chunked: false, data: [{name: 'file', body: null}]} + }, + expected: {chunked: true} + }, + // chunked overrides body value + '+object +chunked -stream': { + options: { + multipart: {chunked: true, data: [{name: 'field', body: 'value'}]} + }, + expected: {chunked: true} + }, + // encoding overrides chunked + '+object +encoding -chunked': { + options: { + headers: {'transfer-encoding': 'chunked'}, + multipart: {chunked: false, data: [{name: 'field', body: 'value'}]} + }, + expected: {chunked: true} + } +} + +function runTest(t, test) { + + var server = http.createServer(function(req, res) { + + t.ok(req.headers['content-type'].match(/^multipart\/related; boundary=[^\s;]+$/)) + + if (test.expected.chunked) { + t.ok(req.headers['transfer-encoding'] === 'chunked') + t.notOk(req.headers['content-length']) + } else { + t.ok(req.headers['content-length']) + t.notOk(req.headers['transfer-encoding']) + } + + // temp workaround + var data = '' + req.setEncoding('utf8') + + req.on('data', function(d) { + data += d + }) + + req.on('end', function() { + // check for the fields traces + if (test.expected.chunked && data.indexOf('name: file') !== -1) { + // file + t.ok(data.indexOf('name: file') !== -1) + // check for unicycle.jpg traces + t.ok(data.indexOf('2005:06:21 01:44:12') !== -1) + } else { + // field + t.ok(data.indexOf('name: field') !== -1) + var parts = test.options.multipart.data || test.options.multipart + t.ok(data.indexOf(parts[0].body) !== -1) + } + + res.writeHead(200) + res.end() + }) + }) + + server.listen(6767, function() { + // @NOTE: multipartData properties must be set here + // so that file read stream does not leak in node v0.8 + var parts = test.options.multipart.data || test.options.multipart + if (parts[0].name === 'file') { + parts[0].body = fs.createReadStream(localFile) + } + + request.post('http://localhost:6767', test.options, function (err, res, body) { + t.equal(err, null) + t.equal(res.statusCode, 200) + server.close(function () { + t.end() + }) + }) + }) +} + +Object.keys(cases).forEach(function (name) { + tape('multipart-encoding ' + name, function(t) { + runTest(t, cases[name]) + }) +}) diff --git a/tests/test-multipart.js b/tests/test-multipart.js index cd7d659aa..dafc23805 100644 --- a/tests/test-multipart.js +++ b/tests/test-multipart.js @@ -6,11 +6,11 @@ var http = require('http') , fs = require('fs') , tape = require('tape') + function runTest(t, a) { var remoteFile = path.join(__dirname, 'googledoodle.jpg') , localFile = path.join(__dirname, 'unicycle.jpg') , multipartData = [] - , chunked = a.stream || a.chunked || a.encoding var server = http.createServer(function(req, res) { if (req.url === '/file') { @@ -19,18 +19,15 @@ function runTest(t, a) { return } - if (a.mixed) { - t.ok(req.headers['content-type'].match(/multipart\/mixed/)) - } else { - t.ok(req.headers['content-type'].match(/multipart\/related/)) - } - - if (chunked) { - t.ok(req.headers['transfer-encoding'] === 'chunked') - t.notOk(req.headers['content-length']) + if (a.header) { + if (a.header.indexOf('mixed') !== -1) { + t.ok(req.headers['content-type'].match(/^multipart\/mixed; boundary=[^\s;]+$/)) + } else { + t.ok(req.headers['content-type'] + .match(/^multipart\/related; boundary=XXX; type=text\/xml; start=""$/)) + } } else { - t.ok(req.headers['content-length']) - t.notOk(req.headers['transfer-encoding']) + t.ok(req.headers['content-type'].match(/^multipart\/related; boundary=[^\s;]+$/)) } // temp workaround @@ -42,26 +39,28 @@ function runTest(t, a) { }) req.on('end', function() { - // check for the fields' traces + // check for the fields traces // 1st field : my_field - t.ok( data.indexOf('name: my_field') !== -1 ) - t.ok( data.indexOf(multipartData[0].body) !== -1 ) + t.ok(data.indexOf('name: my_field') !== -1) + t.ok(data.indexOf(multipartData[0].body) !== -1) // 2nd field : my_buffer - t.ok( data.indexOf('name: my_buffer') !== -1 ) - t.ok( data.indexOf(multipartData[1].body) !== -1 ) - - if (chunked) { - // 3rd field : my_file - t.ok( data.indexOf('name: my_file') !== -1 ) - // check for unicycle.jpg traces - t.ok( data.indexOf('2005:06:21 01:44:12') !== -1 ) - - // 4th field : remote_file - t.ok( data.indexOf('name: remote_file') !== -1 ) - // check for http://localhost:6767/file traces - t.ok( data.indexOf('Photoshop ICC') !== -1 ) + t.ok(data.indexOf('name: my_buffer') !== -1) + t.ok(data.indexOf(multipartData[1].body) !== -1) + + // 3rd field : my_file + t.ok(data.indexOf('name: my_file') !== -1) + // check for unicycle.jpg traces + t.ok(data.indexOf('2005:06:21 01:44:12') !== -1) + + // 4th field : remote_file + t.ok(data.indexOf('name: remote_file') !== -1) + // check for http://localhost:6767/file traces + t.ok(data.indexOf('Photoshop ICC') !== -1) + + if (a.header && a.header.indexOf('mixed') !== -1) { + t.ok(data.indexOf('boundary=XXX')) } res.writeHead(200) @@ -72,33 +71,21 @@ function runTest(t, a) { server.listen(6767, function() { // @NOTE: multipartData properties must be set here so that my_file read stream does not leak in node v0.8 - multipartData = chunked - ? [ + multipartData = [ {name: 'my_field', body: 'my_value'}, {name: 'my_buffer', body: new Buffer([1, 2, 3])}, {name: 'my_file', body: fs.createReadStream(localFile)}, {name: 'remote_file', body: request('http://localhost:6767/file')} ] - : [ - {name: 'my_field', body: 'my_value'}, - {name: 'my_buffer', body: new Buffer([1, 2, 3])} - ] var reqOptions = { url: 'http://localhost:6767/upload', - headers: (function () { - var headers = {} - if (a.mixed) { - headers['content-type'] = 'multipart/mixed' - } - if (a.encoding) { - headers['transfer-encoding'] = 'chunked' - } - return headers - }()), - multipart: a.array - ? multipartData - : {chunked: a.chunked, data: multipartData} + multipart: multipartData + } + if (a.header) { + reqOptions.headers = { + 'content-type': a.header + } } if (a.json) { reqOptions.json = true @@ -111,60 +98,26 @@ function runTest(t, a) { t.end() }) }) - }) } -// array - multipart option is array -// object - multipart option is object -// encoding - headers option have transfer-encoding set to chunked -// mixed - headers option have content-type set to something different than multipart/related -// json - json option -// stream - body contains streams or not -// chunked - chunked is set when multipart is object - -// var methods = ['post', 'get'] -var cases = [ - // based on body type - {name: '+array -stream', args: {array: true, encoding: false, stream: false}}, - {name: '+array +stream', args: {array: true, encoding: false, stream: true}}, - // encoding overrides stream - {name: '+array +encoding', args: {array: true, encoding: true, stream: false}}, - - // based on body type - {name: '+object -stream', args: {object: true, encoding: false, stream: false}}, - {name: '+object +stream', args: {object: true, encoding: false, stream: true}}, - // encoding overrides stream - {name: '+object +encoding', args: {object: true, encoding: true, stream: false}}, - - // based on body type - {name: '+object -chunked -stream', args: {object: true, encoding: false, chunked: false, stream: false}}, - {name: '+object -chunked +stream', args: {object: true, encoding: false, chunked: false, stream: true}}, - // chunked overrides stream - {name: '+object +chunked -stream', args: {object: true, encoding: false, chunked: true, stream: false}}, - // chunked overrides encoding - {name: '+object +encoding -chunked', args: {object: true, encoding: true, chunked: false, stream: false}}, - // stream overrides chunked - {name: '+object +encoding -chunked +stream', args: {object: true, encoding: true, chunked: false, stream: true}} +var testHeaders = [ + null, + 'multipart/mixed', + 'multipart/related; boundary=XXX; type=text/xml; start=""' ] var suite = ['post', 'get'].forEach(function(method) { - [true, false].forEach(function(json) { - [true, false].forEach(function(mixed) { - cases.forEach(function (test) { - var name = [ - 'multipart related', method, - (json ? '+' : '-') + 'json', - (mixed ? '+' : '-') + 'mixed', - test.name - ].join(' ') - - tape(name, function(t) { - test.args.method = method - test.args.json = json - test.args.mixed = mixed - runTest(t, test.args) - }) + testHeaders.forEach(function(header) { + [true, false].forEach(function(json) { + var name = [ + 'multipart-related', method.toUpperCase(), + (header || 'default'), + (json ? '+' : '-') + 'json' + ].join(' ') + + tape(name, function(t) { + runTest(t, {method: method, header: header, json: json}) }) }) }) diff --git a/tests/test-redirect.js b/tests/test-redirect.js index d8301fb60..f5cae24f8 100644 --- a/tests/test-redirect.js +++ b/tests/test-redirect.js @@ -312,6 +312,40 @@ tape('http to https redirect', function(t) { }) }) +tape('should have the referer when following redirect by default', function(t) { + request.post({ + uri: s.url + '/temp', + jar: jar, + followAllRedirects: true, + headers: { cookie: 'foo=bar' } + }, function(err, res, body) { + t.equal(err, null) + t.equal(res.statusCode, 200) + t.end() + }) + .on('redirect',function() { + t.notEqual(this.headers.referer, undefined) + t.equal(this.headers.referer.substring(this.headers.referer.lastIndexOf('/')),'/temp_landing') + }) +}) + +tape('should not have a referer when removeRefererHeader is true', function(t) { + request.post({ + uri: s.url + '/temp', + jar: jar, + followAllRedirects: true, + removeRefererHeader: true, + headers: { cookie: 'foo=bar' } + }, function(err, res, body) { + t.equal(err, null) + t.equal(res.statusCode, 200) + t.end() + }) + .on('redirect',function() { + t.equal(this.headers.referer, undefined) + }) +}) + tape('cleanup', function(t) { s.close(function() { ss.close(function() {