1前書き

HTTPプロトコルとその上に構築されたAPIは、今日のプログラミングで最も重要です。

JVMでは、低レベルのライブラリから非常に高レベルのライブラリ、確立されたプロジェクトから新たなブロックに至るまで、いくつかの選択肢があります。ただし、それらのほとんどは主にJavaプログラムを対象としています。

この記事では、HTTPベースのリソースとAPIを消費するための慣用的なKotlinライブラリであるhttp://khttp.readthedocs.io/en/latest/[khttp]を見ていきます。


2依存関係

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

<dependency>
    <groupId>khttp</groupId>
    <artifactId>khttp</artifactId>
    <version>0.1.0</version>
</dependency>

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

<repository>
    <id>central</id>
    <url>http://jcenter.bintray.com</url>
</repository>

執筆時点でのバージョンは0.1.0です。もちろん、https://bintray.com/jkcclemens/maven/khttp[JCenterで新しいものを確認してください]。

** 3基本的な使い方

HTTPプロトコルの基本は単純ですが、細かい詳細は非常に複雑になる可能性があります。したがって、khttpも同様にシンプルなインターフェースを持っています。

  • すべてのHTTPメソッドに対して、

    khttp

    パッケージ内に

    get、


    post

    などのパッケージレベルの関数があります。

関数はすべて同じ引数のセットを取り、

Response

オブジェクトを返します。次のセクションでこれらの詳細を確認します。

この記事では、

khttp.put

などの完全修飾形式を使用します。私たちのプロジェクトでは、もちろん、これらのメソッドをインポートして名前を変更することができます。

import khttp.delete as httpDelete

  • 注:コード例全体を通して、明快さのために型宣言を追加しています。** IDEがないと、従うことは難しいかもしれません。


4簡単なリクエスト

  • すべてのHTTPリクエストには、少なくとも2つの必須コンポーネントがあります。メソッドとURLです。 khttpでは、前のセクションで見たように、メソッドは呼び出す関数によって決まります。

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

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

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


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

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

  • khttpのメソッドは

    params

    引数** を受け取ります。これは

    String:

    クエリに含めるキーと値のペアの

    Map

    です。

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リクエストボディ

私たちがよく行う必要があるもう1つの一般的な操作は、通常POSTまたはPUTリクエストのペイロードとしてデータを送信することです。

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


5.1. JSONペイロードを送信する


  • json

    引数を使用してJSONオブジェクトまたは配列を送信することができます。

  • org.jsonライブラリによって提供される

    JSONObject

    または

    JSONArray

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

Map


  • Collection



    Iterable

    、または配列。これらはJSONに変換されます。

アレイ

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

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

コレクションからJSONオブジェクトへの変換は浅いことに注意してください。たとえば、

Map



List

はJSONオブジェクトのJSON配列には変換されませんが、文字列の配列には変換されません。

ディープコンバージョンのためには、Jacksonのようなもっと複雑なJSONマッピングライブラリが必要です。ライブラリの変換機能は単純な場合のためだけのものです。

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

**

フォームデータを送信するには(HTMLフォームのようにURLエンコードされた)、

dap

引数と

Map

を使用します。

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に基づいているため、

HTTPメソッドに対応するすべての関数は

サーバーから受信した応答を含む

Response

オブジェクトを返します。

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


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. ヘッダとクッキーの処理

  • すべてのkhttp関数は、ヘッダ名と値の

    Map

    である

    headers

    引数を取ります。

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"]----

[[error-handling]]

====  **  7.2. エラー処理**

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

最初の種類では、khttpが例外をスローすることはありません。代わりに、__Response statusCode__プロパティを確認してください。

[source,java,gutter:,true]

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サブシステムから例外がスローされます。

[[streaming-response]]

====  **  7.3. ストリーミングレスポンス**

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

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

[source,java,gutter:,true]

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

それから、我々はそれを塊で処理することができます:

[source,java,gutter:,true]

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

[[other-methods]]

====  **  7.4. 非標準メソッド

まれに、khttpがネイティブに提供していないHTTPメソッド(または動詞)を使用する必要がある場合(WebDAVなどのHTTPプロトコルの拡張について)、まだ説明しています。

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

[source,java,gutter:,true]

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

====  **  7.5. その他の機能**

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

http://khttp.readthedocs.io/en/latest/[公式ドキュメント]は、ライブラリとそのすべての機能に関する究極の情報源です。

===  **  8結論**

このチュートリアルでは、慣用的なライブラリkhttpを使ってKotlinでHTTPリクエストを行う方法を見ました。

これらすべての例の実装はhttps://github.com/eugenp/tutorials/tree/master/kotlin-libraries[GitHubプロジェクト]にあります - これはMavenプロジェクトなので、インポートして実行するのは簡単なはずです。そのまま。