mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-01-20 21:28:48 +01:00
Special-case 400 errors other than 408/429
Most client errors should remove the subscription.
This commit is contained in:
parent
48e87ed470
commit
d1f0e0f449
@ -218,13 +218,34 @@ func (r *realSender) sendToSubscription(
|
|||||||
_ = resp.Body.Close()
|
_ = resp.Body.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// If there's an error, log the response.
|
|
||||||
if resp.StatusCode < 200 || resp.StatusCode > 299 {
|
if resp.StatusCode < 200 || resp.StatusCode > 299 {
|
||||||
|
if resp.StatusCode >= 400 && resp.StatusCode <= 499 &&
|
||||||
|
resp.StatusCode != http.StatusRequestTimeout &&
|
||||||
|
resp.StatusCode != http.StatusTooManyRequests {
|
||||||
|
// We should not send any more notifications to this subscription. Try to delete it.
|
||||||
|
if err := r.state.DB.DeleteWebPushSubscriptionByTokenID(ctx, subscription.TokenID); err != nil {
|
||||||
|
return gtserror.Newf(
|
||||||
|
"received HTTP status %s but failed to delete subscription: %s",
|
||||||
|
resp.Status,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
log.Infof(
|
||||||
|
ctx,
|
||||||
|
"Deleted Web Push subscription with token ID %s because push server sent HTTP status %s",
|
||||||
|
subscription.TokenID,
|
||||||
|
resp.Status,
|
||||||
|
)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, try to get the response body.
|
||||||
bodyBytes, err := io.ReadAll(io.LimitReader(resp.Body, responseBodyMaxLen))
|
bodyBytes, err := io.ReadAll(io.LimitReader(resp.Body, responseBodyMaxLen))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return gtserror.Newf("error reading Web Push server response: %w", err)
|
return gtserror.Newf("error reading Web Push server response: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Log the error with its response body.
|
||||||
return gtserror.Newf(
|
return gtserror.Newf(
|
||||||
"unexpected HTTP status %s received when sending Web Push notification: %s",
|
"unexpected HTTP status %s received when sending Web Push notification: %s",
|
||||||
resp.Status,
|
resp.Status,
|
||||||
|
@ -178,9 +178,12 @@ func (rc *notifyingReadCloser) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *RealSenderStandardTestSuite) TestSendSuccess() {
|
// Simulate sending a push notification with the suite's fake web client.
|
||||||
// Set a timeout on the whole test. If it fails due to the timeout,
|
func (suite *RealSenderStandardTestSuite) simulatePushNotification(
|
||||||
// the push notification was not sent for some reason.
|
statusCode int,
|
||||||
|
expectDeletedSubscription bool,
|
||||||
|
) error {
|
||||||
|
// Don't let the test run forever if the push notification was not sent for some reason.
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
@ -193,17 +196,17 @@ func (suite *RealSenderStandardTestSuite) TestSendSuccess() {
|
|||||||
bodyClosed: make(chan struct{}, 1),
|
bodyClosed: make(chan struct{}, 1),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simulate a successful response from the Web Push server.
|
// Simulate a response from the Web Push server.
|
||||||
suite.webPushHttpClientDo = func(request *http.Request) (*http.Response, error) {
|
suite.webPushHttpClientDo = func(request *http.Request) (*http.Response, error) {
|
||||||
return &http.Response{
|
return &http.Response{
|
||||||
Status: "200 OK",
|
Status: http.StatusText(statusCode),
|
||||||
StatusCode: 200,
|
StatusCode: statusCode,
|
||||||
Body: rc,
|
Body: rc,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the push notification.
|
// Send the push notification.
|
||||||
suite.NoError(suite.webPushSender.Send(ctx, notification, nil, nil))
|
sendError := suite.webPushSender.Send(ctx, notification, nil, nil)
|
||||||
|
|
||||||
// Wait for it to be sent or for the context to time out.
|
// Wait for it to be sent or for the context to time out.
|
||||||
bodyClosed := false
|
bodyClosed := false
|
||||||
@ -216,6 +219,42 @@ func (suite *RealSenderStandardTestSuite) TestSendSuccess() {
|
|||||||
}
|
}
|
||||||
suite.True(bodyClosed)
|
suite.True(bodyClosed)
|
||||||
suite.False(contextExpired)
|
suite.False(contextExpired)
|
||||||
|
|
||||||
|
// Look for the associated Web Push subscription. Some server responses should delete it.
|
||||||
|
subscription, err := suite.state.DB.GetWebPushSubscriptionByTokenID(
|
||||||
|
ctx,
|
||||||
|
suite.testWebPushSubscriptions["local_account_1_token_1"].TokenID,
|
||||||
|
)
|
||||||
|
if expectDeletedSubscription {
|
||||||
|
suite.ErrorIs(err, db.ErrNoEntries)
|
||||||
|
} else {
|
||||||
|
suite.NotNil(subscription)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sendError
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test a successful response to sending a push notification.
|
||||||
|
func (suite *RealSenderStandardTestSuite) TestSendSuccess() {
|
||||||
|
suite.NoError(suite.simulatePushNotification(http.StatusOK, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test a rate-limiting response to sending a push notification.
|
||||||
|
// This should not delete the subscription.
|
||||||
|
func (suite *RealSenderStandardTestSuite) TestRateLimited() {
|
||||||
|
suite.NoError(suite.simulatePushNotification(http.StatusTooManyRequests, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test a non-special-cased client error response to sending a push notification.
|
||||||
|
// This should delete the subscription.
|
||||||
|
func (suite *RealSenderStandardTestSuite) TestClientError() {
|
||||||
|
suite.NoError(suite.simulatePushNotification(http.StatusBadRequest, true))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test a server error response to sending a push notification.
|
||||||
|
// This should not delete the subscription.
|
||||||
|
func (suite *RealSenderStandardTestSuite) TestServerError() {
|
||||||
|
suite.NoError(suite.simulatePushNotification(http.StatusInternalServerError, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRealSenderStandardTestSuite(t *testing.T) {
|
func TestRealSenderStandardTestSuite(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user