HTTP Client Request

预计阅读时间:6分钟

Simple requests

基本用法是超级简单:你只需要实例化一个HttpClient实例,指定一个引擎,例如ApacheOkHttpAndroidIosJsJettyCIOMock ,并开始制作使用现有的许多方便的方法之一请求.

您可以省略引擎,Ktor将使用JVM上的ServiceLoader或其他平台上的默认实现从随附的工件中选择可用的引擎.

首先,您需要实例化客户端:

val client = HttpClient()

然后,执行GET请求以完全读取String

val htmlContent = client.get<String>("https://en.wikipedia.org/wiki/Main_Page")

如果您对原始位感兴趣,则可以读取ByteArray

val bytes: ByteArray = client.get<ByteArray>("http://127.0.0.1:8080/")

可以大量自定义请求并流式传输请求和响应有效负载:

val channel: ByteReadChannel = client.get<ByteReadChannel>("http://127.0.0.1:8080/")

与客户端一起使用后,应将其关闭以正确停止基础引擎.

client.close()

如果要使用客户端仅发出一个请求,请考虑use -ing它. 一旦执行了传递的块,客户端将自动关闭:

val status = HttpClient().use { client ->
    client.get<HttpStatusCode>("http://127.0.0.1:8080/check")
}

Custom requests

我们不能仅仅依靠get请求,Ktor允许您使用任何HTTP动词来构建复杂的请求,并具有以多种方式处理响应的灵活性.

The call method

HttpClient call方法,返回HttpClientCall并允许您执行简单的无类型请求.

您可以使用response: HttpResponse读取内容. 有关更多信息,请使用HttpResponse部分签出接收内容 .

val call = client.call("http://127.0.0.1:8080/") {
    method = HttpMethod.Get
}
println(call.response.receive<String>())

The request method

除了调用之外,还有一种用于执行类型化请求的request方法,该方法接收诸如String,HttpResponse或任意类的特定类型 . 构建请求时,必须指定URL和方法.

val call = client.request<String> {
    url("http://127.0.0.1:8080/")
    method = HttpMethod.Get
}

The get, post, put, delete, patch, head and options methods

request类似,有几种扩展方法可以使用最常见的HTTP动词执行请求: GETPOSTPUTDELETEPATCHHEADOPTIONS .

val text = client.post<String>("http://127.0.0.1:8080/")

调用请求方法时,可以提供一个lambda来构建请求参数,例如URL,HTTP method(verb),正文或标头. HttpRequestBuilder看起来像这样:

class HttpRequestBuilder : HttpMessageBuilder {
    var method: HttpMethod

    val url: URLBuilder
    fun url(block: URLBuilder.(URLBuilder) -> Unit)

    val headers: HeadersBuilder
    fun header(key: String, value: String)
    fun headers(block: HeadersBuilder.() -> Unit)

    var body: Any = EmptyContent

    val executionContext: CompletableDeferred<Unit>
    fun setAttributes(block: Attributes.() -> Unit)
    fun takeFrom(builder: HttpRequestBuilder): HttpRequestBuilder
}

HttpClient类仅提供一些基本功能,并且所有用于构建请求的方法都作为扩展公开.
您可以检查可用的标准HttpClient构建扩展方法 .

The submitForm and submitFormWithBinaryData methods

有两种便捷的扩展方法可以提交表单信息. 详细的参考资料在这里列出.

The submitForm method:

client.submitForm(
    formData: Parameters = Parameters.Empty,
    encodeInQuery: Boolean = false,
    block: HttpRequestBuilder.() -> Unit = {}
)

根据encodeInQuery参数,它允许使用查询字符串中编码的Parameters (默认为GET )进行请求或使用编码为multipart的Parameters (默认为POST )进行encodeInQuery .

The submitFormWithBinaryData method:

client.submitFormWithBinaryData(
    formData: List<PartData>,
    block: HttpRequestBuilder.() -> Unit = {}
): T

