1. 07 Oct, 2018 1 commit
    • Kenton Varda's avatar
      Make HttpInputStream reusable. · 513cd4e8
      Kenton Varda authored
      Some protocols, like Visual Studio Code's Language Server Protocol, have made the unfortunate decision to use HTTP-style message envelope even though they are not HTTP protocols. LSP, for example, sends each JSON-RPC messages as a Content-Length header followed by two CRLF followed by a JSON message of that length. I didn't want to rewrite HTTP parsing, so I extended the HTTP library to make this functionality reusable.
      513cd4e8
  2. 31 Aug, 2018 1 commit
  3. 26 Aug, 2018 2 commits
  4. 10 Aug, 2018 1 commit
    • Harris Hancock's avatar
      Expose CONNECTION_HEADERS_COUNT in http.h · 1a8b95d1
      Harris Hancock authored
      To safely use HttpHeaders::serialize*() with overridden connection-level headers, dependent code must stay up-to-date with any changes in the builtin header list. We now expose CONNECTION_HEADERS_COUNT and its friends to facilitate this.
      1a8b95d1
  5. 07 Jun, 2018 1 commit
  6. 24 Apr, 2018 1 commit
  7. 22 Apr, 2018 1 commit
    • Kenton Varda's avatar
      Implement newHttpClient(HttpService&). · 76104a88
      Kenton Varda authored
      It turns out wrapping an HttpService in an HttpClient is considerably more complicated than vice versa, due to the need for pipes. This commit adds a WebSocket pipe implementation very similar to the recent byte-stream pipe (though considerably simpler since there's no need to deal with mismatched buffer sizes).
      76104a88
  8. 09 Apr, 2018 1 commit
    • Kenton Varda's avatar
      Allow app to send arbitrary Content-Length/Transfer-Encoding in HEAD responses. · be9b18c5
      Kenton Varda authored
      Previously, the app could control Content-Length by passing `expectedBodySize`. This is great for enabling code that "just works" by handling GET and HEAD requests identically.
      
      However, in somewhat more-complicated situations -- especilaly in proxies -- you end up having to write special-case hacks for HEAD requests to deal with the fact that the body is actually empty, but has a non-zero "expected" size.
      
      We can make life easier for proxies by allowing the application to directly set the Content-Length and Transfer-Encoding headers in the case of HEAD responses, much like we allow applications to set WebSocket-related headers on non-WebSocket requests/responses.
      
      This change actually fixes a bug in Cloudflare Workers where Content-Length is not passed through correctly for HEAD responses. No changes are needed on the Workers side (except adding a test).
      be9b18c5
  9. 23 Feb, 2018 1 commit
    • Kenton Varda's avatar
      Extend HttpServer to inform the caller when a connection ends cleanly on drain(). · 098004cd
      Kenton Varda authored
      This allows an application which calls drain() to potentially pass off HTTP connections to a new HttpServer afterwards. Without this, the application has no way to know if the connections are in an indeterminant state.
      
      This change also makes it OK for an application to fail to read the whole request body. Previously, if an app returned a response without reading the whole request, an exception would eventually be thrown, but potentially not until the client had initiated a new request on the same connection. The client would then get a spurious 500 error.
      098004cd
  10. 13 Feb, 2018 1 commit
    • Kenton Varda's avatar
      Redesign server-side WebSocket handling. · 632888d6
      Kenton Varda authored
      Previously HttpService had two virtual methods: request() and openWebSocket(). Since it's legitimate to respond to a WebSocket request with a normal HTTP response, openWebSocket() actually had a default implementation that fell back to request().
      
      In the new design, there is only request(). The HttpService detects a WebSocket request by checking the headers. A convenience method, HttpHeaders::isWebSocket(), is provided for this purpose.
      
      The new approach makes life much easier for services composed of many layers. For example, you might write an HttpService implementation which performs some URL or header rewrite and then calls on to another HttpService. Previously, every such wrapper would have to separately handle regular requests and WebSockets, usually with near-identical code. Of course, you could factor out the common code, but in practice this often turned out pretty clunky. Worse, developers would often just omit the openWebSocket() implementation since implementing only request() seems to work fine -- until you need a WebSocket, and everything is broken. With the new approach, you have to go somewhat out of your way to write a wrapper layer that breaks WebSockets.
      
      I did not apply the same logic to HttpClient because:
      
      1. It's not as easy: HttpClient's methods return results rather than calling a callback on completion, so unifying the methods would have forced request()'s signature to change. Lots of code would need to be updated, and would likely become uglier, as request() would now have to return a `webSocketOrBody` variant type even when the caller isn't asking for a WebSocket.
      2. People don't implement custom HttpClients nearly as often as they implement custom HttpServices.
      632888d6
  11. 11 Feb, 2018 1 commit
  12. 04 Feb, 2018 1 commit
  13. 18 Jan, 2018 1 commit
    • Kenton Varda's avatar
      Refactor handling of connection-level headers. · 3b08c76b
      Kenton Varda authored
      Although applications in theory shouldn't care to see connection-level headers (e.g. `Transfer-Encoding`), higher-level specs like the JavaScript Fetch API often specify that these headers should be visible, and they can be useful for debugging. So, this change makes it so that the application can see the connection-level headers on incoming requests.
      
      For outgoing requests, the application can provide an HttpHeaders object that specifies these headers (important especially for the pass-through case), but the HTTP implementation will ignore them.
      
      Additionally, we can now allow the application to set WebSocket connection-level headers on non-WebSocket requests. This is useful for frameworks that emulate WebSocket over HTTP and assume the ability to set WebSocket headers (especially `Sec-WebSocket-Extension`) on regular non-WebSocket HTTP requests.
      3b08c76b
  14. 11 Jan, 2018 1 commit
    • Kenton Varda's avatar
      Replace all include guards with #pragma once. · 677a52ab
      Kenton Varda authored
      @kloepper pointed out a while back that every compiler you've ever heard of supports this. Plus, it's more concise, it's not prone to copy-paste errors, and it looks nicer.
      
      At the time I wanted to remain consistent and I didn't feel like spending the time to update all my existing code. But, every time I've added a new header since I've cursed the include guard, so I finally broke down and changed it.
      677a52ab
  15. 24 Sep, 2017 1 commit
    • Kenton Varda's avatar
      Sec-WebSocket-Extensions is a connection-level header. · 2d956813
      Kenton Varda authored
      We don't support any extensions currently, but it's important that when acting as a proxy, we don't pass through this header, since it could result in the client and server negotiating extensions that the proxy doesn't understand and will botch.
      2d956813
  16. 22 Sep, 2017 1 commit
  17. 21 Sep, 2017 1 commit
    • Kenton Varda's avatar
      Implement HttpClient that automatically manages connections. · 2751b577
      Kenton Varda authored
      There are actually two new client types:
      - One which always connects to a given NetworkAddress, but will automatically manage a pool of reusable connections.
      - One which looks up the remote address based on the URL it is given, and manages a pool of connections for each host.
      
      The latter of these two is a "true HTTP client library".
      2751b577
  18. 05 Sep, 2017 1 commit
  19. 04 Sep, 2017 2 commits
  20. 18 Aug, 2017 1 commit
  21. 15 Aug, 2017 4 commits
  22. 26 May, 2017 1 commit
  23. 02 May, 2017 1 commit
  24. 29 Apr, 2017 2 commits
  25. 27 Apr, 2017 1 commit
  26. 27 Jan, 2017 4 commits
  27. 24 Jan, 2017 1 commit
    • Kenton Varda's avatar
      Add HTTP client and server implementation. · 8f5d1f10
      Kenton Varda authored
      Properties:
      - Presented as a LIBRARY, designed to be unopinionated about the application using it.
      - Uses KJ async framework.
      - Header parsing is zero-copy. The whole header block is read into a contiguous buffer, then parsed all at once. Avoids complicated state machinery (and is probably pretty fast).
      - Known headers are parsed to numeric identifiers so that the application doesn't need to look them up by string name. The app registers all headers it is interested in upfront, receiving numeric IDs for each. Some common headers also have pre-defined constants, avoiding the need for registration.
      - Connection-level headers (e.g. Content-Length, Transfer-Encoding) are handled entirely internally.
      - WebSocket support (planned).
      
      Not done yet:
      - Implement the version of HttpClient that connects to new servers as-needed, managing a pool of connections. Currently I've only implemented the version that takes a pre-existing connection and speaks HTTP on it.
      - Implement WebSockets.
      - Implement plugable transfer encodings (although I guess Chrome doesn't even support transfer encodings other than chunked; maybe it's a lost cause).
      - Implement HTTP/2, hopefully transparently (... someday).
      8f5d1f10