RESUMABLE: Redefine Upload-Complete on the server side#3404
RESUMABLE: Redefine Upload-Complete on the server side#3404guoye-zhang wants to merge 15 commits into
Conversation
smatsson
left a comment
There was a problem hiding this comment.
I like the idea here but I think the PR needs a bit more to be fully understandable.
The biggest issue for me is that Upload-Complete: ?1 in a response no longer means what the name implies, that the upload is complete. It now means "Stop sending data, we are done here". I think that this change deserves more than a side note. A reader coming to this fresh will be confused.
It would definitely help to have some examples e.g. showing the early response case and what the client should do when it receives Upload-Complete: ?1 midway through the upload.
|
@smatsson I updated one of the examples to show this in action. What do you think? |
|
@guoye-zhang Thanks for the update! Still not convinced of the wording.
Why is this important to mention? It seems like an implementation detail to me. For an event based implementation (tusdotnet, tusd etc) the "teporary upload resource" could very well cause this case by user action in an event. Why not just simplify it and say that the server can cancel the entire upload by sending a response with It would not hurt to add a sentence on what the expectations are from the client as well, given that this is what started the discussion in the other issue, e.g.
|
|
The reason I mentioned it is that we implemented resumable upload as a middleware. To the application at the top, it's just a regular upload and they don't need to be aware of the temporary upload resource at all. The responses with |
|
@guoye-zhang Thanks for the clarification! While I understand that this makes sense for your specific middleware architecture, stating that the header "distinguishes the response from the initial targeted resource or the temporary upload resource" is completely irrelevant for other types of implementations. Including this kind of implementation specific detail in the specification only creates confusion for anyone who hasn't built their server with the exact same architecture. We should just strictly define the protocol behavior over the wire and not add internal details about how different software layers process headers in a specific system. It would be much clearer if the entire mention of "initial targeted" and "temporary upload" resources were just dropped. It's confusing because the draft already uses the terms "temporary resource" and "upload resource" to mean the URL returned in the Location header, see 3. Overview:
|
|
I want to clarify that the phrasing isn't about implementation details; it's about response semantics and isn't irrelevant depending on architecture. Let's suppose you create an upload using But I'm not arguing the phrasing is necessary, just adding this clarification about the intent behind it to inform your judgment. Personally, I am undecided on whether it's necessary. If we do keep it, it's probably a good idea to change the phrasing to make this clearer. Or alternatively, come up with different semantics that create the same effect. |
|
@GrantGryczan I completely understand the underlying use case here. The client needs to know whether an error occurred during the actual byte transfer (meaning they might be able to resume/retry) or during the final processing of the completed payload (meaning the transfer phase is over, but backend processing failed). My issue is that the current phrasing in the draft is still unclear and messy. Trying to explain this by saying the response conceptually "comes from the initial targeted resource" rather than the "temporary upload resource" is an abstract and confusing way to describe it. Describing it this way leaks implementation details into the protocol, and as mentioned earlier, it also clashes with the terminology already established in Section 3. Instead of describing which internal resource is supposedly answering, wouldn't it be much clearer to just describe what this means for the state of the upload? Something along the lines of:
This achieves the exact same goal for the client but focuses on concrete protocol behavior rather than abstract backend architecture. |
|
Again, this is completely independent from how it's implemented or any backend architecture. It's just about response semantics. It's saying:
These are just examples. The point is that all semantics that would otherwise apply to a response from the initial resource must also apply to an To reiterate, this has nothing to do with backend architecture. In my backend implementation, I personally plan to implement the final complete response as coming from the same function that handles responses for the upload resource. There won't be any middleware or whatever. But the data that function generates for the response is still obliged to obey whatever semantics are defined for the initial resource. Perhaps this is not the best way to communicate this effect, but my point is just that it's certainly not about implementation details. It's defining a contract that the interface must follow. Merely specifying whether the upload can be resumed or retried does not communicate the same contract. |
|
Also, regarding @smatsson's initial feedback:
This is a fair point. Would it be a good idea to rename |
|
I thought about renaming it, ultimately concluded that keeping the same is the right decision for a few reasons:
|
|
What about keeping both explanations? Saying that |
|
That could work, but I still think the phrasing of the current explanation needs refining. |
I agree with this. My issue is just that the current phrasing in the draft doesn't actually say that. "distinguishes from the initial targeted resource" sounds like internal server routing, not HTTP semantics.
I think this is a good addition and I agree with you that the name should stay intact as the other names mean the same thing. |
|
What about now? @GrantGryczan @smatsson |
|
This is better, but I think it still doesn't make much sense to say a response comes from the temporary upload resource. As I said in my previous review, if a client creates a resumable upload with Furthermore, I suspect Stefan's criticism still applies to the "distinguishes the response from the initial targeted resource or the temporary upload resource", "response is from", and "targeted resource decides to generate" phrasings. I think those should probably be replaced or removed entirely, because framing it in terms of which semantics apply is much less ambiguous. I'll defer to Stefan. |
|
I rephrased it by avoiding mentioning the upload resource |
|
|
||
| An upload is marked as completed if a request for creating the upload resource ({{upload-creation}}) or appending to it ({{upload-appending}}) included the `Upload-Complete` header field with a true value and the request content was fully processed. | ||
|
|
||
| The `Upload-Complete` response header field distinguishes the response from the initial targeted resource or the temporary upload resource. The value of true means the response is from the initial targeted resource, and the value of false means the response is from the temporary upload resource. It is worth noting that `Upload-Complete` can be true even when the full representation data was not received if the targeted resource decides to generate an early response. |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
|
|
||
| An upload is marked as completed if a request for creating the upload resource ({{upload-creation}}) or appending to it ({{upload-appending}}) included the `Upload-Complete` header field with a true value and the request content was fully processed. | ||
|
|
||
| The `Upload-Complete` response header field distinguishes the response from the initial targeted resource or the temporary upload resource. The value of true means the response is from the initial targeted resource, and that the semantics of the targeted resource apply; the value of false means the response is from the temporary upload resource, and the semantics of the resumable upload protocol apply. It is worth noting that `Upload-Complete` can be true even when the full representation data was not received if the targeted resource decides to generate an early response. The client SHOULD NOT perform upload resumption to the upload resource after receiving a response with the `Upload-Complete` field value set to true. |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
|
Nice work! I think this is great. Let's see what Stefan thinks. |
Co-authored-by: Grant Gryczan <grantgryczan@gmail.com>
|
|
||
| An upload is marked as completed if a request for creating the upload resource ({{upload-creation}}) or appending to it ({{upload-appending}}) included the `Upload-Complete` header field with a true value and the request content was fully processed. | ||
|
|
||
| The `Upload-Complete` response header field signals whether the response comes from the initial targeted resource. The value of true means that the semantics of the targeted resource apply, and the value of false means that the semantics of the resumable upload protocol apply. It is worth noting that `Upload-Complete` can be true even when the full representation data was not transmitted in the case that the server decides to generate an early response when processing the targeted resource. The client SHOULD NOT perform upload resumption to the upload resource after receiving a response with the `Upload-Complete` field value set to true. |
There was a problem hiding this comment.
Should we mention the possibility of an early response in the sections for PATCH and/or HEAD as well?
There was a problem hiding this comment.
I added Upload-Complete back as a SHOULD but realized that it was removed earlier in draft 10. Does the change make sense?
| ~~~ | ||
|
|
||
| D) The following example shows an upload creation being rejected by the server because uploads to the targetted resource are not allowed. The client cannot continue the upload. | ||
| D) The following example shows an upload creation being rejected by the server because uploads to the targeted resource are not allowed. The Upload-Complete header in the response is set to true since the server is uninterested in receiving the full representation and the upload is complete in its perspective. The client cannot continue the upload. |
There was a problem hiding this comment.
I'm unsure this is a good example for an early response. A 4XX response usually marks the end of an upload regardless of the presence of the Upload-Complete: ?1 header. IMO the value of early responses isn't visible in error responses, but actually successful responses. Could we have an example where the early response is 2XX because the targeted resource already received all the representation it needed to generate a response?
There was a problem hiding this comment.
I personally think an early 2XX response in the wild would be extremely rare. Supporting error responses that interrupt an upload is probably going to be the most common use case for early responses, and there's no reason an example couldn't reflect that well. Though I agree this in particular is not the best example of that, since the error response here is the very first response, so in a sense, it's not really "interrupting" the upload, just preventing it from starting in the first place.
There was a problem hiding this comment.
Yes, the most common cases for early responses are failures (401 unauthorized for example), and it's usually at the very beginning of the request. I think this example is fine for showcasing that Upload-Complete can be false in the request but true in the response. Or do we want an edge case example showing a particular pattern?
There was a problem hiding this comment.
the most common cases for early responses are failures (401 unauthorized for example)
In my mental model, these authentication failures would be raised before an upload resource is even allocated. But this might be different depending on your implementation.
One example for an early error response that's slightly different is when a content-encoded representation (e.g. Content-Encoding: gzip) is uploaded and a decoding failure occurs. If the resource receives invalid gzip data at some point, it can decide to end the upload with an early response because it cannot recover the decoded representation.
There was a problem hiding this comment.
I changed the example to corrupted gzip
There was a problem hiding this comment.
I think, ideally, if the example is intended to demonstrate the significance of early responses, then the error should occur after the upload resource has been successfully created (even if that's less common), in response to an upload append.
There was a problem hiding this comment.
Add a 104 to the example
Co-authored-by: Lucas Pardue <lucas@lucaspardue.com>
|
@guoye-zhang Much clearer now, thanks! The update resolves my concerns. |
Co-authored-by: Grant Gryczan <grantgryczan@gmail.com>
| ~~~ | ||
|
|
||
| D) The following example shows an upload creation being rejected by the server because uploads to the targetted resource are not allowed. The client cannot continue the upload. | ||
| D) The following example shows an upload creation being rejected by the server because the request content cannot be decoded. The Upload-Complete header in the response is set to true since the server is uninterested in receiving the full representation after the decoding failure and the upload is complete in its perspective. The client cannot continue the upload. |
There was a problem hiding this comment.
Nit: fixed formatting.
| D) The following example shows an upload creation being rejected by the server because the request content cannot be decoded. The Upload-Complete header in the response is set to true since the server is uninterested in receiving the full representation after the decoding failure and the upload is complete in its perspective. The client cannot continue the upload. | |
| D) The following example shows an upload creation being rejected by the server because the request content cannot be decoded. The `Upload-Complete` header in the response is set to true since the server is uninterested in receiving the full representation after the decoding failure and the upload is complete in its perspective. The client cannot continue the upload. |
|
Something seems off about these new semantics. I'm concerned about the error responses specified by the resumable upload protocol: mismatching offset, completed upload, and inconsistent length. If the upload was already completed, then what should
If we decide one of these is best, I think it should be recommended explicitly in the draft. I would not be surprised if servers mistakenly choose a bad value here, since this situation is confusing. We could also carve out an exception in the new definition to allow just these error responses to use Another example of this is offset retrieval responses, which use |
Discussed during IETF125. Refining the
Upload-Completeresponse header to differentiate the final response from the responses from the upload resource. Also allowing the final response to arrive early.Resolves #3398