它允许从PartData列表生成多部分POST请求. PartData可以是PartData.FormItemPartData.BinaryItemPartData.FileItem .

要构建PartData的列表,可以使用formData构建器:

val data: List<PartData> = formData {
    // Can append: String, Number, ByteArray and Input.
    append("hello", "world")
    append("number", 10)
    append("ba", byteArrayOf(1, 2, 3, 4))
    appendInput("input", size = knownSize.orNull()) { openInputStream().asInput() }
    // Allow to set headers to the part:
    append("hello", "world", headersOf("X-My-Header" to "MyValue"))
}

Specifying custom headers

使用HttpRequestBuilder构建请求时,可以设置自定义标头. 有一个最终的属性val headers: HeadersBuilder ,它继承自StringValuesBuilder . 您可以使用它或header方便方法添加或删除标题.

// this : HttpMessageBuilder

// Convenience method to add a header
header("My-Custom-Header", "HeaderValue")

// Calls methods from the headers: HeadersBuilder to manipulate the headers
headers.clear()
headers.append("My-Custom-Header", "HeaderValue")
headers.appendAll("My-Custom-Header", listOf("HeaderValue1", "HeaderValue2"))
headers.remove("My-Custom-Header")

// Applies the headers with the `headers` convenience method
headers { // this: HeadersBuilder
    clear()
    append("My-Custom-Header", "HeaderValue")
    appendAll("My-Custom-Header", listOf("HeaderValue1", "HeaderValue2"))
    remove("My-Custom-Header")
}

完整的HeadersBuilder API 在此处列出.

Specifying a body for requests

对于POSTPUT请求,可以设置body属性:

client.post<Unit> {
    url("http://127.0.0.1:8080/")
    body = // ...
}

HttpRequestBuilder.body属性可以是OutgoingContent的子类型以及String实例:

  • body = "HELLO WORLD!"
  • body = TextContent("HELLO WORLD!", ContentType.Text.Plain)
  • body = ByteArrayContent("HELLO WORLD!".toByteArray(Charsets.UTF_8))
  • body = LocalFileContent(File("build.gradle"))
  • body = JarFileContent(File("myjar.jar"), "test.txt", ContentType.fromFileExtension("txt").first())
  • body = URIFileContent("https://en.wikipedia.org/wiki/Main_Page")

如果安装JsonFeature ,并将内容类型设置为application/json ,则可以使用任意实例作为body ,它们将被序列化为JSON:

data class HelloWorld(val hello: String)

val client = HttpClient(Apache) {
    install(JsonFeature) {
        serializer = GsonSerializer {
            // Configurable .GsonBuilder
            serializeNulls()
            disableHtmlEscaping()
        }
    }
}

client.post<Unit> {
    url("http://127.0.0.1:8080/")
    body = HelloWorld(hello = "world")
}

或者(使用集成的JsonSerializer ):

val json = io.ktor.client.features.json.defaultSerializer()
client.post<Unit>() {
    url("http://127.0.0.1:8080/")
    body = json.write(HelloWorld(hello = "world")) // Generates an OutgoingContent
}

或使用Jackson(仅JVM):

val json = jacksonObjectMapper()
client.post<Unit> {
    url("http://127.0.0.1:8080/")
    body = TextContent(json.writeValueAsString(userData), contentType = ContentType.Application.Json)
}

请记住,您的课程必须是顶级课程,才能被Gson识别.
如果您尝试发送函数内部的类,则该功能将发送null .

Uploading multipart/form-data

Ktor HTTP客户端支持发出MultiPart请求. 这个想法是使用MultiPartFormDataContent(parts: List<PartData>)作为请求正文的OutgoingContent .

The easiest way is to use the submitFormWithBinaryData method.

或者,您可以直接设置主体:

val request = client.request {
    method = HttpMethod.Post
    body = MultiPartFormDataContent(formData {
        append("key", "value")
    })
}

by  ICOPY.SITE