HTTP Requests with Kotlin and khttp
1.简介
目前,基于HTTP协议和基于API的API在编程中至关重要。
在JVM上,我们有几个可用的选项,从较低级的库到非常高级的库,从已建立的项目到新的孩子。 但是,它们中的大多数主要针对Java程序。
在本文中,我们将研究khttp,这是一个惯用的Kotlin库,用于使用基于HTTP的资源和API。
2.依存关系
为了在我们的项目中使用该库,首先我们必须将其添加到我们的依赖项中:
1 2 3 4 5 | <dependency> <groupId>khttp</groupId> <artifactId>khttp</artifactId> <version>0.1.0</version> </dependency> |
由于尚未在Maven Central上启用,因此我们还必须启用JCenter存储库:
1 2 3 4 | <repository> <id>central</id> <url>http://jcenter.bintray.com</url> </repository> |
在撰写本文时,版本0.1.0是当前版本。 当然,我们可以检查JCenter以获得较新的版本。
3.基本用法
HTTP协议的基础很简单,即使细节很复杂。 因此,khttp也具有简单的界面。
对于每个HTTP方法,我们都可以在khttp包中找到一个包级函数,例如get,post等。
所有函数都使用相同的参数集并返回Response对象; 我们将在以下各节中详细介绍这些内容。
在本文的过程中,我们将使用完全限定的格式,例如khttp.put。 当然,在我们的项目中,我们可以导入并可能重命名这些方法:
1 | import khttp.delete as httpDelete |
注意:为了清楚起见,我们在代码示例中添加了类型声明,因为如果没有IDE,它们将很难遵循。
4.一个简单的请求
每个HTTP请求至少具有两个必需的组件:方法和URL。 在khttp中,方法由我们调用的函数确定,如上一节所述。
URL是该方法唯一需要的参数。 因此,我们可以轻松执行一个简单的请求:
1 | khttp.get("http://httpbin.org/get") |
在以下各节中,我们将考虑所有成功完成的请求。
4.1。 添加参数
除基本URL之外,我们通常还必须提供查询参数,尤其是对于GET请求。
khttp的方法接受params参数,该参数是要包含在查询String中的键/值对的Map:
1 2 3 | khttp.get( url ="http://httpbin.org/get", params = mapOf("key1" to"value1","keyn" to"valuen")) |
请注意,我们已经使用mapOf函数来动态构建Map; 最终的请求URL将是:
1 | http://httpbin.org/get?key1=value1&keyn=valuen |
5.请求主体
我们通常需要执行的另一个常见操作是发送数据,通常作为POST或PUT请求的有效负载。
为此,该库提供了几个选项,我们将在以下各节中进行研究。
5.1。 发送JSON有效负载
我们可以使用json参数发送JSON对象或数组。 它可以是几种不同的类型:
org.json库提供的JSONObject或JSONArray
一个Map,转换为JSON对象
Collection,Iterable或数组,它转换为JSON数组
我们可以轻松地将之前的GET示例转换为POST示例,该示例将发送一个简单的JSON对象:
1 2 3 | khttp.post( url ="http://httpbin.org/post", json = mapOf("key1" to"value1","keyn" to"valuen")) |
请注意,从集合到JSON对象的转换很浅。 例如,地图列表不会转换为JSON对象的JSON数组,而是转换为字符串数组。
为了进行深度转换,我们需要一个更复杂的JSON映射库,例如Jackson。 库的转换工具仅适用于简单情况。
5.2。 发送表单数据(URL编码)
要发送表单数据(URL编码,如HTML表单),我们将data参数与Map结合使用:
1 2 3 | khttp.post( url ="http://httpbin.org/post", data = mapOf("key1" to"value1","keyn" to"valuen")) |
5.3。 上传文件(多部分表单)
我们可以发送一个或多个编码为多部分表单数据请求的文件。
在这种情况下,我们使用files参数:
1 2 3 4 5 | khttp.post( url ="http://httpbin.org/post", files = listOf( FileLike("file1","content1"), FileLike("file2", File("kitty.jpg")))) |
我们可以看到http使用File Like抽象,这是一个具有名称和内容的对象。 内容可以是字符串,字节数组,文件或路径。
5.4。 发送原始内容
如果以上选项都不适合,我们可以使用InputStream发送原始数据作为HTTP请求的主体:
1 | khttp.post(url ="http://httpbin.org/post", data = someInputStream) |
在这种情况下,我们很可能也需要手动设置一些标题,我们将在后面的部分中介绍这些标题。
6.处理回应
到目前为止,我们已经看到了将数据发送到服务器的各种方法。 但是许多HTTP操作还是有用的,因为它们也会返回数据。
khttp基于阻塞的I / O,因此与HTTP方法相对应的所有功能都返回一个Response对象,其中包含从服务器接收到的响应。
根据内容的类型,此对象具有可访问的各种属性。
6.1。 JSON回应
如果我们知道响应是JSON对象或数组,则可以使用jsonObject和jsonArray属性:
1 2 3 | val response : Response = khttp.get("http://httpbin.org/get") val obj : JSONObject = response.jsonObject print(obj["someProperty"]) |
6.2。 文字或二进制回复
如果我们想将响应作为字符串读取,则可以使用text属性:
1 |
或者,如果我们想将其读取为二进制数据(例如文件下载),则可以使用content属性:
1 | val imageData : ByteArray = response.content |
最后,我们还可以访问基础InputStream:
1 |
7.高级用法
让我们也看一下一些更有用的高级用法模式,这些模式通常是有用的,并且在上一节中我们还没有讨论过。
7.1。 处理标题和Cookie
所有khttp函数都采用headers参数,该参数是标头名称和值的映射。
1 2 3 | val response = khttp.get( url ="http://httpbin.org/get", headers = mapOf("header1" to"1","header2" to"2")) |
对于Cookie同样:
1 2 3 | val response = khttp.get( url ="http://httpbin.org/get", cookies = mapOf("cookie1" to"1","cookie2" to"2")) |
我们还可以在响应中访问服务器发送的标头和cookie:
1 2 |
7.2。 处理错误
HTTP中可能会产生两种类型的错误:错误响应,例如404 –未找到,是协议的一部分; 和低级错误,例如"连接被拒绝"。
第一种不会导致khttp抛出异常。 相反,我们应该检查Response statusCode属性:
1 2 3 4 5 6 | val response = khttp.get(url ="http://httpbin.org/nothing/to/see/here") if(response.statusCode == 200) { process(response) } else { handleError(response) } |
相反,较低级别的错误导致底层Java I / O子系统(如ConnectException)引发异常。
7.3。 流式响应
有时,服务器可以响应大量内容,并且/或者花费很长时间做出响应。 在这些情况下,我们可能希望分块处理响应,而不是等待响应完成并占用内存。
如果我们想指示库给我们一个流响应,那么我们必须传递true作为stream参数:
1 | val response = khttp.get(url ="http://httpbin.org", stream = true) |
然后,我们可以分块处理它:
1 | response.contentIterator(chunkSize = 1024).forEach { arr : ByteArray -> handleChunk(arr) } |
7.4。 非标准方法
在极少数情况下,我们需要使用khttp本身没有提供的HTTP方法(或动词),例如,对于HTTP协议的某些扩展,例如WebDAV,我们仍然可以解决。
实际上,khttp包中与HTTP方法相对应的所有函数都是使用通用请求函数实现的,我们也可以使用该函数:
1 2 3 4 | khttp.request( method ="COPY", url ="http://httpbin.org/get", headers = mapOf("Destination" to"/copy-of-get")) |
7.5。 其他特性
我们还没有涉及khttp的所有功能。 例如,我们没有讨论超时,重定向和历史记录或异步操作。
官方文档是有关库及其所有功能的最终信息来源。
8.结论
在本教程中,我们已经看到了如何使用惯用的库khttp在Kotlin中发出HTTP请求。
所有这些示例的实现都可以在GitHub项目中找到–这是一个Maven项目,因此应易于导入和运行。