w3c / websub

WebSub Spec in Social Web Working Group
https://w3c.github.io/websub/
287 stars 51 forks source link

Allow a subscriber to expire a subscription using an HTTP response code #103

Closed aaronpk closed 7 years ago

aaronpk commented 7 years ago

I'm not sure if this came up only because of the type of subscriber I'm creating (the websub.rocks test suite), but I'm finding myself wanting a way for the subscriber to indicate its subscription should be deleted by returning a specific HTTP response code.

Right now the spec says:

The successful response from the subscriber's callback URL must be an HTTP [RFC7231] success (2xx) code. The hub must consider all other subscriber response codes as failures;

It then continues to say:

Hubs should retry notifications up to self-imposed limits on the number of times and the overall time period to retry.

This means that if the subscriber receives a notification it doesn't want (e.g. it knows it has re-subscribed to this topic with a new callback URL), it has no way to tell the hub to stop delivering those notifications. If the subscriber returns a 4xx code, the hub will retry the delivery again.

I think it would be useful if there was a mechanism for the subscriber to indicate to the hub "no I really don't want any more notifications at this callback URL anymore, this is not a temporary failure, please go away."

@julien51 have you seen this come up before? Any suggestions?

aaronpk commented 7 years ago

Currently the best I can think of is returning HTTP 404 and making sure that it doesn't take a lot of resources in order to determine that response. That way it doesn't really bother the subscriber to be getting these pings. However this is definitely wasting resources of the hub, since it would be better if the hub just stopped sending these.

julien51 commented 7 years ago

Well the subscriber can very well send an unsubscription request?

On May 9, 2017, 5:38 PM, at 5:38 PM, Aaron Parecki notifications@github.com wrote:

I'm not sure if this came up only because of the type of subscriber I'm creating (the websub.rocks test suite), but I'm finding myself wanting a way for the subscriber to indicate its subscription should be deleted by returning a specific HTTP response code.

Right now the spec says:

The successful response from the subscriber's callback URL must be an HTTP [RFC7231] success (2xx) code. The hub must consider all other subscriber response codes as failures;

It then continues to say:

Hubs should retry notifications up to self-imposed limits on the number of times and the overall time period to retry.

This means that if the subscriber receives a notification it doesn't want (e.g. it knows it has re-subscribed to this topic with a new callback URL), it has no way to tell the hub to stop delivering those notifications. If the subscriber returns a 4xx code, the hub will retry the delivery again.

I think it would be useful if there was a mechanism for the subscriber to indicate to the hub "no I really don't want any more notifications at this callback URL anymore, this is not a temporary failure, please go away."

@julien51 have you seen this come up before? Any suggestions?

-- You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub: https://github.com/w3c/websub/issues/103

aaronpk commented 7 years ago

In my case, there isn't really an appropriate time to send the unsubscription request. I'm also imagining this situation:

If I had to pick an HTTP response code, I think 410 would be most appropriate. Since we recommend capability URLs, this essentially indicates that this particular capability URL has been deleted.

This would be easily implemented by storing unique tokens in a cache, and when they disappear from the cache, the endpoint would return 410.

julien51 commented 7 years ago

Generally the recommended adjust was to return 200 for every notification and then prices the payload (including signature verification...etc) asynchronously...

On May 9, 2017, 5:48 PM, at 5:48 PM, Julien Genestoux julien.genestoux@gmail.com wrote:

But why wouldn't the subscriber return 200 a and unsubscribe immediately? The 200 is just "thanks I received what you sent".

On May 9, 2017, 5:45 PM, at 5:45 PM, Aaron Parecki notifications@github.com wrote:

Currently the best I can think of is returning HTTP 404 and making sure that it doesn't take a lot of resources in order to determine that response. That way it doesn't really bother the subscriber to be getting these pings. However this is definitely wasting resources of the hub, since it would be better if the hub just stopped sending these.

-- You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub: https://github.com/w3c/websub/issues/103#issuecomment-300311168

julien51 commented 7 years ago

But why wouldn't the subscriber return 200 a and unsubscribe immediately? The 200 is just "thanks I received what you sent".

On May 9, 2017, 5:45 PM, at 5:45 PM, Aaron Parecki notifications@github.com wrote:

Currently the best I can think of is returning HTTP 404 and making sure that it doesn't take a lot of resources in order to determine that response. That way it doesn't really bother the subscriber to be getting these pings. However this is definitely wasting resources of the hub, since it would be better if the hub just stopped sending these.

-- You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub: https://github.com/w3c/websub/issues/103#issuecomment-300311168

aaronpk commented 7 years ago

That's fine, this still applies in that case. If the subscriber gets a notification at /callback?id=1234567890123456780 and 1234567890123456780 isn't in the cache, it can reject the notification even before starting an asynchronous processing job.

tonyg commented 7 years ago

Since the hub must supply hub.lease_seconds during verification-of-subscription-intent, and must not lie, then if the subscriber treats the notification after 300 seconds but before 86400 seconds as invalid, then one way to look at it is that the subscriber is at fault for having ignored the hub.lease_seconds it was told about. So, in principle, the subscriber should always be able to issue an unsubscribe request.

That said, I think it'd be more robust to treat a 4xx response[*] as an implicit unsubscription request. (Of course a 5xx might still be some kind of transient error.)

[*] Or at least those considered "permanent client errors"; so for example, 408 and 413 might not imply unsubscription...

julien51 commented 7 years ago

I think your case is not valid; the subscriber should take into account the lease that the hub returned... But it that happens

The hub delivers a notification after the 300 seconds has elapsed, so the subscriber treats the notification as invalid, and will always reject those notifications in the future, up until the hub stops sending them after 86400 seconds

Then the subscriber should return 200 and just unsubscribe from the resource.

I really want to make sure that there is no way to misinterpret what the subscriber returns on notifications. Having multiple responses is adding complexity and potential for errors. Also I am in favor of only have one way to do one thing rather than 2 ways to achieve the same result (unsubscribing).

julien51 commented 7 years ago

That said, I think it'd be more robust to treat a 4xx response[*] as an implicit unsubscription request. (Of course a 5xx might still be some kind of transient error.)

I would strongly disagree with that. I have seen services returning 4XX when they were down. For example, a feed service which shall renamed unamed had a database issue at some point, but the app server was fine. The result was that it was no finding the content of the feed in database and assumed that the feed was then 'Nt found'... when in reality it was just that their datastore was broken.

However I strongly agree with the first part of the comment.

I really don't see why the 200 + unsubscribe approach is not working?

aaronpk commented 7 years ago

the subscriber is at fault for having ignored the hub.lease_seconds it was told about

True, I hadn't thought of the fact that the hub would tell me the lease duration it issued.

I have seen services returning 4XX when they were down.

Yes I definitely don't want all 4xx errors to be treated as an unsubscription request, for exactly this reason. If anything, just a very specific code should be considered an expiration, like the 410 I suggested. (It is unlikely anything would accidentally return HTTP 410.)

That said, I fully admit this may be a very unusual case that exists only because I'm writing the test suite rather than a "normal" subscriber.

aaronpk commented 7 years ago

After some more thought, I think I'm okay with the existing mechanism of making an explicit unsubscribe request if the subscriber wants, since the hub will have indicated the lease duration in the initial subscription. I'm going to chalk up the idea for this due to the fact that I was writing the test suite which has very different requirements from a typical subscriber.