예제 #1
0
파일: handler.go 프로젝트: yarpc/yarpc-go
func (h handler) callHandler(ctx context.Context, call inboundCall, start time.Time) error {
	_, ok := ctx.Deadline()
	if !ok {
		return tchannel.ErrTimeoutRequired
	}

	treq := &transport.Request{
		Caller:    call.CallerName(),
		Service:   call.ServiceName(),
		Encoding:  transport.Encoding(call.Format()),
		Procedure: call.MethodString(),
	}

	ctx, headers, err := readRequestHeaders(ctx, call.Format(), call.Arg2Reader)
	if err != nil {
		return encoding.RequestHeadersDecodeError(treq, err)
	}
	treq.Headers = headers

	if tcall, ok := call.(tchannelCall); ok {
		tracer := h.deps.Tracer()
		ctx = tchannel.ExtractInboundSpan(ctx, tcall.InboundCall, headers.Items(), tracer)
	}

	body, err := call.Arg3Reader()
	if err != nil {
		return err
	}
	defer body.Close()
	treq.Body = body

	rw := newResponseWriter(treq, call)
	defer rw.Close() // TODO(abg): log if this errors

	treq, err = request.Validate(ctx, treq)
	if err != nil {
		return err
	}

	spec, err := h.Registry.GetHandlerSpec(treq.Service, treq.Procedure)
	if err != nil {
		return err
	}

	switch spec.Type() {
	case transport.Unary:
		treq, err = request.ValidateUnary(ctx, treq)
		if err == nil {
			err = internal.SafelyCallUnaryHandler(ctx, spec.Unary(), start, treq, rw)
		}

	default:
		err = errors.UnsupportedTypeError{Transport: "TChannel", Type: string(spec.Type())}
	}

	return err
}
예제 #2
0
파일: handler.go 프로젝트: yarpc/yarpc-go
func (h handler) callHandler(w http.ResponseWriter, req *http.Request, start time.Time) error {
	treq := &transport.Request{
		Caller:    popHeader(req.Header, CallerHeader),
		Service:   popHeader(req.Header, ServiceHeader),
		Procedure: popHeader(req.Header, ProcedureHeader),
		Encoding:  transport.Encoding(popHeader(req.Header, EncodingHeader)),
		Headers:   applicationHeaders.FromHTTPHeaders(req.Header, transport.Headers{}),
		Body:      req.Body,
	}

	ctx := req.Context()

	v := request.Validator{Request: treq}
	ctx, cancel := v.ParseTTL(ctx, popHeader(req.Header, TTLMSHeader))
	defer cancel()

	ctx, span := h.createSpan(ctx, req, treq, start)

	treq, err := v.Validate(ctx)
	if err != nil {
		return err
	}

	spec, err := h.Registry.GetHandlerSpec(treq.Service, treq.Procedure)
	if err != nil {
		return updateSpanWithErr(span, err)
	}

	switch spec.Type() {
	case transport.Unary:
		defer span.Finish()

		ctx, cancel := v.ParseTTL(ctx, popHeader(req.Header, TTLMSHeader))
		defer cancel()

		treq, err = v.ValidateUnary(ctx)
		if err != nil {
			return err
		}
		err = internal.SafelyCallUnaryHandler(ctx, spec.Unary(), start, treq, newResponseWriter(w))

	case transport.Oneway:
		treq, err = v.ValidateOneway(ctx)
		if err != nil {
			return err
		}
		err = handleOnewayRequest(ctx, span, treq, spec.Oneway())

	default:
		err = errors.UnsupportedTypeError{Transport: "HTTP", Type: string(spec.Type())}
	}

	return updateSpanWithErr(span, err)
}