api-web-request-spec.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. const assert = require('assert')
  2. const http = require('http')
  3. const qs = require('querystring')
  4. const remote = require('electron').remote
  5. const session = remote.session
  6. /* The whole webRequest API doesn't use standard callbacks */
  7. /* eslint-disable standard/no-callback-literal */
  8. describe('webRequest module', () => {
  9. const ses = session.defaultSession
  10. const server = http.createServer((req, res) => {
  11. if (req.url === '/serverRedirect') {
  12. res.statusCode = 301
  13. res.setHeader('Location', 'http://' + req.rawHeaders[1])
  14. res.end()
  15. } else {
  16. res.setHeader('Custom', ['Header'])
  17. let content = req.url
  18. if (req.headers.accept === '*/*;test/header') {
  19. content += 'header/received'
  20. }
  21. res.end(content)
  22. }
  23. })
  24. let defaultURL = null
  25. before((done) => {
  26. server.listen(0, '127.0.0.1', () => {
  27. const port = server.address().port
  28. defaultURL = 'http://127.0.0.1:' + port + '/'
  29. done()
  30. })
  31. })
  32. after(() => {
  33. server.close()
  34. })
  35. describe('webRequest.onBeforeRequest', () => {
  36. afterEach(() => {
  37. ses.webRequest.onBeforeRequest(null)
  38. })
  39. it('can cancel the request', (done) => {
  40. ses.webRequest.onBeforeRequest((details, callback) => {
  41. callback({
  42. cancel: true
  43. })
  44. })
  45. $.ajax({
  46. url: defaultURL,
  47. success: () => {
  48. done('unexpected success')
  49. },
  50. error: () => {
  51. done()
  52. }
  53. })
  54. })
  55. it('can filter URLs', (done) => {
  56. const filter = { urls: [defaultURL + 'filter/*'] }
  57. ses.webRequest.onBeforeRequest(filter, (details, callback) => {
  58. callback({cancel: true})
  59. })
  60. $.ajax({
  61. url: `${defaultURL}nofilter/test`,
  62. success: (data) => {
  63. assert.equal(data, '/nofilter/test')
  64. $.ajax({
  65. url: `${defaultURL}filter/test`,
  66. success: () => done('unexpected success'),
  67. error: () => done()
  68. })
  69. },
  70. error: (xhr, errorType) => done(errorType)
  71. })
  72. })
  73. it('receives details object', (done) => {
  74. ses.webRequest.onBeforeRequest((details, callback) => {
  75. assert.equal(typeof details.id, 'number')
  76. assert.equal(typeof details.timestamp, 'number')
  77. assert.equal(typeof details.webContentsId, 'number')
  78. assert.equal(details.url, defaultURL)
  79. assert.equal(details.method, 'GET')
  80. assert.equal(details.resourceType, 'xhr')
  81. assert(!details.uploadData)
  82. callback({})
  83. })
  84. $.ajax({
  85. url: defaultURL,
  86. success: (data) => {
  87. assert.equal(data, '/')
  88. done()
  89. },
  90. error: (xhr, errorType) => done(errorType)
  91. })
  92. })
  93. it('receives post data in details object', (done) => {
  94. const postData = {
  95. name: 'post test',
  96. type: 'string'
  97. }
  98. ses.webRequest.onBeforeRequest((details, callback) => {
  99. assert.equal(details.url, defaultURL)
  100. assert.equal(details.method, 'POST')
  101. assert.equal(details.uploadData.length, 1)
  102. const data = qs.parse(details.uploadData[0].bytes.toString())
  103. assert.deepEqual(data, postData)
  104. callback({ cancel: true })
  105. })
  106. $.ajax({
  107. url: defaultURL,
  108. type: 'POST',
  109. data: postData,
  110. success: () => {},
  111. error: () => done()
  112. })
  113. })
  114. it('can redirect the request', (done) => {
  115. ses.webRequest.onBeforeRequest((details, callback) => {
  116. if (details.url === defaultURL) {
  117. callback({ redirectURL: `${defaultURL}redirect` })
  118. } else {
  119. callback({})
  120. }
  121. })
  122. $.ajax({
  123. url: defaultURL,
  124. success: (data) => {
  125. assert.equal(data, '/redirect')
  126. done()
  127. },
  128. error: (xhr, errorType) => done(errorType)
  129. })
  130. })
  131. })
  132. describe('webRequest.onBeforeSendHeaders', () => {
  133. afterEach(() => {
  134. ses.webRequest.onBeforeSendHeaders(null)
  135. })
  136. it('receives details object', (done) => {
  137. ses.webRequest.onBeforeSendHeaders((details, callback) => {
  138. assert.equal(typeof details.requestHeaders, 'object')
  139. assert.equal(details.requestHeaders['Foo.Bar'], 'baz')
  140. callback({})
  141. })
  142. $.ajax({
  143. url: defaultURL,
  144. headers: { 'Foo.Bar': 'baz' },
  145. success: (data) => {
  146. assert.equal(data, '/')
  147. done()
  148. },
  149. error: (xhr, errorType) => done(errorType)
  150. })
  151. })
  152. it('can change the request headers', (done) => {
  153. ses.webRequest.onBeforeSendHeaders((details, callback) => {
  154. const requestHeaders = details.requestHeaders
  155. requestHeaders.Accept = '*/*;test/header'
  156. callback({ requestHeaders: requestHeaders })
  157. })
  158. $.ajax({
  159. url: defaultURL,
  160. success: (data) => {
  161. assert.equal(data, '/header/received')
  162. done()
  163. },
  164. error: (xhr, errorType) => done(errorType)
  165. })
  166. })
  167. it('resets the whole headers', (done) => {
  168. const requestHeaders = {
  169. Test: 'header'
  170. }
  171. ses.webRequest.onBeforeSendHeaders((details, callback) => {
  172. callback({ requestHeaders: requestHeaders })
  173. })
  174. ses.webRequest.onSendHeaders((details) => {
  175. assert.deepEqual(details.requestHeaders, requestHeaders)
  176. done()
  177. })
  178. $.ajax({
  179. url: defaultURL,
  180. error: (xhr, errorType) => done(errorType)
  181. })
  182. })
  183. })
  184. describe('webRequest.onSendHeaders', () => {
  185. afterEach(() => {
  186. ses.webRequest.onSendHeaders(null)
  187. })
  188. it('receives details object', (done) => {
  189. ses.webRequest.onSendHeaders((details) => {
  190. assert.equal(typeof details.requestHeaders, 'object')
  191. })
  192. $.ajax({
  193. url: defaultURL,
  194. success: (data) => {
  195. assert.equal(data, '/')
  196. done()
  197. },
  198. error: (xhr, errorType) => done(errorType)
  199. })
  200. })
  201. })
  202. describe('webRequest.onHeadersReceived', () => {
  203. afterEach(() => {
  204. ses.webRequest.onHeadersReceived(null)
  205. })
  206. it('receives details object', (done) => {
  207. ses.webRequest.onHeadersReceived((details, callback) => {
  208. assert.equal(details.statusLine, 'HTTP/1.1 200 OK')
  209. assert.equal(details.statusCode, 200)
  210. assert.equal(details.responseHeaders['Custom'], 'Header')
  211. callback({})
  212. })
  213. $.ajax({
  214. url: defaultURL,
  215. success: (data) => {
  216. assert.equal(data, '/')
  217. done()
  218. },
  219. error: (xhr, errorType) => done(errorType)
  220. })
  221. })
  222. it('can change the response header', (done) => {
  223. ses.webRequest.onHeadersReceived((details, callback) => {
  224. const responseHeaders = details.responseHeaders
  225. responseHeaders['Custom'] = ['Changed']
  226. callback({ responseHeaders: responseHeaders })
  227. })
  228. $.ajax({
  229. url: defaultURL,
  230. success: (data, status, xhr) => {
  231. assert.equal(xhr.getResponseHeader('Custom'), 'Changed')
  232. assert.equal(data, '/')
  233. done()
  234. },
  235. error: (xhr, errorType) => done(errorType)
  236. })
  237. })
  238. it('does not change header by default', (done) => {
  239. ses.webRequest.onHeadersReceived((details, callback) => {
  240. callback({})
  241. })
  242. $.ajax({
  243. url: defaultURL,
  244. success: (data, status, xhr) => {
  245. assert.equal(xhr.getResponseHeader('Custom'), 'Header')
  246. assert.equal(data, '/')
  247. done()
  248. },
  249. error: (xhr, errorType) => done(errorType)
  250. })
  251. })
  252. it('follows server redirect', (done) => {
  253. ses.webRequest.onHeadersReceived((details, callback) => {
  254. const responseHeaders = details.responseHeaders
  255. callback({ responseHeaders: responseHeaders })
  256. })
  257. $.ajax({
  258. url: defaultURL + 'serverRedirect',
  259. success: (data, status, xhr) => {
  260. assert.equal(xhr.getResponseHeader('Custom'), 'Header')
  261. done()
  262. },
  263. error: (xhr, errorType) => done(errorType)
  264. })
  265. })
  266. it('can change the header status', (done) => {
  267. ses.webRequest.onHeadersReceived((details, callback) => {
  268. const responseHeaders = details.responseHeaders
  269. callback({
  270. responseHeaders: responseHeaders,
  271. statusLine: 'HTTP/1.1 404 Not Found'
  272. })
  273. })
  274. $.ajax({
  275. url: defaultURL,
  276. success: (data, status, xhr) => {},
  277. error: (xhr, errorType) => {
  278. assert.equal(xhr.getResponseHeader('Custom'), 'Header')
  279. done()
  280. }
  281. })
  282. })
  283. })
  284. describe('webRequest.onResponseStarted', () => {
  285. afterEach(() => {
  286. ses.webRequest.onResponseStarted(null)
  287. })
  288. it('receives details object', (done) => {
  289. ses.webRequest.onResponseStarted((details) => {
  290. assert.equal(typeof details.fromCache, 'boolean')
  291. assert.equal(details.statusLine, 'HTTP/1.1 200 OK')
  292. assert.equal(details.statusCode, 200)
  293. assert.equal(details.responseHeaders['Custom'], 'Header')
  294. })
  295. $.ajax({
  296. url: defaultURL,
  297. success: (data, status, xhr) => {
  298. assert.equal(xhr.getResponseHeader('Custom'), 'Header')
  299. assert.equal(data, '/')
  300. done()
  301. },
  302. error: (xhr, errorType) => done(errorType)
  303. })
  304. })
  305. })
  306. describe('webRequest.onBeforeRedirect', () => {
  307. afterEach(() => {
  308. ses.webRequest.onBeforeRedirect(null)
  309. ses.webRequest.onBeforeRequest(null)
  310. })
  311. it('receives details object', (done) => {
  312. const redirectURL = defaultURL + 'redirect'
  313. ses.webRequest.onBeforeRequest((details, callback) => {
  314. if (details.url === defaultURL) {
  315. callback({ redirectURL: redirectURL })
  316. } else {
  317. callback({})
  318. }
  319. })
  320. ses.webRequest.onBeforeRedirect((details) => {
  321. assert.equal(typeof details.fromCache, 'boolean')
  322. assert.equal(details.statusLine, 'HTTP/1.1 307 Internal Redirect')
  323. assert.equal(details.statusCode, 307)
  324. assert.equal(details.redirectURL, redirectURL)
  325. })
  326. $.ajax({
  327. url: defaultURL,
  328. success: (data) => {
  329. assert.equal(data, '/redirect')
  330. done()
  331. },
  332. error: (xhr, errorType) => done(errorType)
  333. })
  334. })
  335. })
  336. describe('webRequest.onCompleted', () => {
  337. afterEach(() => {
  338. ses.webRequest.onCompleted(null)
  339. })
  340. it('receives details object', (done) => {
  341. ses.webRequest.onCompleted((details) => {
  342. assert.equal(typeof details.fromCache, 'boolean')
  343. assert.equal(details.statusLine, 'HTTP/1.1 200 OK')
  344. assert.equal(details.statusCode, 200)
  345. })
  346. $.ajax({
  347. url: defaultURL,
  348. success: (data) => {
  349. assert.equal(data, '/')
  350. done()
  351. },
  352. error: (xhr, errorType) => done(errorType)
  353. })
  354. })
  355. })
  356. describe('webRequest.onErrorOccurred', () => {
  357. afterEach(() => {
  358. ses.webRequest.onErrorOccurred(null)
  359. ses.webRequest.onBeforeRequest(null)
  360. })
  361. it('receives details object', (done) => {
  362. ses.webRequest.onBeforeRequest((details, callback) => {
  363. callback({ cancel: true })
  364. })
  365. ses.webRequest.onErrorOccurred((details) => {
  366. assert.equal(details.error, 'net::ERR_BLOCKED_BY_CLIENT')
  367. done()
  368. })
  369. $.ajax({
  370. url: defaultURL,
  371. success: () => done('unexpected success')
  372. })
  373. })
  374. })
  375. })