cypress icon indicating copy to clipboard operation
cypress copied to clipboard

Add HTTP/2 Support in Proxy Layer

Open flotwig opened this issue 6 years ago • 43 comments
trafficstars

The proxy layer currently doesn't really support HTTP/2. The only case in which a user can take advantage of HTTP/2 is if they are making a non-intercepted request through the https-proxy, and when #687 lands, all requests will be intercepted. When a request is intercepted, it can't be upgraded to HTTP/2.

Take this page, which loads 1000 images: https://flotwig.github.io/cypress-fetch-page/index1000.html

Loaded with HTTP/2, 1000 images load in 1362ms on my browser.

With HTTP/1.1, it takes 3896ms - three times as long.

Making our backend requests use HTTP/2 would give us a huge performance boost for making requests against servers that support it.

Obstacles:

  1. request library doesn't support HTTP/2 - we'd need to fork or figure out a different way to try to upgrade to http2
  2. need to figure out how HTTP/2 interacts with HTTP proxies

flotwig avatar Mar 14 '19 14:03 flotwig

What are the smallest next steps possible to bring this ticket forward?

I found there's https://github.com/cypress-io/cypress/tree/develop/packages/https-proxy and in there is also a test suite. Are new tests to be added? I can see these new cases:

  • [ ] HTTP/2 from the proxy to the target
  • [ ] HTTP/2 from the browser to the proxy
  • [ ] various conversions done in the proxy code
    • [ ] target server is HTTP/1.1 only, but browser sent a HTTP/2 request
    • [ ] target server is HTTP/2 and browser sent a HTTP/3 or 1.1 or QUIC request

sesam avatar Oct 15 '20 19:10 sesam

@sesam There's two systems at play here, neither of which support HTTP/2 at this time:

  1. The HTTP/1.1 proxy server that all user requests go through - the server is stood up in packages/server/lib/server.js, proxied requests are sent outgoing in packages/proxy/lib/http/request-middleware.ts
  2. The HTTP request library that is used to make outgoing requests for the proxy and for cy.visit/cy.request does not support HTTP/1.1 at all, neither does request, the underlying library which it is based upon. See packages/server/lib/request.js

I think that, for real performance gains, both (1) and (2) would have to be updated to speak HTTP/2. This could be done in two separate PRs. After that's completed, an HTTP/2 conversation inside of Cypress would look like this (similar to how HTTPS connections are handled in Cypress currently):

  1. User attempts to load example.com inside of the Cypress browser.
  2. Browser makes a request to the Cypress proxy with the header line: CONNECT example.com:443 HTTP/1.1
  3. Cypress routes this CONNECT request to the https-proxy, which establishes an HTTP/2 server to handle requests to example.com:443, and then pipes the incoming CONNECT request to this HTTP/2 server.
    • This is similar to how plain HTTPS is intercepted in Cypress today - CONNECT requests stand up an HTTPS server, which is then piped to the incoming CONNECT request.
  4. Then, inside of packages/server/lib/request.js, the outgoing HTTP request library is also updated to use HTTP/2. The requests/responses are proxied as normal via packages/proxy/lib/http.

I haven't worked directly with HTTP/2 yet, but does this make sense? There are several different places where tests would need to be added, but it sounds like your ideas for test coverage would be a good start.


Some quick notes from messing with (1):

  • Chrome supports HTTP/2 proxying using --proxy-server=https://localhost:xxx. However, since Chrome doesn't support insecure HTTP/2, the proxy server needs to be listening on HTTPS. Which is fine.
  • Firefox does not seem to support HTTP/2 proxying.

flotwig avatar Oct 15 '20 21:10 flotwig

I would like to mention that this is not only performance issue. All projects that use http2 streams they just can't use Cypress. Any updates on this issue ?

midan888 avatar Apr 02 '21 07:04 midan888

@midan888 nobody from Cypress is currently working on this issue.

flotwig avatar Apr 02 '21 13:04 flotwig

Making our backend requests use HTTP/2 would give us a huge performance boost for making requests against servers that support it.

For completeness, this is virtually all servers not running on localhost in development mode, so this feature would help a huge number of usecases.

csvan avatar Dec 14 '21 06:12 csvan

I use Cypress Ccomponent tests with Vite. Vite downloads huge amount of javascript modules separetly. Due to limitations of HTTP1 tests initial load is slow.

Waiting for 1.5s at each module to get 304 Not Modified response :/ image

edikdeisling avatar Feb 03 '22 14:02 edikdeisling

I'm trying to test my Sveltekit app which use FaunaDB's document streaming to update the page in real-time. It works when tested manually with the dev server but not when tested in Cypress.

homostellaris avatar Feb 07 '22 09:02 homostellaris

Are there any updates on this issue at this point?? My team is trying to use Cypress to test our app that is using grpc-web services and we are currently unable to intercept requests or even make successful requests currently from our app in a Cypress test.

seanmcquaid avatar Apr 12 '22 17:04 seanmcquaid

Is there a way to entirely disable proxy?

gajus avatar Jun 14 '22 19:06 gajus

This could be solved with https://github.com/cypress-io/cypress/issues/22319

gajus avatar Jun 14 '22 19:06 gajus

