func (h handler) ServeHTTP(w http.ResponseWriter, req *http.Request) { start := time.Now() defer req.Body.Close() if req.Method != "POST" { http.NotFound(w, req) return } service := req.Header.Get(ServiceHeader) procedure := req.Header.Get(ProcedureHeader) err := h.callHandler(w, req, start) if err == nil { return } err = errors.AsHandlerError(service, procedure, err) status := http.StatusInternalServerError if transport.IsBadRequestError(err) { status = http.StatusBadRequest } else if transport.IsTimeoutError(err) { status = http.StatusGatewayTimeout } http.Error(w, err.Error(), status) }
// remoteTimeout tests if a yarpc client returns a remote timeout error behind // the TimeoutError interface when a remote tchannel handler returns a handler // timeout. func remoteTimeout(t crossdock.T, dispatcher yarpc.Dispatcher) { assert := crossdock.Assert(t) headers := yarpc.NewHeaders() token := random.Bytes(5) _, _, err := rawCall(dispatcher, headers, "handlertimeout/raw", token) if skipOnConnRefused(t, err) { return } if !assert.Error(err, "expected an error") { return } if transport.IsBadRequestError(err) { t.Skipf("handlertimeout/raw procedure not implemented: %v", err) return } assert.True(transport.IsTimeoutError(err), "returns a TimeoutError: %T", err) form := strings.HasPrefix(err.Error(), `Timeout: call to procedure "handlertimeout/raw" of service "service" from caller "caller" timed out after`) assert.True(form, "must be a remote handler timeout: %q", err.Error()) }
func (h handler) handle(ctx context.Context, call inboundCall) { start := time.Now() err := h.callHandler(ctx, call, start) if err == nil { return } if _, ok := err.(tchannel.SystemError); ok { call.Response().SendSystemError(err) return } err = errors.AsHandlerError(call.ServiceName(), call.MethodString(), err) status := tchannel.ErrCodeUnexpected if transport.IsBadRequestError(err) { status = tchannel.ErrCodeBadRequest } else if transport.IsTimeoutError(err) { status = tchannel.ErrCodeTimeout } call.Response().SendSystemError(tchannel.NewSystemError(status, err.Error())) }
// runRaw tests if a yarpc client returns a remote timeout error behind the // TimeoutError interface when a remote http handler returns a handler timeout. func runRaw(t crossdock.T, disp yarpc.Dispatcher) { assert := crossdock.Assert(t) fatals := crossdock.Fatals(t) ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) defer cancel() ch := raw.New(disp.Channel("yarpc-test")) _, _, err := ch.Call(ctx, yarpc.NewReqMeta().Procedure("handlertimeout/raw"), nil) fatals.Error(err, "expected an error") if transport.IsBadRequestError(err) { t.Skipf("handlertimeout/raw method not implemented: %v", err) return } assert.True(transport.IsTimeoutError(err), "returns a TimeoutError: %T", err) form := strings.HasPrefix(err.Error(), `Timeout: call to procedure "handlertimeout/raw" of service "service" from caller "caller" timed out after`) assert.True(form, "must be a remote handler timeout: %q", err.Error()) }
// Run tests if a yarpc client returns correctly a client timeout error behind // the TimeoutError interface when the context deadline is reached while the // server is taking too long to respond. func Run(t crossdock.T) { assert := crossdock.Assert(t) fatals := crossdock.Fatals(t) ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) defer cancel() dispatcher := disp.Create(t) fatals.NoError(dispatcher.Start(), "could not start Dispatcher") defer dispatcher.Stop() ch := raw.New(dispatcher.Channel("yarpc-test")) _, _, err := ch.Call(ctx, yarpc.NewReqMeta().Procedure("sleep/raw"), nil) fatals.Error(err, "expected a failure for timeout") if transport.IsBadRequestError(err) { t.Skipf("sleep/raw method not implemented: %v", err) return } assert.True(transport.IsTimeoutError(err), "returns a TimeoutError: %T", err) trans := t.Param(params.Transport) switch trans { case "http": form := strings.HasPrefix(err.Error(), `client timeout for procedure "sleep/raw" of service "yarpc-test" after`) assert.True(form, "should be a client timeout: %q", err.Error()) case "tchannel": form := strings.HasPrefix(err.Error(), `timeout`) assert.True(form, "should be a remote timeout (we cant represent client timeout with tchannel): %q", err.Error()) default: fatals.Fail("", "unknown transport %q", trans) } }