處理路由或直接攔截管道時,您將獲得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
複製程式碼