Exemplo n.º 1
0
// HandleStreamingRPC is an internal method. Do not use!
func (server *Server) HandleStreamingRPC(
	grpcStream core.LeverRPC_HandleStreamingRPCServer) error {
	ctx := grpcStream.Context()
	err := setInternalRPCGateway(ctx)
	if err != nil {
		return err
	}
	leverURL, err := extractLeverURL(ctx)
	if err != nil {
		return err
	}

	fstMsg, err := grpcStream.Recv()
	if err != nil {
		return err
	}
	rpc := fstMsg.GetRpc()
	if rpc == nil {
		return fmt.Errorf("First message needs to have RPC field set")
	}
	if rpc.GetArgsOneof() == nil {
		return fmt.Errorf("RPC has no args oneof")
	}
	// Reply with an empty msg (first response message must be empty).
	grpcStream.Send(&core.StreamMessage{})

	server.lock.RLock()
	entry, handlerOK := server.streamingHandlers[leverURL.Method]
	resourceOK := true
	if leverURL.Resource != "" {
		_, resourceOK = server.resources[leverURL.Resource]
	}
	server.lock.RUnlock()
	if !handlerOK {
		return fmt.Errorf("Method not found")
	}
	if !resourceOK {
		return fmt.Errorf("Resource not found")
	}

	_, err = callHandler(ctx, leverURL.Resource, entry, rpc, grpcStream)
	return err
}
Exemplo n.º 2
0
func callHandler(
	ctx context.Context, resource string, entry *handlerEntry, rpc *core.RPC,
	grpcStream core.LeverRPC_HandleStreamingRPCServer) (
	reply *core.RPCReply, err error) {
	// Prepare args for handler.
	var callArgs []reflect.Value
	if entry.isMethod {
		callArgs = append(callArgs, reflect.ValueOf(entry.obj))
	}
	isStreaming := (grpcStream != nil)
	if isStreaming {
		callArgs = append(
			callArgs, reflect.ValueOf(newServerStream(grpcStream)))
	} else {
		if entry.hasContext {
			callArgs = append(callArgs, reflect.ValueOf(ctx))
		}
	}
	if resource != "" {
		callArgs = append(callArgs, reflect.ValueOf(resource))
	}
	switch args := rpc.GetArgsOneof().(type) {
	case *core.RPC_Args:
		var values []reflect.Value
		values, err = decodeArgsAsValue(args.Args, entry, isStreaming)
		if err != nil {
			return nil, err
		}
		callArgs = append(callArgs, values...)
	case *core.RPC_ByteArgs:
		callArgs = append(callArgs, reflect.ValueOf(args.ByteArgs))
	default:
		return nil, fmt.Errorf("Invalid args")
	}

	// Call handler.
	result := reflect.ValueOf(entry.handler).Call(callArgs)

	// Interpret result.
	errIndex := 1
	if isStreaming {
		errIndex = 0
	}
	if entry.isByteErrorResult {
		var errBytesResult []byte
		v := result[errIndex].Interface()
		if v != nil {
			var ok bool
			errBytesResult, ok = result[errIndex].Interface().([]byte)
			if !ok {
				errBytesResult =
					result[errIndex].Interface().(BytesError).GetBytes()
			}
			if errBytesResult != nil {
				if !isStreaming {
					return &core.RPCReply{
						ResultOneof: &core.RPCReply_ByteError{
							ByteError: errBytesResult,
						},
					}, nil
				}
				err = grpcStream.Send(&core.StreamMessage{
					MessageOneof: &core.StreamMessage_ByteError{
						ByteError: errBytesResult,
					},
				})
				return nil, err
			}
		}
	} else {
		v := result[errIndex].Interface()
		if v != nil {
			theError, isErrorType := v.(error)
			if isErrorType {
				// For error type, just use the string returned by Error().
				v = theError.Error()
			}
			var encodedErr *core.JSON
			encodedErr, err = encodeArg(v)
			if err != nil {
				return nil, err
			}
			if !isStreaming {
				return &core.RPCReply{
					ResultOneof: &core.RPCReply_Error{
						Error: encodedErr,
					},
				}, nil
			}
			err = grpcStream.Send(&core.StreamMessage{
				MessageOneof: &core.StreamMessage_Error{
					Error: encodedErr,
				},
			})
			return nil, err
		}
	}

	if isStreaming {
		// Stream case - no reply sent back.
		return nil, nil
	}

	// Non-stream case - build reply.
	if entry.isByteResult {
		return &core.RPCReply{
			ResultOneof: &core.RPCReply_ByteResult{
				ByteResult: result[0].Interface().([]byte),
			},
		}, nil
	}
	encodedResult, err := encodeArg(result[0].Interface())
	if err != nil {
		return nil, err
	}
	return &core.RPCReply{
		ResultOneof: &core.RPCReply_Result{
			Result: encodedResult,
		},
	}, nil
}