Right now, the specification says following about the Tus-Resumable header:
The Tus-Resumable header MUST be included in every request and response except for OPTIONS requests. The value MUST be the version of the protocol used by the Client or the Server.
If the version specified by the Client is not supported by the Server, it MUST respond with the 412 Precondition Failed status and MUST include the Tus-Version header into the response. In addition, the Server MUST NOT process the request.
The idea was that Tus-Resumable is used by the Server to know what version of the protocol the Client is using, similar to how HTTP/1.0 or HTTP/1.1 is included in HTTP requests.
However, most Servers implement the version check by simply testing if the Tus-Resumable header matches exactly 1.0.0 since this is the only published version of tus 1.x (I hope to release 1.1 soon but the issue I am describing here has prevented us from doing so). I am also guilty of this, since tusd implements this naive check as well: https://github.com/tus/tusd/blob/26b84bcb1c818f95ea236fbfe1c43e47c32574ab/pkg/handler/unrouted_handler.go#L264. This check has not been an issue in the past but will be if we publish a new version of the protocol:
So, let's assume tus 1.1 is available and a new client supporting tus 1.1 wants to contact a tus 1.0 server. According to the current specification, the client must set Tus-Resumable: 1.1.0 but the server only accepts Tus-Resumable: 1.0.0 and will reject the request. In turn, this makes it impossible for the tus 1.1 client to communicate with the tus 1.0 server which should be possible since tus 1.1 must not be a breaking change. In theory, you could argue that the specification implies that the server must parse the Tus-Resumable header as a SemVer declaration (https://semver.org/) and then check if the client's version is compatible with the server's version. With this understanding we could say that servers, such as tusd, do not correctly implement the specification and must be changed.
However, we must also acknowledge that there is a vast collection of tus servers in production that use this incorrect version check. These servers may not be updated to use a correct version check in the near future making it impossible to use them with tus 1.1 clients once they are available. We should avoid such a situation if possible. I hope this problem is understandable. If not, please let me know.
This leads to following question:
Do we want to keep the current definition of Tus-Resumable and cause compatibility issues between tus 1.1 clients and tus 1.0 servers? Or do we want to change the definition and avoid these issues?
I see following possible answers:
- Keep the current definition and adjust the implementations. The implementations have a wrong version check and so they must be addressed instead of changing the protocol.
- Change the specification to only include the major version in Tus-Resumable, i.e. only
1.0.0, 2.0.0 and so on. This makes the current naive version check compatible with the specification. Clients always set Tus-Resumable: 1.0.0 and Servers always accept that. Now, what if a client wants to use a new feature in tus 1.1? How does a server know that it should handle the request according to tus 1.1? I would argue that the server does not need the Tus-Resumable header to determine that. Since tus 1.1 is compatible with tus 1.0, a client must always use a specific header or a specific extension to use a new feature. A tus 1.0 server will simply ignore these headers or extensions since it does not know them. A tus 1.1 on the other hand, recognizes these headers or extension and therefore knows what the client is talking about. The Tus-Resumable header is not needed in this scenario.
Are there any other possible solution that I forgot? Or is my argumentation flawed? I am happy about any feedback!
This issue has been brought up before (see #96; I laid out similar reasons in the original comment there) but the discussion never really ended in an agreement (that's my fault) so I wanted to bring it back to hopefully resolve it this time.
/cc @nigoroll @smatsson
Right now, the specification says following about the Tus-Resumable header:
The idea was that Tus-Resumable is used by the Server to know what version of the protocol the Client is using, similar to how
HTTP/1.0orHTTP/1.1is included in HTTP requests.However, most Servers implement the version check by simply testing if the Tus-Resumable header matches exactly
1.0.0since this is the only published version of tus 1.x (I hope to release 1.1 soon but the issue I am describing here has prevented us from doing so). I am also guilty of this, since tusd implements this naive check as well: https://github.com/tus/tusd/blob/26b84bcb1c818f95ea236fbfe1c43e47c32574ab/pkg/handler/unrouted_handler.go#L264. This check has not been an issue in the past but will be if we publish a new version of the protocol:So, let's assume tus 1.1 is available and a new client supporting tus 1.1 wants to contact a tus 1.0 server. According to the current specification, the client must set
Tus-Resumable: 1.1.0but the server only acceptsTus-Resumable: 1.0.0and will reject the request. In turn, this makes it impossible for the tus 1.1 client to communicate with the tus 1.0 server which should be possible since tus 1.1 must not be a breaking change. In theory, you could argue that the specification implies that the server must parse the Tus-Resumable header as a SemVer declaration (https://semver.org/) and then check if the client's version is compatible with the server's version. With this understanding we could say that servers, such as tusd, do not correctly implement the specification and must be changed.However, we must also acknowledge that there is a vast collection of tus servers in production that use this incorrect version check. These servers may not be updated to use a correct version check in the near future making it impossible to use them with tus 1.1 clients once they are available. We should avoid such a situation if possible. I hope this problem is understandable. If not, please let me know.
This leads to following question:
I see following possible answers:
1.0.0,2.0.0and so on. This makes the current naive version check compatible with the specification. Clients always setTus-Resumable: 1.0.0and Servers always accept that. Now, what if a client wants to use a new feature in tus 1.1? How does a server know that it should handle the request according to tus 1.1? I would argue that the server does not need the Tus-Resumable header to determine that. Since tus 1.1 is compatible with tus 1.0, a client must always use a specific header or a specific extension to use a new feature. A tus 1.0 server will simply ignore these headers or extensions since it does not know them. A tus 1.1 on the other hand, recognizes these headers or extension and therefore knows what the client is talking about. The Tus-Resumable header is not needed in this scenario.Are there any other possible solution that I forgot? Or is my argumentation flawed? I am happy about any feedback!
This issue has been brought up before (see #96; I laid out similar reasons in the original comment there) but the discussion never really ended in an agreement (that's my fault) so I wanted to bring it back to hopefully resolve it this time.
/cc @nigoroll @smatsson