RPC Server

The RpcServer is the object responsible for implementing the server-side of remote procedure calls. The server, like the client, is implemented using plugin based approach. The RpcServer instance is available from micro.server and is configured by the ServerFeature. Inside an RpcServer we find the following properties:

Property Description
IngoingRequestInterceptor The request interceptor is responsible for reading and parsing a network call into an RPC + request. It also responsible for sending the response over the network.
IngoingCallFilter The call filters act as middle-ware. The middle-ware can implement features such as: logging and service discovery

Controllers

An RpcServer is configured by implementing a Controller and passing it to configureControllers in Server.kt.

// In 'rpc' package
class MyController : Controller {
    override fun configure(rpcServer: RpcServer) = with(rpcServer) {
        implement(Avatars.findAvatar) {
            ok(TODO("Find the avatar"))
        }
    }
}

// In 'Server.kt'
with(micro.server) {
    configureControllers(MyController())
}

Code: Implementing a call is done in a Controller by calling the implement function with an associated call handler.

RpcServer.implement

fun <R : Any, S : Any, E : Any> RpcServer.implement(
    call: CallDescription<R, S, E>,
    requiredContext: Set<IngoingCallCompanion<*>>? = null,
    handler: suspend CallHandler<R, S, E>.() -> Unit
)

The implement function attaches a call handler to an associated CallDescription. You can control in which backends the call handler can run by setting the requiredContext, by-default the call will be able to handle any context.

The RpcServer will call the handler every time a request arrives. The CallHandler will provide a response by calling either ok(SuccessType) or error(ErrorType).

CallHandler<RequestType, SuccessType, ErrorType>

Properties

Properties Description
ctx: IngoingCall Contains additional information about the request, such as, reference to the calling user
request: RequestType Contains the parsed request
description: CallDescription<R, S, E> Contains a reference to the RPC description

Member functions

fun ok(result: SuccessType, statusCode: HttpStatusCode = HttpStatusCode.OK)

Signifies to the RpcServer that this call should produce a successful response containing result. It is an error to call this function twice in a single CallHandler invocation.


fun okContentAlreadyDelivered()

Signifies to the RpcServer that this call has been handled by interacting directly with the backend (see CallHandler.withContext). This function must be called if you produce a response directly. This is required for middle-ware to know that the lack of a response object is not a programmer error.


fun error(error: ErrorType, statusCode: HttpStatusCode)

Signifies to the RpcServer that this call should produce an error response containing result. It is an error to call this function twice in a single CallHandler invocation.


class WithNewContext<T : IngoingCall>(val ctx: T)
fun <T : IngoingCall> withContext(handler: WithNewContext<T>.() -> Unit)

Allows a CallHandler to interact directly with the RPC server backend. We generally recommend that you do not use this function to speak directly to the backend server.

Example:

implement(Avatars.findAvatar) {
    withContext<HttpCall> { 
        ctx.call.respondText { "Direct interaction with ktor" }
    }
    okContentAlreadyDelivered()
}

IngoingCall

Properties

val IngoingCall.securityPrincipal: SecurityPrincipal
val IngoingCall.securityPrincipalOrNull: SecurityPrincipal?
val IngoingCall.securityToken: SecurityPrincipalToken
val IngoingCall.securityTokenOrNull: SecurityPrincipalToken?

Returns information about the authenticated security principal. If there is no guarantee that the user is authenticated (see here) then you should use the OrNull variant.


val IngoingCall.bearer: String?

Returns the raw bearer token used in authenticating the user.


val IngoingCall.audit: AuditData

Allows the CallHandler to modify the data used in auditing.


val IngoingCall.remoteHost: String?

Returns information about the calling users IP address.


val IngoingCall.jobId: String
val IngoingCall.causedBy: String?

Returns information about the job ID and caused-by IDs.


val IngoingCall.userAgent: String?

Returns information about the calling client’s user agent.


val IngoingCall.project: String?

Returns information about the calling user’s active project.