@wiajs/request 3.0.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/.github/ISSUE_TEMPLATE.md +56 -0
  2. package/.github/PULL_REQUEST_TEMPLATE.md +13 -0
  3. package/.github/stale.yml +19 -0
  4. package/.swcrc +57 -0
  5. package/.travis.yml +21 -0
  6. package/CHANGELOG.md +717 -0
  7. package/CONTRIBUTING.md +81 -0
  8. package/biome.json +44 -0
  9. package/codecov.yml +2 -0
  10. package/disabled.appveyor.yml +36 -0
  11. package/dist/request.cjs +1476 -0
  12. package/dist/request.mjs +1474 -0
  13. package/examples/README.md +135 -0
  14. package/gulpfile.js +71 -0
  15. package/package.json +1 -2
  16. package/release.sh +45 -0
  17. package/tests/browser/karma.conf.js +57 -0
  18. package/tests/browser/ssl/ca.crt +14 -0
  19. package/tests/browser/ssl/server.crt +14 -0
  20. package/tests/browser/ssl/server.key +15 -0
  21. package/tests/browser/start.js +37 -0
  22. package/tests/browser/test.js +34 -0
  23. package/tests/fixtures/har.json +158 -0
  24. package/tests/googledoodle.jpg +0 -0
  25. package/tests/server.js +142 -0
  26. package/tests/squid.conf +76 -0
  27. package/tests/ssl/ca/README.md +8 -0
  28. package/tests/ssl/ca/ca.cnf +20 -0
  29. package/tests/ssl/ca/ca.crl +0 -0
  30. package/tests/ssl/ca/ca.crt +17 -0
  31. package/tests/ssl/ca/ca.csr +13 -0
  32. package/tests/ssl/ca/ca.key +18 -0
  33. package/tests/ssl/ca/ca.srl +1 -0
  34. package/tests/ssl/ca/client-enc.key +30 -0
  35. package/tests/ssl/ca/client.cnf +20 -0
  36. package/tests/ssl/ca/client.crt +20 -0
  37. package/tests/ssl/ca/client.csr +18 -0
  38. package/tests/ssl/ca/client.key +27 -0
  39. package/tests/ssl/ca/gen-all-certs.sh +6 -0
  40. package/tests/ssl/ca/gen-client.sh +25 -0
  41. package/tests/ssl/ca/gen-localhost.sh +22 -0
  42. package/tests/ssl/ca/gen-server.sh +18 -0
  43. package/tests/ssl/ca/localhost.cnf +20 -0
  44. package/tests/ssl/ca/localhost.crt +20 -0
  45. package/tests/ssl/ca/localhost.csr +18 -0
  46. package/tests/ssl/ca/localhost.js +33 -0
  47. package/tests/ssl/ca/localhost.key +27 -0
  48. package/tests/ssl/ca/server.cnf +19 -0
  49. package/tests/ssl/ca/server.crt +25 -0
  50. package/tests/ssl/ca/server.csr +29 -0
  51. package/tests/ssl/ca/server.js +34 -0
  52. package/tests/ssl/ca/server.key +51 -0
  53. package/tests/ssl/npm-ca.crt +16 -0
  54. package/tests/ssl/test.crt +15 -0
  55. package/tests/ssl/test.key +15 -0
  56. package/tests/test-agent.js +102 -0
  57. package/tests/test-agentOptions.js +51 -0
  58. package/tests/test-api.js +33 -0
  59. package/tests/test-aws.js +123 -0
  60. package/tests/test-baseUrl.js +133 -0
  61. package/tests/test-basic-auth.js +221 -0
  62. package/tests/test-bearer-auth.js +187 -0
  63. package/tests/test-body.js +154 -0
  64. package/tests/test-cookies.js +130 -0
  65. package/tests/test-defaults.js +340 -0
  66. package/tests/test-digest-auth.js +232 -0
  67. package/tests/test-emptyBody.js +56 -0
  68. package/tests/test-errors.js +108 -0
  69. package/tests/test-event-forwarding.js +39 -0
  70. package/tests/test-follow-all-303.js +45 -0
  71. package/tests/test-follow-all.js +57 -0
  72. package/tests/test-form-data-error.js +85 -0
  73. package/tests/test-form-data.js +133 -0
  74. package/tests/test-form-urlencoded.js +73 -0
  75. package/tests/test-form.js +101 -0
  76. package/tests/test-gzip.js +296 -0
  77. package/tests/test-har.js +175 -0
  78. package/tests/test-hawk.js +187 -0
  79. package/tests/test-headers.js +305 -0
  80. package/tests/test-http-signature.js +110 -0
  81. package/tests/test-httpModule.js +112 -0
  82. package/tests/test-https.js +116 -0
  83. package/tests/test-isUrl.js +120 -0
  84. package/tests/test-json-request.js +117 -0
  85. package/tests/test-localAddress.js +49 -0
  86. package/tests/test-multipart-encoding.js +147 -0
  87. package/tests/test-multipart.js +129 -0
  88. package/tests/test-node-debug.js +95 -0
  89. package/tests/test-oauth.js +721 -0
  90. package/tests/test-onelineproxy.js +61 -0
  91. package/tests/test-option-reuse.js +54 -0
  92. package/tests/test-options-convenience-method.js +52 -0
  93. package/tests/test-params.js +101 -0
  94. package/tests/test-piped-redirect.js +55 -0
  95. package/tests/test-pipes.js +383 -0
  96. package/tests/test-pool.js +148 -0
  97. package/tests/test-promise.js +53 -0
  98. package/tests/test-proxy-connect.js +80 -0
  99. package/tests/test-proxy.js +304 -0
  100. package/tests/test-qs.js +135 -0
  101. package/tests/test-redirect-auth.js +131 -0
  102. package/tests/test-redirect-complex.js +93 -0
  103. package/tests/test-redirect.js +449 -0
  104. package/tests/test-rfc3986.js +106 -0
  105. package/tests/test-stream.js +36 -0
  106. package/tests/test-timeout.js +260 -0
  107. package/tests/test-timing.js +147 -0
  108. package/tests/test-toJSON.js +45 -0
  109. package/tests/test-tunnel.js +466 -0
  110. package/tests/test-unix.js +74 -0
  111. package/tests/unicycle.jpg +0 -0
  112. package/request.js +0 -1553
  113. package/src/ZlibTransform.js +0 -27
  114. package/src/caseless.js +0 -118
  115. package/src/index.js +0 -122
  116. package/src/request.js +0 -967
  117. package/src/utils.js +0 -274
