- From: Mike Bishop <mbishop@evequefou.be>
- Date: Fri, 22 Aug 2025 21:25:02 +0000
- To: Tommy Pauly <tpauly@apple.com>, Working Group HTTP <ietf-http-wg@w3.org>
- Message-ID: <IA0PPF726CD7A1FAAE540AE97EED8A22A21DA3DA@IA0PPF726CD7A1F.namprd22.prod.outlook.>
I've watched this document with some interest, both because it addresses an interesting use-case and because it makes novel use of a number of HTTP primitives, though I haven't been following all the side discussions as closely as I'd like. It's entirely possible some of my comments here duplicate things previously discussed; feel free to point me to those discussions as rationale for not changing something. This is a review, not an order. Thanks for the work on this so far, and the thought-provoking questions you've brought to WG meetings over the course of it. I hope this feedback helps to improve the doc. First, some broader thoughts: * Given that this mechanism really only makes sense for large uploads, the examples of 50-200 byte resources seem a bit *too* contrived. No one would use this for such tiny transfers, would they? Since you're not actually including the payload in this document, why not just use more realistic numbers thoughout? * References are made to the "server's" support for resumable uploads, but depending on how the server is architected, different resources might support partial uploads or not. I'd suggest modifying most instances to refer to the resource's support for resumable uploads, modulo the statement about what happens if all resources on a server support them with identical limits. (Which seems unlikely, as a broad statement.) * Given that Expect: 100-continue is also targeted at large uploads, please describe the interaction between 100 and 104 responses. Can a request both propose resumable uploads and include Expect: 100-continue? (I assume so.) Are there ordering requirements on the two interim responses? Should 104 also imply 100, since any 1xx code can be interpreted as 100? * Given the nature of delivery and buffers as connections are being dropped, it might be more accurate to say that the server "processes" rather than "receives" successful portions of the attempted upload, since some of the bytes might have been delivered and acknowledged at the transport layer, but not processed into the pending upload. Another instance where application semantics can't be inferred from transport state. * The Upload-Length header seems superfluous for requests which are neither Upload-Complete: ?0 nor to an upload resource nor chunked. If the client is attempting to upload the full body, Content-Length already provides this information, no? Regarding fetching the offset: * The use of 204 (No Content) surprises me, because the upload resource inherently does have content -- the bytes uploaded so far. The response to a HEAD request is supposed to be identical to what GET would have returned, except with no content. Presumably a GET to this resource would return a 200, not a 204, and the uploaded bytes? Given that this is a HEAD request, the body would not be transferred even on a 200, so that would seem the more natural response code. * Relatedly, Section 4.2 should describe what happens with GET requests to the request resource. Even if they're not needed as part of the upload flow, they almost certainly will happen occasionally as curious devs see these requests in network debugging tools and investigate what they are. Servers should have guidance on how to handle them. Regarding "prior knowledge" requests: The scenario in Section 3.2 seems dangerous to me. "Prior knowledge" is used to wave away the lack of a discovery step, but the client's prior knowledge might be wrong unless it's fresh. This would result in the client transferring what it knows to be a partial representation and a legacy server/resource attempting to process it as a complete one. How can we guard against this case? This reminds me of Expect: 100-continue in that the client really would like to know what the server is going to do before deciding how to proceed. (And I note that the authors made a similar comparison in Section 12.1.) Is there a way the client can proffer a partial upload in such a way that a legacy server will not see it as a completed request? It may be worth instead defining a mechanism to request an upload resource without including any initial content, since an empty payload will be less likely to be usable as the underlying media type. (Perhaps the application/partial-upload media type should be used here as well, to ensure a legacy server will not process it as the underlying media type? But in that case, how does the server eventually wind up with the correct media type of the upload?) Section 4.1.4 offers another option -- since the base resource is required to support OPTIONS, perhaps this example should explicitly show the client first making an OPTIONS request to determine whether this resource supports resumable uploads? This requirement on the base resource should probably get a little more emphasis, too. Maybe prior to Section 4 (Upload Resource), there should be a section that talks about differences in interacting with the base resource? See my related comment on 4.1.4. Section 1: * A pointer to what is meant by "canceled request" might be useful. An HTTP-naive reader might interpret this as the client deciding it doesn't wish to do the transfer any more, in which case why would it be resumed? Or just skip cancellation here -- the broken connection example suffices. You could even mention why connections get broken (e.g. client mobility, NAT reboot, etc.). Section 4: * I see that in Section 13, you talk about authentication/authorization of the upload resource. The mechanisms the server uses to perform this are probably out of scope, but the server's obligation needs to be mentioned. You also talk about making the URI of the upload resource difficult to guess, such that accessing it in the first place is some indication of authenticity. It's worth a forward reference to these requirements from Section 4, since they discuss the resource and how to implement it. Section 4.1: * In 4.1.1, how does the upload resource "lose[] representation data"? I would perhaps word this in terms of the server state, that if the server loses any part of the state it MUST remove the upload resource and not permit the client to resume it. * In 4.1.4, I'm surprised that keys with unexpected values are ignored rather than an error; does that mean I can include max-age="Really Long, I Swear" and the limit will still work? I commend the future-proofing of ignoring unknown keys, but I'd consider being stricter on keys you know the semantics of. * Most of Section 4.1.4 seems misplaced. Other than max-age, these are not limits of a particular upload resource (the topic of Section 4), but limits of the base resource's support of Resumable Uploads. This is indicated by the use of OPTIONS on the base resource to probe for these values. Consider separating Upload-Limit into properties of the base resource and properties of the upload resource, and pulling the properties of the base resource into their own section. Section 4.2: * In 4.2.1, stopping a request in mid-transfer has some version-specific complexities. See in particular this recent thread on the HTTP mailing list: https://lists.w3.org/Archives/Public/ietf-http-wg/2025JulSep/0088.html. A reference to specific mechanisms for doing so might be useful to an implementer, even if not formally a requirement for this spec. * 4.2.3 example D strikes me as strange. The server doesn't need to create an upload resource, since the client is sending the entire payload in one message and it was delivered. Wouldn't the server simply not send an interim response in this case and then send a 200 after processing the upload? The server only needs to send a 400 for refusal if the client didn't include the full payload, e.g. Upload-Complete: ?0. Section 4.3: * In 4.3.1, it might be reasonable for the client to require that the offset be no less than the last Upload-Offset that it received in interim responses during the previous upload. After all, we already said the client can discard that data. * In 4.3.1: "after rejecting the offset" appears to be an undefined client action. Should this be "if the offset is unacceptable"? Section 4.4: * In 4.4.1, the third and fourth paragraphs conflict. The fourth suggests that the client can wait to see that the server got the last byte before indicating the end of the upload to the server, but the third says that Upload-Complete: ?1 "is true" if the request goes to the final byte. Perhaps this should read "If its value is true, the end..." without claiming the inverse is true? * In 4.4.2, with what status code does the server reject appending to an already-completed upload? 409 might be reasonable here as well, since it's a conflict with the state of the upload; 410 (Gone) might also be reasonable since the upload facility is no longer available at that URI. * In 4.4.3, while the client can correctly infer that the offset is now 200, I'm a little surprised that the 204 response doesn't also include Upload-Offset: 200. * You might consider splitting out part of 4.4 (Append) to a new Upload Completion section, so that 4.4 can focus on handling these interim exchanges. In Section 10.1, regarding integrity verification, could Repr-Digest also be on the HEAD of the upload resource? In Section 11, an example of an "appropriate header field" might be useful. Location, I'd assume? ===NITS FOLLOW=== * 4.3.3, B: "on" => "an" * 4.4.1: * "accept request" => "accept the request" * "not the entire... was transferred" => "the entire... was not transferred" * 4.4.2: "stopping to append bytes..., rejecting the request" => "rejecting requests to append..." perhaps? * 4.3.3 and 4.4.3 titles: "Example" => "Examples" * 4.6: "well behaving" => "well-behaved" * 5: "receive" => "received" * 11: "similar" => "similarly"; "request, which" => "request that" * 12.1: "received" => "receives" * 12.1.1: "offer the server" => "offer" or perhaps "invite the server"? Thanks, Mike Bishop (with hat in my pocket) (Note that this is not officially "the AD Review," but as I'm the AD and this is a review, I'll have a simpler time doing the AD review by looking at the diff versus this version and you'll probably get fewer comments at that point as a result.) ________________________________ From: Tommy Pauly <tpauly@apple.com> Sent: Wednesday, August 20, 2025 7:09 PM To: Working Group HTTP <ietf-http-wg@w3.org> Subject: Re: Working Group Last Call: draft-ietf-httpbis-resumable-upload-09 As a reminder, we do have the WGLC open for draft-ietf-httpbis-resumable-upload. The chairs would like to see more input and reviews of the document still, so please do send those in when possible. Thanks, Tommy On Jul 29, 2025, at 7:51 PM, Tommy Pauly <tpauly@apple.com> wrote: Hello HTTP, This email starts a working group last call for draft-ietf-httpbis-resumable-upload-09. This draft was presented at IETF 123, and has no remaining open issues. You can find the draft here: https://datatracker.ietf.org/doc/draft-ietf-httpbis-resumable-upload/ https://www.ietf.org/archive/id/draft-ietf-httpbis-resumable-upload-09.html Please send your review and comments in response to this email, and file issues to https://github.com/httpwg/http-extensions/issues. This call will be open for three weeks, until Wednesday, August 20, 2025. Best, Tommy
Received on Friday, 22 August 2025 21:25:11 UTC