KotlinとkhttpによるHTTPリクエスト

Kotlinおよびkhttpを使用したHTTPリクエスト

1. 前書き

HTTPプロトコルとそれに基づいて構築されたAPIは、最近のプログラミングにおいて最も重要です。

JVMには、低レベルのライブラリから非常に高レベルのライブラリまで、確立されたプロジェクトからブロック上の新しい子供まで、いくつかの利用可能なオプションがあります。 ただし、それらのほとんどは主にJavaプログラムを対象としています。

この記事では、we’re going to look at khttp, an idiomatic Kotlin library for consuming HTTP-based resourcesとAPIについて説明します。

2. 依存関係

プロジェクトでライブラリを使用するには、まずライブラリを依存関係に追加する必要があります。


    khttp
    khttp
    0.1.0

これはまだMaven Centralにないため、JCenterリポジトリも有効にする必要があります。


    central
    http://jcenter.bintray.com

バージョン0.1.0は、執筆時点で現在のものです。 もちろん、check JCenter for a newer oneも可能です。

3. 基本的な使い方

HTTPプロトコルの基本は単純ですが、詳細は非常に複雑になる場合があります。 したがって、khttpのインターフェイスも単純です。

get,postなどのFor every HTTP method, we can find a package-level function in the khttp package

関数はすべて同じ引数のセットを取り、Responseオブジェクトを返します。これらの詳細については、次のセクションで説明します。

この記事では、khttp.putなどの完全修飾形式を使用します。 私たちのプロジェクトでは、もちろん、これらのメソッドをインポートし、場合によっては名前を変更できます。

import khttp.delete as httpDelete

Note: we’ve added type declarations for clarity throughout code examplesは、IDEがないと、追跡が難しい場合があるためです。

4. 簡単なリクエスト

Every HTTP request has at least two required components: a method and a URL。 khttpでは、前のセクションで見たように、メソッドは呼び出す関数によって決定されます。

URLはメソッドに必要な唯一の引数です。そのため、簡単なリクエストを簡単に実行できます。

khttp.get("http://httpbin.org/get")

次のセクションでは、すべてのリクエストが正常に完了することを検討します。

4.1. パラメータを追加する

多くの場合、特にGETリクエストの場合、ベースURLに加えてクエリパラメータを提供する必要があります。

クエリに含めるキーと値のペアのMapであるkhttp’s methods accept a params argumentString:

khttp.get(
  url = "http://httpbin.org/get",
  params = mapOf("key1" to "value1", "keyn" to "valuen"))

mapOf関数を使用して、その場でMapを作成したことに注意してください。結果のリクエストURLは次のようになります。

http://httpbin.org/get?key1=value1&keyn=valuen

5. リクエストボディ

頻繁に実行する必要がある別の一般的な操作は、通常POSTまたはPUT要求のペイロードとしてデータを送信することです。

このために、ライブラリには、次のセクションで検討するいくつかのオプションが用意されています。

5.1. JSONペイロードの送信

We can use the json argument to send a JSON object or array.いくつかの異なるタイプがあります。

  • org.jsonライブラリによって提供されるJSONObjectまたはJSONArray

  • JSONオブジェクトに変換されるMap

  • JSON配列に変換されるCollectionIterableまたは配列

以前のGETの例を簡単なJSONオブジェクトを送信するPOSTに簡単に変更できます。

khttp.post(
  url = "http://httpbin.org/post",
  json = mapOf("key1" to "value1", "keyn" to "valuen"))

コレクションからJSONオブジェクトへの変換は浅いことに注意してください。 たとえば、MapListは、JSONオブジェクトのJSON配列ではなく、文字列の配列に変換されます。

深い変換を行うには、Jacksonなどのより複雑なJSONマッピングライブラリが必要です。 ライブラリの変換機能は、単純な場合のみを対象としています。

5.2. フォームデータの送信(URLエンコード)

フォームデータ(HTMLフォームのようにURLエンコード)を送信するには、Mapとともにdata引数を使用します。

khttp.post(
  url = "http://httpbin.org/post",
  data = mapOf("key1" to "value1", "keyn" to "valuen"))

5.3. ファイルのアップロード(マルチパートフォーム)

マルチパートフォームデータリクエストとしてエンコードされた1つ以上のファイルを送信できます。

その場合、files引数を使用します。

khttp.post(
  url = "http://httpbin.org/post",
  files = listOf(
    FileLike("file1", "content1"),
    FileLike("file2", File("kitty.jpg"))))

