处理路由或直接拦截管道时,您将获得ApplicationCall的上下文。 该调用包含一个名为request的属性,其中包含有关请求的信息。
介绍
当使用路由功能或拦截请求时,您可以访问处理程序内的call属性。 该调用包括一个请求属性,其中包含有关请求的相关信息:
routing {
get("/") {
val uri = call.request.uri
call.respondText("Request uri: $uri")
}
}
intercept(ApplicationCallPipeline.Call) {
if (call.request.uri == "/") {
call.respondText("Test String")
}
}
复制代码
请求信息
作为请求的一部分,您可以访问其内部上下文:
val call: ApplicationCall = request.call
val pipeline: ApplicationReceivePipeline = request.pipeline
//URL, method, scheme, protocol, host, path, httpVersion, remoteHost, clientIp
val version: String = request.httpVersion // "HTTP/1.1"
val httpMethod: HttpMethod = request.httpMethod // GET, POST...
val uri: String = request.uri // Short cut for `origin.uri`
val scheme: String = request.origin.scheme // "http" or "https"
val host: String? = request.host() // The host part without the port
val port: Int = request.port() // Port of request
val path: String = request.path() // The uri without the query string
val document: String = request.document() // The last component after '/' of the uri
val remoteHost: String = request.origin.remoteHost // The IP address of the client doing the request
复制代码
反向代理支持:origin和local
当在反向代理(例如nginx或负载均衡器)后面时,最终用户不会执行接收到的请求,而是反向代理。 这意味着连接的客户端IP地址将是代理而不是客户端之一。 反向代理也可能通过HTTPS提供服务并通过HTTP向您的服务器请求。 流行的反向代理发送X-Forwarded-标头以便能够访问此信息。
注:请注意,为了在反向代理下工作,您必须安装XForwardedHeaderSupport功能。
作为请求对象的一部分,有两个属性local和origin,它们允许获取原始请求或本地/代理请求的信息。
val local : RequestConnectionPoint = request.local // Local information
val origin: RequestConnectionPoint = request.origin // Local / Origin if XForwardedHeaderSupport feature is installed.
复制代码
您可以获得的local/origin信息:
interface RequestConnectionPoint {
val scheme: String // "http" or "https": The provided protocol (local) or `X-Forwarded-Proto`
val version: String // "HTTP/1.1"
val port: Int
val host: String // The provided host (local) or `X-Forwarded-Host`
val uri: String
val method: HttpMethod
val remoteHost: String // The client IP (the direct ip for `local`, or the redirected one `X-Forwarded-For`)
}
复制代码
GET/QUERY参数
如果需要访问查询参数?param1 = value&param2 = value作为集合,则可以使用queryParameters。 它实现了StringValues接口,其中每个键都可以有一个与之关联的字符串列表。
val queryParameters: Parameters = request.queryParameters
val param1: String? = request.queryParameters["param1"] // To access a single parameter (first one if repeated)
val repeatedParam: List<String>? = request.queryParameters.getAll("repeatedParam") // Multiple values
复制代码
您还可以访问原始queryString(param1 = value&param2 = value):
val queryString: String = request.queryString()
复制代码
POST, PUT 和 PATCH
POST,PUT和PATCH请求具有关联的请求主体(有效负载)。
val channel: ByteReadChannel = call.receiveChannel()
val text: String = call.receiveText()
val inputStream: InputStream = call.receiveStream() // NOTE: InputStream is synchronous and blocks the thread
val multipart: MultiPartData = call.receiveMultipart()
复制代码
表单参数(urlencoded或multipart)
要解析urlencoded或multipart的表单,可以使用receiveParameters或receive <Parameters>:
val postParameters: Parameters = call.receiveParameters()
复制代码
接收类型对象,内容类型和JSON
该调用还支持接收通用对象:
val obj: T = call.receive<T>()
val obj: T? = call.receiveOrNull<T>()
复制代码
要从有效内容接收自定义对象,您必须使用ContentNegotiation功能。 例如,这对于在REST API中接收和发送JSON有效负载非常有用。
install(ContentNegotiation) {
gson {
setDateFormat(DateFormat.LONG)
setPrettyPrinting()
}
}
复制代码
如果将ContentNegotiation配置为使用gson,则需要包含ktor-gson工件:
compile("io.ktor:ktor-gson:$ktor_version")
复制代码
例子如下:
data class HelloWorld(val hello: String)
routing {
post("/route") {
val helloWorld = call.receive<HelloWorld>()
}
}
复制代码
注:请记住,您的类必须在顶级(在任何其他类或函数之外)定义才能被Gson识别。
Cookies
有一个cookie属性可以访问客户端发送的Cookie标头,就像它是一个集合一样:
val cookies: RequestCookies = request.cookies
val mycookie: String? = request.cookies["mycookie"]
复制代码
Headers
要访问Headers,请求对象有一个标头:Headers属性。它实现了StringValues接口,其中每个键都可以有一个与之关联的字符串列表。
val headers: Headers = request.headers
val header: String? = request.header("HeaderName") // To access a single header (first one if repeated)
val repeatedHeader: List<String>? = request.headers.getAll("HeaderName") // Multiple values
//访问一些常见标头的几种便捷方法:
val contentType: ContentType = request.contentType() // Parsed Content-Tpe
val contentCharset: Charset? = request.contentCharset() // Content-Type JVM charset
val authorization: String? = request.authorization() // Authorization header
val location: String? = request.location() // Location header
val accept: String? = request.accept() // Accept header
val acceptItems: List<HeaderValue> = request.acceptItems() // Parsed items of Accept header
val acceptEncoding: String? = request.acceptEncoding() // Accept-Encoding header
val acceptEncodingItems: List<HeaderValue> = request.acceptEncodingItems() // Parsed Accept-Encoding items
val acceptLanguage: String? = request.acceptLanguage() // Accept-Language header
val acceptLanguageItems: List<HeaderValue> = request.acceptLanguageItems() // Parsed Accept-Language items
val acceptCharset: String? = request.acceptCharset() // Accept-Charset header
val acceptCharsetItems: List<HeaderValue> = request.acceptCharsetItems() // Parsed Accept-Charset items
val userAgent: String? = request.userAgent() // User-Agent header
val cacheControl: String? = request.cacheControl() // Cache-Control header
val ranges: RangesSpecifier? = request.ranges() // Parsed Ranges header
val isChunked: Boolean = request.isChunked() // Transfer-Encoding: chunked
val isMultipart: Boolean = request.isMultipart() // Content-Type matches Multipart
复制代码