@@ -0,0 +1,721 @@
1
+ 'use strict'
2
+
3
+ var oauth = require('oauth-sign')
4
+ var qs = require('querystring')
5
+ var fs = require('fs')
6
+ var path = require('path')
7
+ var request = require('../index')
8
+ var tape = require('tape')
9
+ var http = require('http')
10
+
11
+ function getSignature (r) {
12
+ var sign
13
+ r.headers.Authorization.slice('OAuth '.length).replace(/, /g, ',').split(',').forEach(function (v) {
14
+ if (v.slice(0, 'oauth_signature="'.length) === 'oauth_signature="') {
15
+ sign = v.slice('oauth_signature="'.length, -1)
16
+ }
17
+ })
18
+ return decodeURIComponent(sign)
19
+ }
20
+
21
+ // Tests from Twitter documentation https://dev.twitter.com/docs/auth/oauth
22
+
23
+ var hmacsign = oauth.hmacsign
24
+ var hmacsign256 = oauth.hmacsign256
25
+ var rsasign = oauth.rsasign
26
+ var rsaPrivatePEM = fs.readFileSync(path.join(__dirname, 'ssl', 'test.key'))
27
+ var reqsign
28
+ var reqsign256
29
+ var reqsignRSA
30
+ var accsign
31
+ var accsign256
32
+ var accsignRSA
33
+ var upsign
34
+ var upsign256
35
+ var upsignRSA
36
+
37
+ tape('reqsign', function (t) {
38
+ reqsign = hmacsign('POST', 'https://api.twitter.com/oauth/request_token',
39
+ { oauth_callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11',
40
+ oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g',
41
+ oauth_nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk',
42
+ oauth_signature_method: 'HMAC-SHA1',
43
+ oauth_timestamp: '1272323042',
44
+ oauth_version: '1.0'
45
+ }, 'MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98')
46
+
47
+ t.equal(reqsign, '8wUi7m5HFQy76nowoCThusfgB+Q=')
48
+ t.end()
49
+ })
50
+
51
+ tape('reqsign256', function (t) {
52
+ reqsign256 = hmacsign256('POST', 'https://api.twitter.com/oauth/request_token',
53
+ { oauth_callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11',
54
+ oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g',
55
+ oauth_nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk',
56
+ oauth_signature_method: 'HMAC-SHA256',
57
+ oauth_timestamp: '1272323042',
58
+ oauth_version: '1.0'
59
+ }, 'MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98')
60
+
61
+ t.equal(reqsign256, 'N0KBpiPbuPIMx2B77eIg7tNfGNF81iq3bcO9RO6lH+k=')
62
+ t.end()
63
+ })
64
+
65
+ tape('reqsignRSA', function (t) {
66
+ reqsignRSA = rsasign('POST', 'https://api.twitter.com/oauth/request_token',
67
+ { oauth_callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11',
68
+ oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g',
69
+ oauth_nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk',
70
+ oauth_signature_method: 'RSA-SHA1',
71
+ oauth_timestamp: '1272323042',
72
+ oauth_version: '1.0'
73
+ }, rsaPrivatePEM, 'this parameter is not used for RSA signing')
74
+
75
+ t.equal(reqsignRSA, 'MXdzEnIrQco3ACPoVWxCwv5pxYrm5MFRXbsP3LfRV+zfcRr+WMp/dOPS/3r+Wcb+17Z2IK3uJ8dMHfzb5LiDNCTUIj7SWBrbxOpy3Y6SA6z3vcrtjSekkTHLek1j+mzxOi3r3fkbYaNwjHx3PyoFSazbEstnkQQotbITeFt5FBE=')
76
+ t.end()
77
+ })
78
+
79
+ tape('accsign', function (t) {
80
+ accsign = hmacsign('POST', 'https://api.twitter.com/oauth/access_token',
81
+ { oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g',
82
+ oauth_nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8',
83
+ oauth_signature_method: 'HMAC-SHA1',
84
+ oauth_token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc',
85
+ oauth_timestamp: '1272323047',
86
+ oauth_verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY',
87
+ oauth_version: '1.0'
88
+ }, 'MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98', 'x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA')
89
+
90
+ t.equal(accsign, 'PUw/dHA4fnlJYM6RhXk5IU/0fCc=')
91
+ t.end()
92
+ })
93
+
94
+ tape('accsign256', function (t) {
95
+ accsign256 = hmacsign256('POST', 'https://api.twitter.com/oauth/access_token',
96
+ { oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g',
97
+ oauth_nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8',
98
+ oauth_signature_method: 'HMAC-SHA256',
99
+ oauth_token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc',
100
+ oauth_timestamp: '1272323047',
101
+ oauth_verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY',
102
+ oauth_version: '1.0'
103
+ }, 'MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98', 'x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA')
104
+
105
+ t.equal(accsign256, 'y7S9eUhA0tC9/YfRzCPqkg3/bUdYRDpZ93Xi51AvhjQ=')
106
+ t.end()
107
+ })
108
+
109
+ tape('accsignRSA', function (t) {
110
+ accsignRSA = rsasign('POST', 'https://api.twitter.com/oauth/access_token',
111
+ { oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g',
112
+ oauth_nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8',
113
+ oauth_signature_method: 'RSA-SHA1',
114
+ oauth_token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc',
115
+ oauth_timestamp: '1272323047',
116
+ oauth_verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY',
117
+ oauth_version: '1.0'
118
+ }, rsaPrivatePEM)
119
+
120
+ t.equal(accsignRSA, 'gZrMPexdgGMVUl9H6RxK0MbR6Db8tzf2kIIj52kOrDFcMgh4BunMBgUZAO1msUwz6oqZIvkVqyfyDAOP2wIrpYem0mBg3vqwPIroSE1AlUWo+TtQxOTuqrU+3kDcXpdvJe7CAX5hUx9Np/iGRqaCcgByqb9DaCcQ9ViQ+0wJiXI=')
121
+ t.end()
122
+ })
123
+
124
+ tape('upsign', function (t) {
125
+ upsign = hmacsign('POST', 'http://api.twitter.com/1/statuses/update.json',
126
+ { oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g',
127
+ oauth_nonce: 'oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y',
128
+ oauth_signature_method: 'HMAC-SHA1',
129
+ oauth_token: '819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw',
130
+ oauth_timestamp: '1272325550',
131
+ oauth_version: '1.0',
132
+ status: 'setting up my twitter 私のさえずりを設定する'
133
+ }, 'MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98', 'J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA')
134
+
135
+ t.equal(upsign, 'yOahq5m0YjDDjfjxHaXEsW9D+X0=')
136
+ t.end()
137
+ })
138
+
139
+ tape('upsign256', function (t) {
140
+ upsign256 = hmacsign256('POST', 'http://api.twitter.com/1/statuses/update.json',
141
+ { oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g',
142
+ oauth_nonce: 'oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y',
143
+ oauth_signature_method: 'HMAC-SHA256',
144
+ oauth_token: '819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw',
145
+ oauth_timestamp: '1272325550',
146
+ oauth_version: '1.0',
147
+ status: 'setting up my twitter 私のさえずりを設定する'
148
+ }, 'MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98', 'J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA')
149
+
150
+ t.equal(upsign256, 'xYhKjozxc3NYef7C26WU+gORdhEURdZRxSDzRttEKH0=')
151
+ t.end()
152
+ })
153
+
154
+ tape('upsignRSA', function (t) {
155
+ upsignRSA = rsasign('POST', 'http://api.twitter.com/1/statuses/update.json',
156
+ { oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g',
157
+ oauth_nonce: 'oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y',
158
+ oauth_signature_method: 'RSA-SHA1',
159
+ oauth_token: '819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw',
160
+ oauth_timestamp: '1272325550',
161
+ oauth_version: '1.0',
162
+ status: 'setting up my twitter 私のさえずりを設定する'
163
+ }, rsaPrivatePEM)
164
+
165
+ t.equal(upsignRSA, 'fF4G9BNzDxPu/htctzh9CWzGhtXo9DYYl+ZyRO1/QNOhOZPqnWVUOT+CGUKxmAeJSzLKMAH8y/MFSHI0lzihqwgfZr7nUhTx6kH7lUChcVasr+TZ4qPqvGGEhfJ8Av8D5dF5fytfCSzct62uONU0iHYVqainP+zefk1K7Ptb6hI=')
166
+ t.end()
167
+ })
168
+
169
+ tape('rsign', function (t) {
170
+ var rsign = request.post(
171
+ { url: 'https://api.twitter.com/oauth/request_token',
172
+ oauth: { callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11',
173
+ consumer_key: 'GDdmIQH6jhtmLUypg82g',
174
+ nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk',
175
+ timestamp: '1272323042',
176
+ version: '1.0',
177
+ consumer_secret: 'MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98'
178
+ }
179
+ })
180
+
181
+ process.nextTick(function () {
182
+ t.equal(reqsign, getSignature(rsign))
183
+ rsign.abort()
184
+ t.end()
185
+ })
186
+ })
187
+
188
+ tape('rsign_rsa', function (t) {
189
+ var rsignRSA = request.post(
190
+ { url: 'https://api.twitter.com/oauth/request_token',
191
+ oauth: { callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11',
192
+ consumer_key: 'GDdmIQH6jhtmLUypg82g',
193
+ nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk',
194
+ timestamp: '1272323042',
195
+ version: '1.0',
196
+ private_key: rsaPrivatePEM,
197
+ signature_method: 'RSA-SHA1'
198
+ }
199
+ })
200
+
201
+ process.nextTick(function () {
202
+ t.equal(reqsignRSA, getSignature(rsignRSA))
203
+ rsignRSA.abort()
204
+ t.end()
205
+ })
206
+ })
207
+
208
+ tape('raccsign', function (t) {
209
+ var raccsign = request.post(
210
+ { url: 'https://api.twitter.com/oauth/access_token',
211
+ oauth: { consumer_key: 'GDdmIQH6jhtmLUypg82g',
212
+ nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8',
213
+ signature_method: 'HMAC-SHA1',
214
+ token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc',
215
+ timestamp: '1272323047',
216
+ verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY',
217
+ version: '1.0',
218
+ consumer_secret: 'MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98',
219
+ token_secret: 'x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA'
220
+ }
221
+ })
222
+
223
+ process.nextTick(function () {
224
+ t.equal(accsign, getSignature(raccsign))
225
+ raccsign.abort()
226
+ t.end()
227
+ })
228
+ })
229
+
230
+ tape('raccsignRSA', function (t) {
231
+ var raccsignRSA = request.post(
232
+ { url: 'https://api.twitter.com/oauth/access_token',
233
+ oauth: { consumer_key: 'GDdmIQH6jhtmLUypg82g',
234
+ nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8',
235
+ signature_method: 'RSA-SHA1',
236
+ token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc',
237
+ timestamp: '1272323047',
238
+ verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY',
239
+ version: '1.0',
240
+ private_key: rsaPrivatePEM,
241
+ token_secret: 'x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA'
242
+ }
243
+ })
244
+
245
+ process.nextTick(function () {
246
+ t.equal(accsignRSA, getSignature(raccsignRSA))
247
+ raccsignRSA.abort()
248
+ t.end()
249
+ })
250
+ })
251
+
252
+ tape('rupsign', function (t) {
253
+ var rupsign = request.post(
254
+ { url: 'http://api.twitter.com/1/statuses/update.json',
255
+ oauth: { consumer_key: 'GDdmIQH6jhtmLUypg82g',
256
+ nonce: 'oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y',
257
+ signature_method: 'HMAC-SHA1',
258
+ token: '819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw',
259
+ timestamp: '1272325550',
260
+ version: '1.0',
261
+ consumer_secret: 'MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98',
262
+ token_secret: 'J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA'
263
+ },
264
+ form: {status: 'setting up my twitter 私のさえずりを設定する'}
265
+ })
266
+ process.nextTick(function () {
267
+ t.equal(upsign, getSignature(rupsign))
268
+ rupsign.abort()
269
+ t.end()
270
+ })
271
+ })
272
+
273
+ tape('rupsignRSA', function (t) {
274
+ var rupsignRSA = request.post(
275
+ { url: 'http://api.twitter.com/1/statuses/update.json',
276
+ oauth: { consumer_key: 'GDdmIQH6jhtmLUypg82g',
277
+ nonce: 'oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y',
278
+ signature_method: 'RSA-SHA1',
279
+ token: '819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw',
280
+ timestamp: '1272325550',
281
+ version: '1.0',
282
+ private_key: rsaPrivatePEM,
283
+ token_secret: 'J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA'
284
+ },
285
+ form: {status: 'setting up my twitter 私のさえずりを設定する'}
286
+ })
287
+ process.nextTick(function () {
288
+ t.equal(upsignRSA, getSignature(rupsignRSA))
289
+ rupsignRSA.abort()
290
+ t.end()
291
+ })
292
+ })
293
+
294
+ tape('rfc5849 example', function (t) {
295
+ var rfc5849 = request.post(
296
+ { url: 'http://example.com/request?b5=%3D%253D&a3=a&c%40=&a2=r%20b',
297
+ oauth: { consumer_key: '9djdj82h48djs9d2',
298
+ nonce: '7d8f3e4a',
299
+ signature_method: 'HMAC-SHA1',
300
+ token: 'kkk9d7dh3k39sjv7',
301
+ timestamp: '137131201',
302
+ consumer_secret: 'j49sk3j29djd',
303
+ token_secret: 'dh893hdasih9',
304
+ realm: 'Example'
305
+ },
306
+ form: {
307
+ c2: '',
308
+ a3: '2 q'
309
+ }
310
+ })
311
+
312
+ process.nextTick(function () {
313
+ // different signature in rfc5849 because request sets oauth_version by default
314
+ t.equal('OB33pYjWAnf+xtOHN4Gmbdil168=', getSignature(rfc5849))
315
+ rfc5849.abort()
316
+ t.end()
317
+ })
318
+ })
319
+
320
+ tape('rfc5849 RSA example', function (t) {
321
+ var rfc5849RSA = request.post(
322
+ { url: 'http://example.com/request?b5=%3D%253D&a3=a&c%40=&a2=r%20b',
323
+ oauth: { consumer_key: '9djdj82h48djs9d2',
324
+ nonce: '7d8f3e4a',
325
+ signature_method: 'RSA-SHA1',
326
+ token: 'kkk9d7dh3k39sjv7',
327
+ timestamp: '137131201',
328
+ private_key: rsaPrivatePEM,
329
+ token_secret: 'dh893hdasih9',
330
+ realm: 'Example'
331
+ },
332
+ form: {
333
+ c2: '',
334
+ a3: '2 q'
335
+ }
336
+ })
337
+
338
+ process.nextTick(function () {
339
+ // different signature in rfc5849 because request sets oauth_version by default
340
+ t.equal('ThNYfZhYogcAU6rWgI3ZFlPEhoIXHMZcuMzl+jykJZW/ab+AxyefS03dyd64CclIZ0u8JEW64TQ5SHthoQS8aM8qir4t+t88lRF3LDkD2KtS1krgCZTUQxkDL5BO5pxsqAQ2Zfdcrzaxb6VMGD1Hf+Pno+fsHQo/UUKjq4V3RMo=', getSignature(rfc5849RSA))
341
+ rfc5849RSA.abort()
342
+ t.end()
343
+ })
344
+ })
345
+
346
+ tape('plaintext signature method', function (t) {
347
+ var plaintext = request.post(
348
+ { url: 'https://dummy.com',
349
+ oauth: { consumer_secret: 'consumer_secret',
350
+ token_secret: 'token_secret',
351
+ signature_method: 'PLAINTEXT'
352
+ }
353
+ })
354
+
355
+ process.nextTick(function () {
356
+ t.equal('consumer_secret&token_secret', getSignature(plaintext))
357
+ plaintext.abort()
358
+ t.end()
359
+ })
360
+ })
361
+
362
+ tape('invalid transport_method', function (t) {
363
+ t.throws(
364
+ function () {
365
+ request.post(
366
+ { url: 'http://example.com/',
367
+ oauth: { transport_method: 'headerquery'
368
+ }
369
+ })
370
+ }, /transport_method invalid/)
371
+ t.end()
372
+ })
373
+
374
+ tape("invalid method while using transport_method 'body'", function (t) {
375
+ t.throws(
376
+ function () {
377
+ request.get(
378
+ { url: 'http://example.com/',
379
+ headers: { 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8' },
380
+ oauth: { transport_method: 'body'
381
+ }
382
+ })
383
+ }, /requires POST/)
384
+ t.end()
385
+ })
386
+
387
+ tape("invalid content-type while using transport_method 'body'", function (t) {
388
+ t.throws(
389
+ function () {
390
+ request.post(
391
+ { url: 'http://example.com/',
392
+ headers: { 'content-type': 'application/json; charset=UTF-8' },
393
+ oauth: { transport_method: 'body'
394
+ }
395
+ })
396
+ }, /requires POST/)
397
+ t.end()
398
+ })
399
+
400
+ tape('query transport_method', function (t) {
401
+ var r = request.post(
402
+ { url: 'https://api.twitter.com/oauth/access_token',
403
+ oauth: { consumer_key: 'GDdmIQH6jhtmLUypg82g',
404
+ nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8',
405
+ signature_method: 'HMAC-SHA1',
406
+ token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc',
407
+ timestamp: '1272323047',
408
+ verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY',
409
+ version: '1.0',
410
+ consumer_secret: 'MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98',
411
+ token_secret: 'x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA',
412
+ transport_method: 'query'
413
+ }
414
+ })
415
+
416
+ process.nextTick(function () {
417
+ t.notOk(r.headers.Authorization, "oauth Authorization header should not be present with transport_method 'query'")
418
+ t.equal(r.uri.path, r.path, 'r.uri.path should equal r.path')
419
+ t.ok(r.path.match(/^\/oauth\/access_token\?/), 'path should contain path + query')
420
+ t.deepEqual(qs.parse(r.uri.query),
421
+ { oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g',
422
+ oauth_nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8',
423
+ oauth_signature_method: 'HMAC-SHA1',
424
+ oauth_timestamp: '1272323047',
425
+ oauth_token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc',
426
+ oauth_verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY',
427
+ oauth_version: '1.0',
428
+ oauth_signature: accsign })
429
+ r.abort()
430
+ t.end()
431
+ })
432
+ })
433
+
434
+ tape('query transport_method + form option + url params', function (t) {
435
+ var r = request.post(
436
+ { url: 'http://example.com/request?b5=%3D%253D&a3=a&c%40=&a2=r%20b',
437
+ oauth: { consumer_key: '9djdj82h48djs9d2',
438
+ nonce: '7d8f3e4a',
439
+ signature_method: 'HMAC-SHA1',
440
+ token: 'kkk9d7dh3k39sjv7',
441
+ timestamp: '137131201',
442
+ consumer_secret: 'j49sk3j29djd',
443
+ token_secret: 'dh893hdasih9',
444
+ realm: 'Example',
445
+ transport_method: 'query'
446
+ },
447
+ form: {
448
+ c2: '',
449
+ a3: '2 q'
450
+ }
451
+ })
452
+
453
+ process.nextTick(function () {
454
+ t.notOk(r.headers.Authorization, "oauth Authorization header should not be present with transport_method 'query'")
455
+ t.equal(r.uri.path, r.path, 'r.uri.path should equal r.path')
456
+ t.ok(r.path.match(/^\/request\?/), 'path should contain path + query')
457
+ t.deepEqual(qs.parse(r.uri.query),
458
+ { b5: '=%3D',
459
+ a3: 'a',
460
+ 'c@': '',
461
+ a2: 'r b',
462
+ realm: 'Example',
463
+ oauth_consumer_key: '9djdj82h48djs9d2',
464
+ oauth_nonce: '7d8f3e4a',
465
+ oauth_signature_method: 'HMAC-SHA1',
466
+ oauth_timestamp: '137131201',
467
+ oauth_token: 'kkk9d7dh3k39sjv7',
468
+ oauth_version: '1.0',
469
+ oauth_signature: 'OB33pYjWAnf+xtOHN4Gmbdil168=' })
470
+ r.abort()
471
+ t.end()
472
+ })
473
+ })
474
+
475
+ tape('query transport_method + qs option + url params', function (t) {
476
+ var r = request.post(
477
+ { url: 'http://example.com/request?a2=r%20b',
478
+ oauth: { consumer_key: '9djdj82h48djs9d2',
479
+ nonce: '7d8f3e4a',
480
+ signature_method: 'HMAC-SHA1',
481
+ token: 'kkk9d7dh3k39sjv7',
482
+ timestamp: '137131201',
483
+ consumer_secret: 'j49sk3j29djd',
484
+ token_secret: 'dh893hdasih9',
485
+ realm: 'Example',
486
+ transport_method: 'query'
487
+ },
488
+ qs: {
489
+ b5: '=%3D',
490
+ a3: ['a', '2 q'],
491
+ 'c@': '',
492
+ c2: ''
493
+ }
494
+ })
495
+
496
+ process.nextTick(function () {
497
+ t.notOk(r.headers.Authorization, "oauth Authorization header should not be present with transport_method 'query'")
498
+ t.equal(r.uri.path, r.path, 'r.uri.path should equal r.path')
499
+ t.ok(r.path.match(/^\/request\?/), 'path should contain path + query')
500
+ t.deepEqual(qs.parse(r.uri.query),
501
+ { a2: 'r b',
502
+ b5: '=%3D',
503
+ 'a3[0]': 'a',
504
+ 'a3[1]': '2 q',
505
+ 'c@': '',
506
+ c2: '',
507
+ realm: 'Example',
508
+ oauth_consumer_key: '9djdj82h48djs9d2',
509
+ oauth_nonce: '7d8f3e4a',
510
+ oauth_signature_method: 'HMAC-SHA1',
511
+ oauth_timestamp: '137131201',
512
+ oauth_token: 'kkk9d7dh3k39sjv7',
513
+ oauth_version: '1.0',
514
+ oauth_signature: 'OB33pYjWAnf+xtOHN4Gmbdil168=' })
515
+ r.abort()
516
+ t.end()
517
+ })
518
+ })
519
+
520
+ tape('body transport_method', function (t) {
521
+ var r = request.post(
522
+ { url: 'https://api.twitter.com/oauth/access_token',
523
+ headers: { 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8' },
524
+ oauth: { consumer_key: 'GDdmIQH6jhtmLUypg82g',
525
+ nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8',
526
+ signature_method: 'HMAC-SHA1',
527
+ token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc',
528
+ timestamp: '1272323047',
529
+ verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY',
530
+ version: '1.0',
531
+ consumer_secret: 'MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98',
532
+ token_secret: 'x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA',
533
+ transport_method: 'body'
534
+ }
535
+ })
536
+
537
+ process.nextTick(function () {
538
+ t.notOk(r.headers.Authorization, "oauth Authorization header should not be present with transport_method 'body'")
539
+ t.deepEqual(qs.parse(r.body),
540
+ { oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g',
541
+ oauth_nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8',
542
+ oauth_signature_method: 'HMAC-SHA1',
543
+ oauth_timestamp: '1272323047',
544
+ oauth_token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc',
545
+ oauth_verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY',
546
+ oauth_version: '1.0',
547
+ oauth_signature: accsign })
548
+ r.abort()
549
+ t.end()
550
+ })
551
+ })
552
+
553
+ tape('body transport_method + form option + url params', function (t) {
554
+ var r = request.post(
555
+ { url: 'http://example.com/request?b5=%3D%253D&a3=a&c%40=&a2=r%20b',
556
+ oauth: { consumer_key: '9djdj82h48djs9d2',
557
+ nonce: '7d8f3e4a',
558
+ signature_method: 'HMAC-SHA1',
559
+ token: 'kkk9d7dh3k39sjv7',
560
+ timestamp: '137131201',
561
+ consumer_secret: 'j49sk3j29djd',
562
+ token_secret: 'dh893hdasih9',
563
+ realm: 'Example',
564
+ transport_method: 'body'
565
+ },
566
+ form: {
567
+ c2: '',
568
+ a3: '2 q'
569
+ }
570
+ })
571
+
572
+ process.nextTick(function () {
573
+ t.notOk(r.headers.Authorization, "oauth Authorization header should not be present with transport_method 'body'")
574
+ t.deepEqual(qs.parse(r.body),
575
+ { c2: '',
576
+ a3: '2 q',
577
+ realm: 'Example',
578
+ oauth_consumer_key: '9djdj82h48djs9d2',
579
+ oauth_nonce: '7d8f3e4a',
580
+ oauth_signature_method: 'HMAC-SHA1',
581
+ oauth_timestamp: '137131201',
582
+ oauth_token: 'kkk9d7dh3k39sjv7',
583
+ oauth_version: '1.0',
584
+ oauth_signature: 'OB33pYjWAnf+xtOHN4Gmbdil168=' })
585
+ r.abort()
586
+ t.end()
587
+ })
588
+ })
589
+
590
+ tape('body_hash manually set', function (t) {
591
+ var r = request.post(
592
+ { url: 'http://example.com',
593
+ oauth: { consumer_secret: 'consumer_secret',
594
+ body_hash: 'ManuallySetHash'
595
+ },
596
+ json: {foo: 'bar'}
597
+ })
598
+
599
+ process.nextTick(function () {
600
+ var hash = r.headers.Authorization.replace(/.*oauth_body_hash="([^"]+)".*/, '$1')
601
+ t.equal('ManuallySetHash', hash)
602
+ r.abort()
603
+ t.end()
604
+ })
605
+ })
606
+
607
+ tape('body_hash automatically built for string', function (t) {
608
+ var r = request.post(
609
+ { url: 'http://example.com',
610
+ oauth: { consumer_secret: 'consumer_secret',
611
+ body_hash: true
612
+ },
613
+ body: 'Hello World!'
614
+ })
615
+
616
+ process.nextTick(function () {
617
+ var hash = r.headers.Authorization.replace(/.*oauth_body_hash="([^"]+)".*/, '$1')
618
+ // from https://tools.ietf.org/id/draft-eaton-oauth-bodyhash-00.html#anchor15
619
+ t.equal('Lve95gjOVATpfV8EL5X4nxwjKHE%3D', hash)
620
+ r.abort()
621
+ t.end()
622
+ })
623
+ })
624
+
625
+ tape('body_hash automatically built for JSON', function (t) {
626
+ var r = request.post(
627
+ { url: 'http://example.com',
628
+ oauth: { consumer_secret: 'consumer_secret',
629
+ body_hash: true
630
+ },
631
+ json: {foo: 'bar'}
632
+ })
633
+
634
+ process.nextTick(function () {
635
+ var hash = r.headers.Authorization.replace(/.*oauth_body_hash="([^"]+)".*/, '$1')
636
+ t.equal('pedE0BZFQNM7HX6mFsKPL6l%2BdUo%3D', hash)
637
+ r.abort()
638
+ t.end()
639
+ })
640
+ })
641
+
642
+ tape('body_hash PLAINTEXT signature_method', function (t) {
643
+ t.throws(function () {
644
+ request.post(
645
+ { url: 'http://example.com',
646
+ oauth: { consumer_secret: 'consumer_secret',
647
+ body_hash: true,
648
+ signature_method: 'PLAINTEXT'
649
+ },
650
+ json: {foo: 'bar'}
651
+ })
652
+ }, /oauth: PLAINTEXT signature_method not supported with body_hash signing/)
653
+ t.end()
654
+ })
655
+
656
+ tape('refresh oauth_nonce on redirect', function (t) {
657
+ var oauthNonce1
658
+ var oauthNonce2
659
+ var url
660
+ var s = http.createServer(function (req, res) {
661
+ if (req.url === '/redirect') {
662
+ oauthNonce1 = req.headers.authorization.replace(/.*oauth_nonce="([^"]+)".*/, '$1')
663
+ res.writeHead(302, {location: url + '/response'})
664
+ res.end()
665
+ } else if (req.url === '/response') {
666
+ oauthNonce2 = req.headers.authorization.replace(/.*oauth_nonce="([^"]+)".*/, '$1')
667
+ res.writeHead(200, {'content-type': 'text/plain'})
668
+ res.end()
669
+ }
670
+ })
671
+ s.listen(0, function () {
672
+ url = 'http://localhost:' + this.address().port
673
+ request.get(
674
+ { url: url + '/redirect',
675
+ oauth: { consumer_key: 'consumer_key',
676
+ consumer_secret: 'consumer_secret',
677
+ token: 'token',
678
+ token_secret: 'token_secret'
679
+ }
680
+ }, function (err, res, body) {
681
+ t.equal(err, null)
682
+ t.notEqual(oauthNonce1, oauthNonce2)
683
+ s.close(function () {
684
+ t.end()
685
+ })
686
+ })
687
+ })
688
+ })
689
+
690
+ tape('no credentials on external redirect', function (t) {
691
+ var s2 = http.createServer(function (req, res) {
692
+ res.writeHead(200, {'content-type': 'text/plain'})
693
+ res.end()
694
+ })
695
+ var s1 = http.createServer(function (req, res) {
696
+ res.writeHead(302, {location: s2.url})
697
+ res.end()
698
+ })
699
+ s1.listen(0, function () {
700
+ s1.url = 'http://localhost:' + this.address().port
701
+ s2.listen(0, function () {
702
+ s2.url = 'http://127.0.0.1:' + this.address().port
703
+ request.get(
704
+ { url: s1.url,
705
+ oauth: { consumer_key: 'consumer_key',
706
+ consumer_secret: 'consumer_secret',
707
+ token: 'token',
708
+ token_secret: 'token_secret'
709
+ }
710
+ }, function (err, res, body) {
711
+ t.equal(err, null)
712
+ t.equal(res.request.headers.Authorization, undefined)
713
+ s1.close(function () {
714
+ s2.close(function () {
715
+ t.end()
716
+ })
717
+ })
718
+ })
719
+ })
720
+ })
721
+ })