khttpがFileLike抽象化を使用していることがわかります。これは、名前とコンテンツを持つオブジェクトです。 コンテンツは、文字列、バイト配列、File、またはPathにすることができます。

5.4. 生コンテンツの送信

上記のオプションのいずれも適切でない場合は、InputStreamを使用して、HTTPリクエストの本文として生データを送信できます。

khttp.post(url = "http://httpbin.org/post", data = someInputStream)

この場合、ヘッダーも手動で設定する必要があります。これについては、後のセクションで説明します。

6. 応答の処理

これまで、サーバーにデータを送信するさまざまな方法を見てきました。 ただし、多くのHTTP操作は、データが返されるため便利です。

khttpはブロッキングI / Oに基づいているため、サーバーから受信した応答を含むall functions corresponding to HTTP methods return a Response object

このオブジェクトには、コンテンツのタイプに応じてアクセスできるさまざまなプロパティがあります。

6.1. JSON応答

応答がJSONオブジェクトまたは配列であることがわかっている場合は、jsonObjectおよびjsonArrayプロパティを使用できます。

val response : Response = khttp.get("http://httpbin.org/get")
val obj : JSONObject = response.jsonObject
print(obj["someProperty"])

6.2. テキストまたはバイナリ応答

代わりに応答をStringとして読み取りたい場合は、textプロパティを使用できます。

val message : String = response.text

または、バイナリデータとして読み込む場合(例: ファイルのダウンロード)contentプロパティを使用します:

val imageData : ByteArray = response.content

最後に、基になるInputStreamにアクセスすることもできます。

val inputStream : InputStream = response.raw

7. 高度な使用法

また、一般的に役立つ、前のセクションではまだ扱っていない、より高度な使用パターンをいくつか見てみましょう。

7.1. ヘッダーとCookieの処理

ヘッダー名と値のMapであるAll khttp functions take a headers argument

val response = khttp.get(
  url = "http://httpbin.org/get",
  headers = mapOf("header1" to "1", "header2" to "2"))

クッキーについても同様:

val response = khttp.get(
  url = "http://httpbin.org/get",
  cookies = mapOf("cookie1" to "1", "cookie2" to "2"))

応答でサーバーから送信されたヘッダーとCookieにアクセスすることもできます。

val contentType : String = response.headers["Content-Type"]
val sessionID : String = response.cookies["JSESSIONID"]

7.2. エラー処理

HTTPで発生する可能性のあるエラーには、次の2種類があります。404-Not Foundなど、プロトコルの一部であるエラー応答。 「接続が拒否されました」などの低レベルのエラー。

最初の種類では、khttpが例外をスローすることはありません。代わりに、we should check the Response statusCode property

val response = khttp.get(url = "http://httpbin.org/nothing/to/see/here")
if(response.statusCode == 200) {
    process(response)
} else {
    handleError(response)
}

代わりに、低レベルのエラーにより、ConnectExceptionなどの基になるJava I / Oサブシステムから例外がスローされます。

7.3. ストリーミング応答

サーバーが大きなコンテンツで応答する場合や、応答に時間がかかる場合があります。 このような場合、応答が完了してメモリを占有するのを待つのではなく、応答をチャンクで処理することができます。

ストリーミング応答を返すようにライブラリに指示する場合は、stream引数としてtrueを渡す必要があります。

val response = khttp.get(url = "http://httpbin.org", stream = true)

次に、チャンクで処理できます。

response.contentIterator(chunkSize = 1024).forEach { arr : ByteArray -> handleChunk(arr) }

7.4. 非標準的な方法

khttpがネイティブに提供しないHTTPメソッド(または動詞)を使用する必要があるというまれなケースでは、たとえば、WebDAVなどのHTTPプロトコルの拡張については、引き続き説明します。

実際、HTTPメソッドに対応するkhttpパッケージ内のすべての関数は、私たちも使用できる汎用のrequest関数を使用して実装されています。

khttp.request(
  method = "COPY",
  url = "http://httpbin.org/get",
  headers = mapOf("Destination" to "/copy-of-get"))

7.5. その他の機能

khttpのすべての機能に触れたわけではありません。 たとえば、タイムアウト、リダイレクトと履歴、または非同期操作については説明していません。

The official documentationは、ライブラリとそのすべての機能に関する究極の情報源です。

8. 結論

このチュートリアルでは、慣用的なライブラリkhttpを使用してKotlinでHTTPリクエストを作成する方法を説明しました。

これらすべての例の実装はthe GitHub projectにあります。これはMavenプロジェクトであるため、そのままインポートして実行するのは簡単です。