Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTP/2 POST fails from browser over TLS #597

Closed
fizruk opened this Issue Dec 5, 2016 · 11 comments

Comments

Projects
None yet
5 participants
@fizruk
Copy link

commented Dec 5, 2016

Some major browsers use HTTP/2 for HTTPS requests. As it turns out warp does not support some part of it and as a result POST requests from at least Safari and Chrome fail over HTTPS. At the same time cURL works fine with HTTP/2 POST over TLS.

Here's a sample HTTP/2 sessions for Chrome (you can see one in chrome://net-internals): https://gist.github.com/fizruk/84c0feef4315028a20aaf13a31cb7dfd

I have disabled HTTP/2 for now and it's okay for me, but it would be nice to fix this issue.

@kazu-yamamoto kazu-yamamoto added the http2 label Dec 6, 2016

@kazu-yamamoto kazu-yamamoto self-assigned this Dec 6, 2016

@kazu-yamamoto

This comment has been minimized.

Copy link
Contributor

commented Dec 6, 2016

Consider this app:

import Control.Concurrent         ( threadDelay )
import Data.Aeson                 ( json' )
import Data.ByteString.Lazy.Char8 ( pack )
import Data.Conduit               ( ($$) )
import Data.Conduit.Attoparsec    ( sinkParser )
import Network.HTTP.Types.Status  ( ok200 )
import Network.Wai                ( responseLBS )
import Network.Wai.Conduit        ( sourceRequestBody )
import Network.Wai.Handler.Warp

main :: IO ()
main = runSettings stgs app
  where
    stgs = setTimeout 1 $ setPort 2000 $ setOnExceptionResponse err defaultSettings
    err e = responseLBS ok200 [] (pack $ show e)

    app rq k = do v <- sourceRequestBody rq $$ sinkParser json'
                  k $ responseLBS ok200 [] (pack $ show v)

I can post a JSON object with nghttp:

% echo '{}' | nghttp -d - -H "Content-type: application/json" http://localhost:2000
Object (fromList [])

So, HTTP/2 POST in plaintext is working in this case.
I would like to know how to reproduce this in a command line.

@kazu-yamamoto

This comment has been minimized.

Copy link
Contributor

commented Feb 27, 2017

I cannot reproduce this with Firefox/Chrome/Safari on Mac.
Some bugs of Warp relating to HTTP/2, found by new h2spec, were fixed.
So, I could try the latest Warp.

@BlakeRain

This comment has been minimized.

Copy link

commented Feb 26, 2018

I've recently encountered this issue in one of our applications. It seems to be only occurring on Chrome and Safari, and only seems to happen when the POST request has no content.

I've posted an example Yesod application here: https://gist.github.com/BlakeRain/9ce990e5dbb1546f245a92a4bef50a08

The example shows a simple form that submits no fields. When the POST request is made, the handler is not called and Chrome/Safari report similar errors to:

image

Disabling HTTP/2 (via setHTTP2Disabled) stops the issue and the form can be submitted.

As we're running behind Keter, disabling HTTP/2 in our application has no effect. So, a simple botch for us has been to insert a hidden field with a dummy value to make sure that some content is being submitted.

@thomasjm

This comment has been minimized.

Copy link

commented Apr 7, 2018

I'm seeing this too, likewise on Chrome when the POST request has no content.

In chrome://net-internals/#events I see the error HTTP2_STREAM_ERROR and the message "Server reset stream." as well as ERR_SPDY_PROTOCOL_ERROR

I'm on Stack LTS-10.0, with warp-3.2.13 and warp-tls-3.2.4

@kazu-yamamoto

This comment has been minimized.

Copy link
Contributor

commented Apr 19, 2018

Sorry for the delay.
Now I resume the HTTP/2 project and I can reproduce @BlakeRain's one. Thanks.

I will spend time to fix HTTP/2 related issues.

kazu-yamamoto added a commit to kazu-yamamoto/wai that referenced this issue Apr 19, 2018

fixing 0-length body in HTTP/2. (yesodweb#597)
This is due to careless conversion on refactoring.
Firefox sends Header/EoS for 0-length body.
Chrome (and probably Safari) sends Header + Data/EoS for 0-length body.
@kazu-yamamoto

This comment has been minimized.

Copy link
Contributor

commented Apr 19, 2018

It appeared that this bug is due to my careless refactoring.
The commit above fixes this issue at least for no content.

But I'm not sure that this fixes all cases relating to HTTP/2 POST.

@thomasjm

This comment has been minimized.

Copy link

commented Apr 19, 2018

Thanks for the fix! It might be good to add a unit test with an empty body since it's such a subtle edge case.

@kazu-yamamoto

This comment has been minimized.

Copy link
Contributor

commented Apr 20, 2018

Yes. I should improve the http2 library so that we can implement such test cases.

@kazu-yamamoto

This comment has been minimized.

Copy link
Contributor

commented Apr 20, 2018

A new version has been released anyway.

@kazu-yamamoto

This comment has been minimized.

Copy link
Contributor

commented Apr 27, 2018

Now POST is OK even if the request body length is large.

@kazu-yamamoto

This comment has been minimized.

Copy link
Contributor

commented Apr 27, 2018

I would close this in favor of #690.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.