├── README.md ├── streaming-upload-security-privacy-questionnaire.md └── streaming-upload.md /README.md: -------------------------------------------------------------------------------- 1 | Fetch API integrated with Streams 2 | === 3 | 4 | This document is about the integration of [the Streams API](https://streams.spec.whatwg.org/) with [the Fetch API](https://fetch.spec.whatwg.org/#fetch-api). 5 | 6 | -------------------------------------------------------------------------------- /streaming-upload-security-privacy-questionnaire.md: -------------------------------------------------------------------------------- 1 | - What information might this feature expose to Web sites or other parties, and for what purposes is that exposure necessary? 2 | - The feature provides an additional way to upload data to an HTTP server. No additional exposure is introduced. 3 | - Is this specification exposing the minimum amount of information necessary to power the feature? 4 | - Same above. Regarding the amount of information, there is little difference between this feature and traditional uploading feature (uploading strings/arraybuffers/blobs with fetch()). 5 | - How does this specification deal with personal information or personally-identifiable information or information derived thereof? 6 | - This feature doesn't interpret data it uploads. It is up to the application how to handle the data. This feature is usable only on HTTP/2 and HTTP/3, which means the data is always protected by encryption. 7 | - How does this specification deal with sensitive information? 8 | - This feature doesn't interpret data it uploads. It is up to the application how to handle the data. This feature is usable only on HTTP/2 and HTTP/3, which means the data is always protected by encryption. 9 | - Does this specification introduce new state for an origin that persists across browsing sessions? 10 | - No. 11 | - What information from the underlying platform, e.g. configuration data, is exposed by this specification to an origin? 12 | - No configuration data is explicitly exposed. Some network conditions can be obtained as side channel information. For example, a malicious developer can use this API to check whether a user is behind a proxy that only speaks HTTP/1.1. 13 | - Does this specification allow an origin access to sensors on a user’s device? 14 | - No. 15 | - What data does this specification expose to an origin? Please also document what data is identical to data exposed by other features, in the same or different contexts. 16 | - No additional data is exposed compared to other uploading features with fetch() and XMLHttpRequest. 17 | - Does this specification enable new script execution/loading mechanisms? 18 | - No. 19 | - Does this specification allow an origin to access other devices? 20 | - No. 21 | - Does this specification allow an origin some measure of control over a user agent’s native UI? 22 | - No. 23 | - What temporary identifiers might this this specification create or expose to the web? 24 | - None. 25 | - How does this specification distinguish between behavior in first-party and third-party contexts? 26 | - The specification makes no distinction between any parties that can run script in the context of the document’s origin. 27 | - How does this specification work in the context of a user agent’s Private \ Browsing or "incognito" mode? 28 | - Behaviour is unchanged. 29 | - Does this specification have a "Security Considerations" and "Privacy Considerations" section? 30 | - No. 31 | - Does this specification allow downgrading default security characteristics? 32 | - No. 33 | - What should this questionnaire have asked? 34 | - None known. 35 | -------------------------------------------------------------------------------- /streaming-upload.md: -------------------------------------------------------------------------------- 1 | Streaming upload allows web developers to attach a `ReadableStream` to a `Request`. 2 | 3 | ```js 4 | const rs = new ReadableStream({...}); 5 | const resp = await fetch(url, {method: 'POST', body: rs, duplex: 'half'}); 6 | ``` 7 | 8 | With this feature, 9 | 10 | - Web developers can upload unbounded data to the server. This can't be done with 11 | blobs, because the size (and the contents) of a blob needs to be set before 12 | starting sending it. 13 | - Web developers can implement streaming processing easily. Let's assume we have 14 | a large ReadableStream consisting of Strings (`rs`) and a TransformStream 15 | (`deflater`) for an awesome compression algorithm - we can make a fetch with the 16 | compressed stream, like this: 17 | ```js 18 | const body = rs.pipeThrough(new TextEncoderStream()).pipeThrough(deflater); 19 | const resp = await fetch(url, {method: 'POST', body, duplex: 'half'}); 20 | ``` 21 | The encoding and compression is done on-the-fly: we don't need to wait for the 22 | entire body to be encoded and compressed before starting sending. 23 | 24 | Without this feature, web developers typically need to do one (or more) of the 25 | followings to implement the equivalent: 26 | 27 | - Split the stream into multiple chunks and make a fetch for each chunk. This is 28 | generally bad for performance, and it is difficult to figure out the optimal 29 | size of each chunk. This also requires additional logic and error handling on 30 | both of client and server sides. 31 | - Construct a blob (or ArrayBuffer) to be sent before making a fetch. This will 32 | impact the latency and peek memory usage heavily. 33 | - Use protocols such as WebSocket and WebTransport over HTTP/3. The server needs 34 | to understand these protocols if we choose this option. 35 | 36 | These performance shortcomings and cost of additional logic will impact end-users. 37 | In other words, this feature will help end-users enjoy web applications with better 38 | performance, more reliability and less cost. 39 | 40 | 41 | There are some caveats: 42 | 43 | - Most of redirects and authentication responses lead to errors. This comes 44 | from the fact that a streaming body cannot be replayed without storing the 45 | entire body (even after sending them), and we don't want to store the entire 46 | body. 47 | - Only 'cors' and 'same-origin' requests allow streaming upload. You can't use 48 | streaming upload with 'navigate' and 'no-cors' requests. 49 | - Cross-origin requests with streaming upload always trigger CORS preflight. 50 | - This feature cannot be used with HTTP/1.x. If the server doesn't support 51 | HTTP/2 or HTTP/3, the request fails. This is for some compatibility concerns. 52 | See https://github.com/whatwg/fetch/issues/966 for the past discussions. 53 | - The browser sends all the request body before starting processing the response 54 | headers. This, so-called "half-duplex" behavior, is aligned with what browsers 55 | (Chrome, Firefox, Safari) currently do. There is another, so-called 56 | "full-duplex" behavior. With the model, user-agents process response 57 | (including the response body) while sending the request (including the 58 | request body). This is being discussed at 59 | https://github.com/whatwg/fetch/issues/1254, but it is not included in the 60 | first version. 61 | --------------------------------------------------------------------------------