ZetCode

Kotlin HTTP GET/POST 请求

最后修改于 2024 年 1 月 29 日

本文展示了如何在 Kotlin 中发送 GET 和 POST 请求。 我们使用 HttpClient 和 Fuel 库。

HTTP

超文本传输协议 (HTTP) 是一种用于分布式、协作式、超媒体信息系统的应用协议。HTTP 是万维网数据通信的基础。

在示例中,我们使用了 httpbin.org,这是一个免费提供的 HTTP 请求和响应服务,以及 webcode.me,这是一个用于测试的微型 HTML 页面。

HTTP GET

HTTP GET 方法请求指定资源的表示。使用 GET 的请求应该只检索数据。

HTTP POST

HTTP POST 方法将数据发送到服务器。它通常用于上传文件或提交完成的 Web 表单。

使用 HttpClient 发送 Kotlin GET 请求

HttpClient 是在 Java 中生成 http 请求的工具。

GetRequest.kt
package com.zetcode

import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse

fun main() {
    val client = HttpClient.newBuilder().build();
    val request = HttpRequest.newBuilder()
        .uri(URI.create("http://webcode.me"))
        .build();
        
    val response = client.send(request, HttpResponse.BodyHandlers.ofString());
    println(response.body())
}

我们向 webcode.me 网页发出 GET 请求。

val client = HttpClient.newBuilder().build();

创建一个客户端。

val request = HttpRequest.newBuilder()
    .uri(URI.create("http://webcode.me"))
    .build();

我们构建一个到网页的同步请求。 默认方法是 GET。

val response = client.send(request, HttpResponse.BodyHandlers.ofString());
println(response.body())

我们发送请求,检索响应的内容,并将其打印到控制台。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My html page</title>
</head>
<body>

    <p>
        Today is a beautiful day. We go swimming and fishing.
    </p>
    
    <p>
         Hello there. How are you?
    </p>
    
</body>
</html>

使用 HttpClient 发送 GET 查询参数

下面的例子将一些查询参数附加到 URL。

GetRequestParams.kt
package com.zetcode

import java.net.URI
import java.net.URLEncoder
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse

fun String.utf8(): String = URLEncoder.encode(this, "UTF-8")

fun main() {

    val params = mapOf("name" to "John Doe", "occupation" to "gardener")
    val urlParams = params.map {(k, v) -> "${(k.utf8())}=${v.utf8()}"}
        .joinToString("&")

    val client = HttpClient.newBuilder().build();
    val request = HttpRequest.newBuilder()
        .uri(URI.create("https://httpbin.org/get?${urlParams}"))
        .build();
        
    val response = client.send(request, HttpResponse.BodyHandlers.ofString());
    println(response.body())
}

我们创建一个 GET 请求到 httpbin.org/get,并带有一些 URL 参数。

fun String.utf8(): String = URLEncoder.encode(this, "UTF-8")

这是一个用于编码 URL 参数的字符串扩展方法。

val params = mapOf("name" to "John Doe", "occupation" to "gardener")
val urlParams = params.map {(k, v) -> "${(k.utf8())}=${v.utf8()}"}
    .joinToString("&")

我们有一个值映射。我们使用自定义扩展方法对它们进行 URL 路径编码。

val request = HttpRequest.newBuilder()
    .uri(URI.create("https://httpbin.org/get?${urlParams}"))
    .build();

我们将参数附加到 URL。

{
  "args": {
    "name": "John Doe", 
    "occupation": "gardener"
  }, 
  "headers": {
    "Host": "httpbin.org", 
    "User-Agent": "Java-http-client/14.0.1", 
    "X-Amzn-Trace-Id": "Root=1-6000269f-2389dad80db13d002a8a9003"
  }, 
  ... 
  "url": "https://httpbin.org/get?name=John+Doe&amp;occupation=gardener"
}

使用 HttpClient 发送 Kotlin POST JSON 数据请求

下面的例子使用 HttpClient 发送 POST 请求。数据以 JSON 格式发送。

dependencies {
    testImplementation(kotlin("test-junit"))
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.12.1")
}

对于这个例子,我们需要 jackson-module-kotlin 依赖项。

PostRequestJson.kt
package com.zetcode

import com.fasterxml.jackson.databind.ObjectMapper
import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse

fun main() {

    val values = mapOf("name" to "John Doe", "occupation" to "gardener")

    val objectMapper = ObjectMapper()
    val requestBody: String = objectMapper
        .writeValueAsString(values)

    val client = HttpClient.newBuilder().build();
    val request = HttpRequest.newBuilder()
        .uri(URI.create("https://httpbin.org/post"))
        .POST(HttpRequest.BodyPublishers.ofString(requestBody))
        .build()
    val response = client.send(request, HttpResponse.BodyHandlers.ofString());
    println(response.body())
}

我们生成一个 POST 请求到 httpbin.org/post 网页。 发布的资料取自一个映射,并使用 Jackson 的 ObjectMapper 转换为字符串。

val request = HttpRequest.newBuilder()
    .uri(URI.create("https://httpbin.org/post"))
    .POST(HttpRequest.BodyPublishers.ofString(requestBody))
    .build()

POST 请求是通过 POST 方法生成的。

