tus / tus-js-client

A pure JavaScript client for the tus resumable upload protocol
https://tus.io/
MIT License
2.12k stars 316 forks source link

Provide last response to `onSuccess` callback #689

Closed netdown closed 3 months ago

netdown commented 6 months ago

Support using customized responses as introduced in tus/tus-node-server#615

Acconut commented 6 months ago

Thank you for this PR, but I am concerned that this is too confusing for users. The response that is passed to onSuccess this way might be a POST, PATCH, or HEAD response depending on when the upload is finished. If users expect the value in onSuccess to always be the last PATCH request, then they will run into issues. Instead we commend people to use the onAfterResponse callback, which provides access to all responses and also makes it clear that there might be multiple requests involved in the upload process. Does this not work for you?

netdown commented 6 months ago

Indeed I wasn't cautious enough. What if the argument is only passed for post and patch requests' events? Or maybe like { requestMethod: 'PATCH'|'POST'|'HEAD', response: HttpResponse };

My goal is being able to access response data in Uppy's complete event using uppy.getFiles(). Unfortunately neither headers nor status code (actually the response object contains a status code, but the value is hard coded to 200) are returned using tus, so I know nothing but the upload url.

Acconut commented 6 months ago

Have you tried the onAfterResponse callback? Did that not work for you? It should also be usable from Uppy.

netdown commented 6 months ago

It feels really hacky that I'd need to decide which response is a success response and store them in a custom state, then at the complete handler, make sure my state is actually in sync with uppy's state, find the appropriate response for each file, and make sure uppy processing haven't failed for the responses I assumed to be ok. Seems too complicated and prone to bugs while it could be solved by passing the response. Are you sure the object signature I presented is not suitable?

Acconut commented 6 months ago

Are you sure the object signature I presented is not suitable?

No, I am not very sure and cannot guarantee that my opinion doesn't change :) I am trying to considering the bigger picture here and how we can improve the overall approach. The problem is that in tus, there is no standardized way of sending information from the server back to the client as tus focuses on uploads where the client sends data to the server. This has lead to the current situation where additional data from the server is added to PATCH responses for clients to retrieve. But this is not ideal because the information in these responses cannot be re-retrieved if the clients needs to fetch it again. So overall, I would like to have a more holistic approach for sending data from the server, which solves this problem in a proper way without shortcomings. Some discussion on this has happened in https://github.com/tus/tus-resumable-upload-protocol/issues/190.

Therefore, I would like to reserve a future argument for onSuccess to be whatever approach we come up with there instead of using it right now for the last response right now, which might not make sense in the future. Is that understandable?

netdown commented 6 months ago

I regret to hear. I briefly checked the discussion, and I would like to point out that IMO - and if I'm not mistaken - forcing Content-Location raises a pointless obstacle in most use cases. Storing the tus upload id and creating a separate endpoint just to be able to pass the final id to the client does not make sense. I don't care about tus id nor I want to let the client requery anything, I just want to know the id returned from my server, which seems to be the most common use case.

Additionally, I'm not sure requerying some data about the uploaded file is not out of tus territory. The upload has been completed, why bother post-upload logic? Just make the headers and body available to the client, so multiple approaches can be implemented.

Acconut commented 5 months ago

I can understand that an extra round trip for fetching the Content-Location resource is not desired in your case. You will always have the ability to add custom headers to responses and retrieve them on the client side to implement custom logic.

Additionally, I'm not sure requerying some data about the uploaded file is not out of tus territory. The upload has been completed, why bother post-upload logic?

That's definitely a question worth asking and my opinioned in the past year has developed to be that tus implementations should assist you with postprocessing in some way as this makes file handling in applications more straightforward, robust and seamsless. Of course, that doesn't mean that we have to offer a full solution for postprocessing files. But these questions come up very often and I would prefer if we can offer some answer. Using them is then up to each person on their own.

Acconut commented 5 months ago

I have continued thinking about this and changed my opinion on the original proposal of including the last response in the onSuccess callback. It will be useful to other users and save them from having to implement the method using onAfterResponse. However, I would prefer if the last response was not passed directly as the argument to onSuccess but instead inside another object, such as:

onSuccess({
  lastResponse: resp
})

This will allow us to extend the information passed to onSuccess in the future if we choose to do so.

Would you be willing to make these adjustments? I can then also help you with the necessary tests and documentation updates.

netdown commented 3 months ago

Sorry for the late reply. I have modified the signature and added a test.

netdown commented 3 months ago

All done.