request_interception_spec.rb 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. require 'spec_helper'
  2. RSpec.describe 'request interception', skip: Puppeteer.env.firefox? do
  3. it 'should intercept', sinatra: true do
  4. page.request_interception = true
  5. page.on('request') do |request|
  6. if request.url.include?('favicon.ico')
  7. request.continue
  8. next
  9. end
  10. expect(request.url).to include('/empty.html')
  11. expect(request.headers['user-agent']).not_to be_nil
  12. expect(request.headers['accept']).not_to be_nil
  13. expect(request.method).to eq('GET')
  14. expect(request.post_data).to be_nil
  15. expect(request.navigation_request?).to eq(true)
  16. expect(request.resource_type).to eq('document')
  17. request.continue
  18. end
  19. response = page.goto(server_empty_page)
  20. expect(response.ok?).to eq(true)
  21. end
  22. it 'should indicate alreay-handled if an intercept has been handled', sinatra: true do
  23. page.request_interception = true
  24. page.on('request', &:continue)
  25. page.on('request') do |request|
  26. expect(request.intercept_resolution_handled?).to eq(true)
  27. end
  28. page.on('request') do |request|
  29. expect(request.intercept_resolution_state.action).to eq('already-handled')
  30. end
  31. page.goto(server_empty_page)
  32. end
  33. it 'should allow mocking multiple headers with same key', sinatra: true do
  34. page.request_interception = true
  35. page.on('request') do |request|
  36. request.respond(
  37. status: 200,
  38. headers: {
  39. foo: 'bar',
  40. arr: ['1', '2'],
  41. 'set-cookie': ['first=1', 'second=2'],
  42. },
  43. body: 'Hello world',
  44. )
  45. end
  46. response = page.goto(server_empty_page)
  47. cookies = page.cookies
  48. first_cookie = cookies.find { |cookie| cookie['name'] == 'first' }
  49. second_cookie = cookies.find { |cookie| cookie['name'] == 'second' }
  50. expect(response.status).to eq(200)
  51. expect(response.headers['foo']).to eq('bar')
  52. expect(response.headers['arr']).to eq("1\n2")
  53. # request.respond() will not trigger Network.responseReceivedExtraInfo
  54. # fail to get 'set-cookie' header from response
  55. expect(first_cookie['value']).to eq('1')
  56. expect(second_cookie['value']).to eq('2')
  57. end
  58. end
  59. # https://github.com/puppeteer/puppeteer/blob/e2e98376b9a3fa9a2501ddc86ff6407f3b59887d/docs/api.md#cooperative-intercept-mode-and-legacy-intercept-mode
  60. RSpec.describe 'request interception example', skip: Puppeteer.env.firefox? do
  61. example 'Legacy Mode prevails and the request is aborted', sinatra: true do
  62. # In this example, Legacy Mode prevails and the request is aborted immediately
  63. # because at least one handler omits priority when resolving the intercept:
  64. # Final outcome: immediate abort()
  65. page.request_interception = true
  66. page.on('request') do |request|
  67. # Legacy Mode: interception is aborted immediately.
  68. request.abort(error_code: 'failed')
  69. end
  70. page.on('request') do |request|
  71. # ['already-handled'], meaning a legacy resolution has taken place
  72. expect(request.intercept_resolution_state.action).to eq('already-handled')
  73. # Cooperative Mode: votes for continue at priority 0.
  74. # Ultimately throws an exception after all handlers have finished
  75. # running and Cooperative Mode resolutions are evaluated becasue
  76. # abort() was called using Legacy Mode.
  77. request.continue(priority: 0)
  78. end
  79. expect { page.goto(server_empty_page) }.to raise_error(/net::ERR_FAILED/)
  80. end
  81. example 'Legacy Mode prevails and the request is continued', sinatra: true do
  82. # In this example, Legacy Mode prevails and the request is continued
  83. # because at least one handler does not specify a priority:
  84. # Final outcome: immediate continue()
  85. page.request_interception = true
  86. page.on('request') do |request|
  87. # Cooperative Mode: votes to abort at priority 0.
  88. # Ultimately throws an exception after all handlers have finished
  89. # running and Cooperative Mode resolutions are evaluated becasue
  90. # continue() was called using Legacy Mode.
  91. request.abort(error_code: 'failed', priority: 0)
  92. end
  93. page.on('request') do |request|
  94. # ['abort', 0], meaning an abort @ 0 is the current winning resolution
  95. expect(request.intercept_resolution_state.action).to eq('abort')
  96. expect(request.intercept_resolution_state.priority).to eq(0)
  97. # Legacy Mode: intercept continues immediately.
  98. request.continue
  99. end
  100. expect(page.goto(server_empty_page)).to be_a(Puppeteer::HTTPResponse)
  101. end
  102. example 'Cooperative Mode is active #1', sinatra: true do
  103. # In this example, Cooperative Mode is active
  104. # because all handlers specify a priority.
  105. # continue() wins because it has a higher priority than abort().
  106. # Final outcome: cooperative continue() @ 5
  107. page.request_interception = true
  108. page.on('request') do |request|
  109. # Cooperative Mode: votes to abort at priority 0
  110. request.abort(error_code: 'failed', priority: 0)
  111. end
  112. page.on('request') do |request|
  113. # Cooperative Mode: votes to continue at priority 5
  114. params = request.continue_request_overrides
  115. params[:priority] = 5
  116. request.continue(**params)
  117. end
  118. page.on('request') do |request|
  119. # ['continue', 5], because continue @ 5 > abort @ 0
  120. expect(request.intercept_resolution_state.action).to eq('continue')
  121. expect(request.intercept_resolution_state.priority).to eq(5)
  122. request.continue
  123. end
  124. expect(page.goto(server_empty_page)).to be_a(Puppeteer::HTTPResponse)
  125. end
  126. example 'Cooperative Mode is active #2', sinatra: true do
  127. # In this example, Cooperative Mode is active
  128. # because all handlers specify priority.
  129. # respond() wins because its priority ties with continue(), but respond() beats continue().
  130. # Final outcome: cooperative continue() @ 5
  131. page.request_interception = true
  132. page.on('request') do |request|
  133. # Cooperative Mode: votes to abort at priority 10
  134. request.abort(error_code: 'failed', priority: 10)
  135. end
  136. page.on('request') do |request|
  137. # Cooperative Mode: votes to continue at priority 15
  138. params = request.continue_request_overrides
  139. params[:priority] = 15
  140. request.continue(**params)
  141. end
  142. page.on('request') do |request|
  143. # Cooperative Mode: votes to respond at priority 15
  144. params = request.response_for_request || {}
  145. params[:priority] = 15
  146. request.respond(**params)
  147. end
  148. page.on('request') do |request|
  149. # Cooperative Mode: votes to respond at priority 15
  150. params = request.response_for_request || {}
  151. params[:priority] = 12
  152. request.respond(**params)
  153. end
  154. page.on('request') do |request|
  155. # ['continue', 5], because continue @ 5 > abort @ 0
  156. expect(request.intercept_resolution_state.action).to eq('respond')
  157. expect(request.intercept_resolution_state.priority).to eq(15)
  158. request.continue
  159. end
  160. expect(page.goto(server_empty_page)).to be_a(Puppeteer::HTTPResponse)
  161. end
  162. end