5、Ktor學習-生成HTTP響應;

Melrose發表於2019-03-04

  處理路徑或直接攔截管道時,將獲得ApplicationCall的上下文。 該呼叫包含一個名為response的屬性,允許發出響應。

上下文

  使用路由功能時,您可以訪問路由處理程式中的call屬性:

routing {
    get("/") {
        call.respondText("Request uri: ${call.request.uri}")
    } 
}
複製程式碼

當攔截請求時,攔截中的lambda處理程式也具有可用的call屬性:

intercept(ApplicationCallPipeline.Call) { 
    if (call.request.uri == "/") {
        call.respondText("Test String")
    }
}
複製程式碼

控制HTTP headers和status

  您可以控制響應的生成方式,HTTP status,headers,cookie等。

  作為響應的一部分,您可以訪問其內部上下文:

val call: ApplicationCall = response.call
val pipeline: ApplicationSendPipeline = response.pipeline
複製程式碼

  headers:

val headers: ResponseHeaders = response.headers
複製程式碼

  用於設定Set-Cookie標頭的便捷cookie例項:

val cookies: ResponseCookies = response.cookies
複製程式碼

  獲取和更改HTTP status:

response.status(HttpStatusCode.OK) - Sets the HttpStatusCode to a predefined standard one
response.status(HttpStatusCode(418, "I'm a tea pot")) - Sets the HttpStatusCode to a custom status code
val status: HttpStatusCode? = response.status() - Gets the currently set HttpStatusCode if set

response.contentType(ContentType.Text.Plain.withCharset(Charsets.UTF_8)) - Typed way for setting the Content-Type (for ContentType.Application.Json the default charset is UTF_8 without making it explicit)
response.contentType("application/json; charset=UTF-8") - Untyped way for setting the Content-Type header
複製程式碼

  自定義headers:

response.header("X-My-Header", "my value") - Appends a custom header
response.header("X-My-Times", 1000) - Appends a custom header
response.header("X-My-Times", 1000L) - Appends a custom header
response.header("X-My-Date", Instant.EPOCH) - Appends a custom header
複製程式碼

  設定標頭的便捷方法:

response.etag("33a64df551425fcc55e4d42a148795d9f25f89d4") - Sets the ETag used for caching
response.lastModified(ZonedDateTime.now()) - Sets the Last-Modified header
response.contentLength(1024L) - Sets the Content-Length. This is generally automatically set when sending the payload
response.cacheControl(CacheControl.NoCache(CacheControl.Visibility.Private)) - Sets the Cache-Control header in a typed way
response.expires(LocalDateTime.now()) - Sets the Expires header
response.contentRange(1024L until 2048L, 4096L) - Sets the Content-Range header (check the PartialContent feature)
複製程式碼

HTTP/2 Pushing和HTTP/1連結頭

  call支援Pushing功能。

  • 在HTTP/2中,使用Pushing功能
  • 在HTTP/1.2中,它將連結頭新增為一個提示
routing {
    get("/") {
        call.push("/style.css")
    }
}
複製程式碼

注:Pushing減少了請求和頁面顯示之間的時間。但請注意,事先傳送內容可能會傳送已由客戶端快取的內容。

重定向

  您可以使用respondRedirect方法輕鬆生成重定向響應,使用Location標頭髮送301 Moved Permanently或302 Found重定向。

call.respondRedirect("/moved/here", permanent = true)
複製程式碼

傳送響應內容

  傳送通用內容(與Content negotiation相容):

call.respond(MyDataClass("hello", "world")) - Check the Content Negotiation section
call.respond(HttpStatusCode.NotFound, MyDataClass("hello", "world")) - Specifies a status code, and sends a payload in a single call. Check StatusPages
複製程式碼

  傳送文字資訊:

call.respondText("text") - Just a string with the body
call.respondText("p { background: red; }", contentType = ContentType.Text.CSS, status = HttpStatusCode.OK) { ... } - Sending a text specifying the ContentType, the HTTP Status and configuring the OutgoingContent
call.respondText { "string" } - Responding a string with a suspend provider
call.respondText(contentType = ..., status = ...) { "string" } - Responding a string with a suspend provider
call.respond(TextContent("{}", ContentType.Application.Json)) - Responding a string without adding a charset to the Content-Type
複製程式碼

  傳送byte陣列:

call.respondBytes(byteArrayOf(1, 2, 3)) - A ByteArray with a binary body
複製程式碼

傳送檔案:

call.respondFile(File("/path/to/file")) - Sends a file
call.respondFile(File("basedir"), "filename") { ... } - Send a file and configures the OutgoingContent
複製程式碼

  傳送URL編碼的表單(application/x-www-form-urlencoded):

Use Parameters.formUrlEncode. Check the Utilities page for more information about this.
複製程式碼

  使用Writer傳送分塊內容:

call.respondWrite { write("hello"); write("world") } - Sends text using a writer. This is used with the HTML DSL
call.respondWrite(contentType = ..., status = ...) { write("hello"); write("world") } - Sends text using a writer and specifies a contentType and a status
複製程式碼

使檔案可下載

  您可以通過新增Content-Disposition標頭使檔案“可下載”。以無型別的方式,您可以執行以下操作:

call.response.header(HttpHeaders.ContentDisposition, "attachment; filename=\"myfilename.bin\"")
複製程式碼

  但是Ktor還提供了一種帶有正確轉義的型別化方法來生成此標頭:

call.response.header(HttpHeaders.ContentDisposition, ContentDisposition.Attachment.withParameter(ContentDisposition.Parameters.FileName, "myfilename.bin").toString())
複製程式碼

Content negotiation(介紹)

  在配置用於Content negotiation的外掛時,管道可以接受call.respond方法的其他型別。

  1. 傳送 HTML DSL
  2. 傳送 HTMLFreeMarker
  3. 傳送data class生成的json

相關文章