示例#1
0
func extractResourceFromArgs(rpc *core.RPC) (resource string, err error) {
	if rpc.GetArgsOneof() == nil {
		return "", fmt.Errorf("Could not find args")
	}
	args, ok := rpc.GetArgsOneof().(*core.RPC_Args)
	if !ok {
		return "", fmt.Errorf("Unexpected type of args for newResource")
	}
	if len(args.Args.Element) != 1 {
		return "", fmt.Errorf("Unexpected number of args for newResource")
	}
	el := args.Args.Element[0]
	if el.GetJsonValueOneof() == nil {
		return "", fmt.Errorf("Unexpected arg for newResource")
	}
	strArg, ok := el.GetJsonValueOneof().(*core.JSON_JsonString)
	if !ok {
		return "", fmt.Errorf("Unexpected arg type for newResource")
	}
	resource = strArg.JsonString
	if resource == "" {
		return "", fmt.Errorf("Invalid resource empty string")
	}
	return resource, nil
}
示例#2
0
// HandleRPC is an internal method. Do not use!
func (server *Server) HandleRPC(
	ctx context.Context, rpc *core.RPC) (reply *core.RPCReply, err error) {
	err = setInternalRPCGateway(ctx)
	if err != nil {
		return nil, err
	}
	leverURL, err := extractLeverURL(ctx)
	if err != nil {
		return nil, err
	}
	if rpc.GetArgsOneof() == nil {
		return nil, fmt.Errorf("RPC has no args oneof")
	}

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

	err = server.maybeHandleResourceLifecycle(leverURL, rpc)
	if err != nil {
		return nil, err
	}

	return callHandler(ctx, leverURL.Resource, entry, rpc, nil)
}
示例#3
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
}