As a workaround, I modified resources/app/packages/server/lib/browsers/chrome.js to exclude my http/2 requests since they use a different port in order to not break the streaming support: args.push('--proxy-bypass-list=<-loopback>;https://localhost:9000');

breynolds3 avatar Jul 18 '22 12:07 breynolds3

+1 :)

wojciak avatar Sep 06 '22 08:09 wojciak

An update on this would be great to see. :) As it stands, projects using http/2 seem to have to look elsewhere.

kelseyaubrecht avatar Sep 06 '22 13:09 kelseyaubrecht

+1 Multiple event sources make cypress useless

mmakarin avatar Sep 09 '22 11:09 mmakarin

+1. I have a project with multiple EventSources connection. Currently we have to pending the automation scripts due to this issue.

shirai91 avatar Nov 03 '22 14:11 shirai91

As not to leave everyone hanging, this is been discussed recently internally (eg, "we need to make the network layer faster"), and not straight up ignored. I don't have a date for when this will be 1) worked on or 2) completed right now, though.

Once there is more information, this issue will be updated. I hope we can do it soon, fast is good, faster is better.

lmiller1990 avatar Dec 20 '22 01:12 lmiller1990

This is causing a lot of slowness in a new application that uses lots of chunks by default (default for a lot of new apps), so glad to see this is being worked on

bigcakes avatar Jan 31 '23 18:01 bigcakes

@bigcakes what version of Cypress are you on? There were some incremental (not major) tweaks to things during Cypress 11, maybe some of those help?

I agree that apps making many requests (especially if you use Vite for your dev server and test against it, too) it can be a major bottleneck.

lmiller1990 avatar Feb 01 '23 23:02 lmiller1990

@lmiller1990 We are on 11.2, but I am loading about 100 javascript chunks + css/images + API calls currently so the http1 limitation is fairly impactful to our initial load speed

bigcakes avatar Feb 02 '23 15:02 bigcakes

Agreed, it's slow with many chunks, some of the slowness was addressed in this PR https://github.com/cypress-io/cypress/pull/25209 which was released in Cypress 12.3.0, if you can update to 12.3.0, that might help, it helped my app using Vite load much quicker in Cypress. Another user reported the same, see here: https://github.com/cypress-io/cypress/issues/22868#issuecomment-1383633338 (this thread has a ton of info about the exact problem you are encountering).

That actual HTTP/2 improvements will be the biggest help, this is getting worked on but I am not sure on ETA.

lmiller1990 avatar Feb 02 '23 23:02 lmiller1990

Perf is definitely better since 12.3.0, thank you to all contributors for that. However, it is still noticeably slower, especially in the vite use case.

HTTP2 seems like a win-win direction, but id also note the convo on https://github.com/cypress-io/cypress/issues/25201.

adam-thomas-privitar avatar Feb 20 '23 13:02 adam-thomas-privitar

@lmiller1990 I did update us and saw ~20% test speed increase, however definitely looking forward to http2

bigcakes avatar Feb 20 '23 13:02 bigcakes

Actually, I've changed my mind on this. HTTP2 might not be the core issue at hand in many scenarios. See https://github.com/cypress-io/cypress/issues/25201#issuecomment-1438475302

adam-thomas-privitar avatar Feb 21 '23 13:02 adam-thomas-privitar

+1

amiralav-sonrai avatar Jun 26 '23 16:06 amiralav-sonrai

+1

paulwalsh-sonrai avatar Jun 26 '23 19:06 paulwalsh-sonrai

+1 have same issues!

codingwesley avatar Jul 08 '23 04:07 codingwesley

Just wondering whats happening regarding support got http2 - my current project has switched to http2, now all tests are broken and getting pressured to use another framework that supports it.

markbeaman44 avatar Jul 17 '23 09:07 markbeaman44

Hi @markbeaman44 - your app should work fine, even if you are using HTTP/2 - if you've got a minimal reproduction, I'd recommend creating a new issue and we can take a look.

This issue in relating to how Cypress internally handles requests - the idea is to use HTTP/2 for performance reasons. Apps using HTTP/2 work fine right now, they might just load bit slower when running in Cypress.

If you have an actual issue where an app using HTTP/2 is not working at all in Cypress, please share a minimal reproduction in a new issue and we can take a look. Thanks.

lmiller1990 avatar Jul 17 '23 23:07 lmiller1990

@lmiller1990 it doesn't work if you use a lot of streaming connections due to the lack of multiplexing with http/1.1. Originally I was able to work around it because our application used a separate port for the streaming connections (grpc). I bypassed the proxy for the streaming connections. But now we consolidated to a single port, so all of my tests are broken also.

breynolds3 avatar Jul 18 '23 02:07 breynolds3

Right, I see, I think this makes sense. If you can post a minimal reproduction, that would be really useful -- ideally in a separate issue.

Having more "my app cannot be tested in Cypress" like use cases will greatly help with prioritizing this feature. Right now, the main reason to do this is to make Cypress faster -- performance is always good to have, but a real business use case (eg - "I want to use Cypress, but I can't) certainly helps the product team when they re-evaluate the priority on issues every other month or so. Thank you!

lmiller1990 avatar Jul 18 '23 04:07 lmiller1990