func handler(req mercury.Request) (mercury.Response, error) { request := req.Body().(*hello.Request) rsp := req.Response(&hello.Response{ Msg: "Hey " + request.Name, }) return rsp, nil }
// Handle takes an inbound Request, unmarshals it, dispatches it to the handler, and serialises the result as a // Response. Note that the response may be nil. func (e Endpoint) Handle(req mercury.Request) (rsp mercury.Response, err error) { // Unmarshal the request body (unless there already is one) if req.Body() == nil && e.Request != nil { if um := e.unmarshaler(req); um != nil { if werr := terrors.Wrap(um.UnmarshalPayload(req), nil); werr != nil { log.Warnf("[Mercury:Server] Cannot unmarshal request payload: %v", werr) terr := werr.(*terrors.Error) terr.Code = terrors.ErrBadRequest rsp, err = nil, terr return } } } defer func() { if v := recover(); v != nil { traceVerbose := make([]byte, 1024) runtime.Stack(traceVerbose, true) log.Criticalf("[Mercury:Server] Recovered from handler panic for request %s:\n%v\n%s", req.Id(), v, string(traceVerbose)) rsp, err = nil, terrors.InternalService("panic", fmt.Sprintf("Panic in handler %s:\n%s", req.Endpoint(), string(traceVerbose)), nil) } }() rsp, err = e.Handler(req) return }
func (e Endpoint) unmarshaler(req mercury.Request) tmsg.Unmarshaler { result := marshaling.Unmarshaler(req.Headers()[marshaling.ContentTypeHeader], e.Request) if result == nil { // Default to json result = marshaling.Unmarshaler(marshaling.JSONContentType, e.Request) } return result }
func (m requestTreeMiddleware) ProcessClientRequest(req mercury.Request) mercury.Request { if req.Headers()[parentIdHeader] == "" { // Don't overwrite an exiting header if parentId, ok := req.Context().Value(reqIdCtxKey).(string); ok && parentId != "" { req.SetHeader(parentIdHeader, parentId) } } // Pass through the current service and endpoint as the origin of this request req.SetHeader(originServiceHeader, CurrentServiceFor(req)) req.SetHeader(originEndpointHeader, CurrentEndpointFor(req)) return req }
// ErrorResponse constructs a response for the given request, with the given error as its contents. Mercury clients // know how to unmarshal these errors. func ErrorResponse(req mercury.Request, err error) mercury.Response { rsp := req.Response(nil) var terr *terrors.Error if err != nil { terr = terrors.Wrap(err, nil).(*terrors.Error) } rsp.SetBody(terrors.Marshal(terr)) if err := tmsg.ProtoMarshaler().MarshalBody(rsp); err != nil { log.Errorf("[Mercury:Server] Failed to marshal error response: %v", err) return nil // Not much we can do here } rsp.SetIsError(true) return rsp }
// Handle takes an inbound Request, unmarshals it, dispatches it to the handler, and serialises the result as a // Response. Note that the response may be nil. func (e Endpoint) Handle(req mercury.Request) (mercury.Response, error) { // Unmarshal the request body (unless there already is one) if req.Body() == nil && e.Request != nil { if um := e.unmarshaler(req); um != nil { if werr := terrors.Wrap(um.UnmarshalPayload(req), nil); werr != nil { log.Warn(req, "[Mercury:Server] Cannot unmarshal request payload: %v", werr) terr := werr.(*terrors.Error) terr.Code = terrors.ErrBadRequest return nil, terr } } } return e.Handler(req) }
func (m *testMw) ProcessClientRequest(req mercury.Request) mercury.Request { req.SetHeader("X-Foo", "X-Bar") return req }
func old2NewRequest(oldReq mercury.Request) typhon.Request { ep := oldReq.Endpoint() if !strings.HasPrefix(ep, "/") { ep = "/" + ep } v := typhon.Request{ Context: oldReq.Context(), Request: http.Request{ Method: "POST", URL: &url.URL{ Scheme: "http", Host: oldReq.Service(), Path: ep}, Proto: "HTTP/1.1", ProtoMajor: 1, ProtoMinor: 1, Header: toHeader(oldReq.Headers()), Host: oldReq.Service(), Body: ioutil.NopCloser(bytes.NewReader(oldReq.Payload())), ContentLength: int64(len(oldReq.Payload()))}} v.Header.Set(legacyIdHeader, oldReq.Id()) return v }
func (e Endpoint) unmarshaler(req mercury.Request) tmsg.Unmarshaler { return marshaling.Unmarshaler(req.Headers()[marshaling.ContentTypeHeader], e.Request) }
func (m requestTreeMiddleware) ProcessServerRequest(req mercury.Request) (mercury.Request, mercury.Response) { req.SetContext(context.WithValue(req.Context(), reqIdCtxKey, req.Id())) if v := req.Headers()[parentIdHeader]; v != "" { req.SetContext(context.WithValue(req.Context(), parentIdCtxKey, v)) } // Set the current service and endpoint into the context req.SetContext(context.WithValue(req.Context(), currentServiceHeader, req.Service())) req.SetContext(context.WithValue(req.Context(), currentEndpointHeader, req.Endpoint())) // Set the originator into the context req.SetContext(context.WithValue(req.Context(), originServiceHeader, req.Headers()[originServiceHeader])) req.SetContext(context.WithValue(req.Context(), originEndpointHeader, req.Headers()[originEndpointHeader])) return req, nil }