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

Abort streamed request #112

Closed
LostKobrakai opened this issue Jan 14, 2021 · 8 comments
Closed

Abort streamed request #112

LostKobrakai opened this issue Jan 14, 2021 · 8 comments

Comments

@LostKobrakai
Copy link

LostKobrakai commented Jan 14, 2021

Say I'm using Finch to proxy some request to an upstream http server I might want to stop the stream if the caller closed the connection:

Finch.stream(request, Pour.HTTP, conn, fn
  {:status, status}, conn -> 
    send_chunked(conn, status)
    
  {:headers, _}, conn -> 
    conn
    
  {:data, _}, conn -> 
    case Plug.Conn.chunk(conn, chunk) do
      {:ok, conn} -> conn
      {:error, :closed} -> # how to abort here
    end
end)
@thbar
Copy link
Contributor

thbar commented Apr 10, 2021

This can also be useful when e.g. you'd want to halt the processing based on headers or status. For instance, if one wants to use streaming to compute a checksum of the data, but only compute it if the status is 200, and ignore otherwise (or follow a redirect header etc).

@ericmj
Copy link
Contributor

ericmj commented Apr 11, 2021

You cannot abort HTTP/1 requests, the only thing you can do is close the connection. If you want to make a choice based on the headers you should use Expect: 100-continue.

With HTTP/2 you can abort requests, Mint exposes that through Mint.HTTP2.cancel_request/2.

@thbar
Copy link
Contributor

thbar commented Apr 11, 2021

Thanks! To simulate the abortion, is there a recommended way to close an HTTP/1 connection inside a Finch.stream stream function?

@chargreezy
Copy link

chargreezy commented Apr 6, 2022

Sorry to bump this issue, but I was also curious if there is recommended way to close a connection inside a Finch.stream?

@chargreezy
Copy link

chargreezy commented Apr 7, 2022

To expand on this, when streaming in finch we pass a reducing function for status, headers and data. This underlying mint connection is not available inside these calls, would adding the mint connection to the call make the functionality possible?

Before:

      {:status, value}, {_, headers, body} ->
        {value, headers, body}
      {:headers, value}, {status, headers, body} ->
        {status, headers ++ value, body}
      {:data, value}, {status, headers, body} ->
        {status, headers, [value | body]}

After:

      {:status, value, mint}, {_, headers, body} ->
        {value, headers, body}
      {:headers, value, mint}, {status, headers, body} ->
        {status, headers ++ value, body}
      {:data, value, mint}, {status, headers, body} ->
        // Maybe close the connection with Mint.HTTP.close(mint)

@ericmj
Copy link
Contributor

ericmj commented Apr 8, 2022

If you throw inside the streaming function the connection will be closed (for HTTP/1.1) and the request will be cancelled: https://github.com/sneako/finch/blob/main/test/finch/http1/integration_test.exs#L83

@sneako
Copy link
Owner

sneako commented Apr 10, 2022

Thanks @ericmj, that is a great point! If you throw in your stream function HTTP/1 will close the connection here and HTTP/2 will cancel the request here. I think that should be sufficient but if anyone can describe a situation where it would not be please share.

@chargreezy
Copy link

Thanks for the response! I saw the integration test but it's great to get a confirmation this is expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants