GRPC: Log user-initiated cancellations as HTTP 408 (#5546)
- Log user-initiated cancellations as HTTP 408 instead of HTTP 500 - Only check status code of `err` if an error was intercepted Fixes #5444
This commit is contained in:
parent
0be4679a9b
commit
631f6dfa0c
|
@ -15,6 +15,7 @@ import (
|
|||
"google.golang.org/grpc/status"
|
||||
|
||||
berrors "github.com/letsencrypt/boulder/errors"
|
||||
"github.com/letsencrypt/boulder/probs"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -201,12 +202,15 @@ func (ci *clientInterceptor) intercept(
|
|||
err := invoker(localCtx, fullMethod, req, reply, cc, opts...)
|
||||
if err != nil {
|
||||
err = unwrapError(err, respMD)
|
||||
}
|
||||
if status.Code(err) == codes.DeadlineExceeded {
|
||||
return deadlineDetails{
|
||||
service: service,
|
||||
method: method,
|
||||
latency: ci.clk.Since(begin),
|
||||
switch status.Code(err) {
|
||||
case codes.DeadlineExceeded:
|
||||
return deadlineDetails{
|
||||
service: service,
|
||||
method: method,
|
||||
latency: ci.clk.Since(begin),
|
||||
}
|
||||
case codes.Canceled:
|
||||
return probs.Canceled(err.Error())
|
||||
}
|
||||
}
|
||||
return err
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"errors"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -16,9 +17,11 @@ import (
|
|||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/letsencrypt/boulder/grpc/test_proto"
|
||||
"github.com/letsencrypt/boulder/metrics"
|
||||
"github.com/letsencrypt/boulder/probs"
|
||||
"github.com/letsencrypt/boulder/test"
|
||||
)
|
||||
|
||||
|
@ -33,8 +36,11 @@ func testHandler(_ context.Context, i interface{}) (interface{}, error) {
|
|||
}
|
||||
|
||||
func testInvoker(_ context.Context, method string, _, _ interface{}, _ *grpc.ClientConn, opts ...grpc.CallOption) error {
|
||||
if method == "-service-brokeTest" {
|
||||
switch method {
|
||||
case "-service-brokeTest":
|
||||
return errors.New("")
|
||||
case "-service-requesterCanceledTest":
|
||||
return status.Error(1, context.Canceled.Error())
|
||||
}
|
||||
fc.Sleep(time.Second)
|
||||
return nil
|
||||
|
@ -71,6 +77,14 @@ func TestClientInterceptor(t *testing.T) {
|
|||
|
||||
err = ci.intercept(context.Background(), "-service-brokeTest", nil, nil, nil, testInvoker)
|
||||
test.AssertError(t, err, "ci.intercept didn't fail when handler returned a error")
|
||||
|
||||
err = ci.intercept(context.Background(), "-service-requesterCanceledTest", nil, nil, nil, testInvoker)
|
||||
test.AssertError(t, err, "ci.intercept didn't fail when handler returned a error")
|
||||
|
||||
var probDetails *probs.ProblemDetails
|
||||
test.AssertErrorWraps(t, err, &probDetails)
|
||||
test.AssertEquals(t, probDetails.Type, probs.MalformedProblem)
|
||||
test.AssertEquals(t, probDetails.HTTPStatus, http.StatusRequestTimeout)
|
||||
}
|
||||
|
||||
// TestFailFastFalse sends a gRPC request to a backend that is
|
||||
|
|
|
@ -161,6 +161,19 @@ func Malformed(detail string, args ...interface{}) *ProblemDetails {
|
|||
}
|
||||
}
|
||||
|
||||
// Canceled returns a ProblemDetails with a MalformedProblem and a 408 Request
|
||||
// Timeout status code.
|
||||
func Canceled(detail string, args ...interface{}) *ProblemDetails {
|
||||
if len(args) > 0 {
|
||||
detail = fmt.Sprintf(detail, args...)
|
||||
}
|
||||
return &ProblemDetails{
|
||||
Type: MalformedProblem,
|
||||
Detail: detail,
|
||||
HTTPStatus: http.StatusRequestTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
// BadSignatureAlgorithm returns a ProblemDetails with a BadSignatureAlgorithmProblem
|
||||
// and a 400 Bad Request status code.
|
||||
func BadSignatureAlgorithm(detail string, a ...interface{}) *ProblemDetails {
|
||||
|
|
Loading…
Reference in New Issue