[Success: {
  "args": {}, 
  "data": "{\"name\":\"John Doe\",\"occupation\":\"gardener\"}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2", 
    "Content-Length": "43", 
    "Content-Type": "application/json", 
    "Host": "httpbin.org", 
    "User-Agent": "Java/14.0.1", 
    "X-Amzn-Trace-Id": "Root=1-60004591-5248fddb69a2221616147220"
  }, 
  "json": {
    "name": "John Doe", 
    "occupation": "gardener"
  }, 
  "origin": "188.167.250.74", 
  "url": "https://httpbin.org/post"
}
]

使用 HttpClient 发送 Kotlin POST FORM 数据请求

使用 application/x-www-form-urlencoded,数据在请求体中发送; 键和值以键值对的形式编码,用 '&' 分隔,键和值之间用 '=' 分隔。

PostRequstForm.kt
package com.zetcode

import java.net.URI
import java.net.URLEncoder
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse

fun main() {

    val values = mapOf("name" to "John Doe", "occupation" to "gardener")

    val client = HttpClient.newBuilder().build();
    val request = HttpRequest.newBuilder()
        .uri(URI.create("https://httpbin.org/post"))
        .POST(formData(values))
        .header("Content-Type", "application/x-www-form-urlencoded")
        .build()
    val response = client.send(request, HttpResponse.BodyHandlers.ofString());
    println(response.body())
}

fun String.utf8(): String = URLEncoder.encode(this, "UTF-8")

fun formData(data: Map<String, String>): HttpRequest.BodyPublisher? {

    val res = data.map {(k, v) -> "${(k.utf8())}=${v.utf8()}"}
        .joinToString("&")

    return HttpRequest.BodyPublishers.ofString(res)
}

我们生成一个带有 FORM 数据的 POST 请求到 httpbin.org/post

.header("Content-Type", "application/x-www-form-urlencoded")

我们将内容类型标头设置为 application/x-www-form-urlencoded

fun String.utf8(): String = URLEncoder.encode(this, "UTF-8")

fun formData(data: Map<String, String>): HttpRequest.BodyPublisher? {

    val res = data.map {(k, v) -> "${(k.utf8())}=${v.utf8()}"}
        .joinToString("&")

    return HttpRequest.BodyPublishers.ofString(res)
}

使用 String.uft8formData 辅助函数,我们创建一个带有 URL 编码值的 body 发布者。

{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "name": "John Doe", 
    "occupation": "gardener"
  }, 
  "headers": {
    "Content-Length": "33", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "Java-http-client/14.0.1", 
    "X-Amzn-Trace-Id": "Root=1-600030bb-7c7f4d026883523b438f2e63"
  }, 
  "json": null, 
  ...
  "url": "https://httpbin.org/post"
}

使用 Fuel 发送 Kotlin GET 请求

Fuel 是一个易于使用的 Kotlin HTTP 网络库。

dependencies {
    testImplementation(kotlin("test-junit"))
    implementation("com.github.kittinunf.fuel:fuel:2.3.1")
}

我们需要添加 fuel 依赖项。

FuelGetRequest.kt
package com.zetcode

import com.github.kittinunf.fuel.httpGet

fun main() {

    val (_, _, result) = "http://webcode.me".httpGet().responseString()
    println(result)
}

该示例向 webcode.me 发送一个简单的 GET 请求。

使用 Fuel 发送 GET 查询参数

下面的例子使用 GET 请求发送一些查询参数。

FuelGetRequestQueryParams.kt
package com.zetcode

import com.github.kittinunf.fuel.httpGet

fun main() {

    val (_, _, result) = "http://httpbin.org/get"
        .httpGet(listOf("name" to "John Doe", "occupation" to "gardener"))
        .responseString()
    println(result)
}

Fuel 库会自动处理 httpGet 中参数的编码。

使用 Fuel 发送 Kotlin POST JSON 数据请求

我们使用 JSON 数据设置 POST 请求。这次我们使用 Gson 库。

dependencies {
    testImplementation(kotlin("test-junit"))
    implementation("com.github.kittinunf.fuel:fuel:2.3.1")
    implementation("com.github.kittinunf.fuel:fuel-gson:2.3.1")
    implementation("com.google.code.gson:gson:2.8.6")
}

我们有 Gson 库的额外依赖项。

FuelPostRequestJson.kt
package com.zetcode

import com.github.kittinunf.fuel.core.extensions.jsonBody
import com.github.kittinunf.fuel.httpPost
import com.google.gson.Gson

data class User(var name: String, var occupation: String)

fun main() {

    val user = User("John Doe", "gardener")

    val (_, _, result) = "https://httpbin.org/post".httpPost()
        .jsonBody(Gson().toJson(user).toString())
        .responseString()
    println(result)
}

我们使用 toJson 方法将用户对象序列化为 JSON 字符串。 我们使用 jsonBody 方法设置 JSON body。

使用 Fuel 发送 Kotlin POST FORM 数据请求

在下面的例子中,我们发送一个带有 FORM 数据的 POST 请求。

FuelPostRequestForm.kt
package com.zetcode

import com.github.kittinunf.fuel.httpPost

fun main() {

    val (_, _, result) = "https://httpbin.org/post"
        .httpPost(listOf("name" to "John Doe", "occupation" to "gardener"))
        .responseString()
    println(result)
}

Fuel 自动将数据转换为 application/x-www-form-urlencoded 内容类型在 httpPost 中。

来源

Kotlin Fuel Github 页面

本文展示了如何在 Kotlin 中发送 GET 和 POST 请求。

作者

我叫 Jan Bodnar,是一位对编程充满热情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。 迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。 我拥有十多年的编程教学经验。

列出 所有 Kotlin 教程