［翻訳］curl vignette: 「curl パッケージ：libcurlへのモダンなRインターフェイス」

この文書は，Jeroen Ooms 他によるRパッケージ [`curl`](https://cran.r-project.org/web/packages/curl/) (version 2.1) のビネット ["The curl package: a modern R interface to libcurl"](https://cran.r-project.org/web/packages/curl/vignettes/intro.html) の日本語訳です．

License: [MIT](https://opensource.org/licenses/MIT)

----



<!-- The curl package provides bindings to the [libcurl](http://curl.haxx.se/libcurl/) C library for R. The package supports retrieving data in-memory, downloading to disk, or streaming using the [R "connection" interface](https://stat.ethz.ch/R-manual/R-devel/library/base/html/connections.html). Some knowledge of curl is recommended to use this package. For a more user-friendly HTTP client, have a look at the  [httr](https://cran.r-project.org/package=httr/vignettes/quickstart.html) package which builds on curl with HTTP specific tools and logic. -->

curl パッケージは，Cライブラリ [libcurl](http://curl.haxx.se/libcurl/) へのRバインディングを提供します．このパッケージは，メモリへのデータ読込やディスクへのダウンロード，[Rのコネクションインターフェイス](https://stat.ethz.ch/R-manual/R-devel/library/base/html/connections.html)を用いたストリーミング処理をサポートしています．よりユーザにやさしいHTTPクライアントが必要であれば，curlをもとにしてHTTP用のツールや処理が追加された [httr](https://cran.r-project.org/package=httr/vignettes/quickstart.html) パッケージを見てみてください．


<!-- ## Request interfaces -->

## リクエストのインターフェイス

<!-- The curl package implements several interfaces to retrieve data from a URL: -->

curl パッケージはURLからデータを読み込むためのいくつかのインターフェイスを実装しています．

<!-- - `curl_fetch_memory()`  saves response in memory -->
<!-- - `curl_download()` or `curl_fetch_disk()`  writes response to disk -->
<!-- - `curl()` or `curl_fetch_stream()` streams response data -->
<!-- - `curl_fetch_multi()` (Advanced) process responses via callback functions -->

- `curl_fetch_memory()` はレスポンスをメモリに保存します
- `curl_download()` や `curl_fetch_disk()` はレスポンスをディスクに書き込みます
- `curl()` や `curl_fetch_stream()` はレスポンスのデータをストリーミング処理します
- `curl_fetch_multi()` はレスポンスをコールバック関数によって処理します（高度な機能）

<!-- Each interface performs the same HTTP request, they only differ in how response data is processed. -->

どのインターフェイスも同じHTTPリクエストを行いますが，レスポンスのデータをどう処理するかだけが異なります．

<!-- ### Getting in memory -->

### メモリに読み込む場合

<!-- The `curl_fetch_memory` function is a blocking interface which waits for the request to complete and returns a list with all content (data, headers, status, timings) of the server response. -->

`curl_fetch_memory()` 関数はブロッキングインターフェイスであり，リクエストが完了してサーバのレスポンス内容すべて（データ，ヘッダ，ステータス，タイミング）を含むリストが返ってくるまで待機します．


```r
req <- curl_fetch_memory("https://httpbin.org/get")
str(req)
```

```
List of 6
 $ url        : chr "https://httpbin.org/get"
 $ status_code: int 200
 $ headers    : raw [1:220] 48 54 54 50 ...
 $ modified   : POSIXct[1:1], format: NA
 $ times      : Named num [1:6] 0 0 0.265 1.513 1.778 ...
  ..- attr(*, "names")= chr [1:6] "redirect" "namelookup" "connect" "pretransfer" ...
 $ content    : raw [1:232] 7b 0a 20 20 ...
```

```r
parse_headers(req$headers)
```

```
[1] "HTTP/1.1 200 OK"                       
[2] "Server: nginx"                         
[3] "Date: Sat, 15 Oct 2016 13:21:29 GMT"   
[4] "Content-Type: application/json"        
[5] "Content-Length: 232"                   
[6] "Connection: keep-alive"                
[7] "Access-Control-Allow-Origin: *"        
[8] "Access-Control-Allow-Credentials: true"
```

```r
cat(rawToChar(req$content))
```

```
{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Host": "httpbin.org", 
    "User-Agent": "r/curl/jeroen"
  }, 
  "origin": "106.161.101.127", 
  "url": "https://httpbin.org/get"
}
```

<!-- The `curl_fetch_memory` interface is the easiest interface and most powerful for buidling API clients. However it is not suitable for downloading really large files because it is fully in-memory. If you are expecting 100G of data, you probably need one of the other interfaces. -->

`curl_fetch_memory()` インターフェイスは，APIクライアントを構築するための最も簡単で強力なインターフェイスです．ですがメモリ内ですべての処理を行うので，非常に大きなファイルをダウンロードするのには向いていません．もしデータが100GBあると予想しているのであれば，きっとどれか他のインターフェイスが必要になるでしょう．

<!-- ### Downloading to disk -->

### ディスクにダウンロードする場合

<!-- The second method is `curl_download`, which has been designed as a drop-in replacement for `download.file` in r-base. It writes the response straight to disk, which is useful for downloading (large) files. -->

ふたつめの方法は `curl_download()` です．これは base R の `download.file()` 関数を簡単に代替できるように設計されています．この関数はレスポンスを直接ディスクに書き込むので，（大きな）ファイルをダウンロードするのに便利です．


```r
tmp <- tempfile()
curl_download("https://httpbin.org/get", tmp)
cat(readLines(tmp), sep = "\n")
```

```
{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Host": "httpbin.org", 
    "User-Agent": "r/curl/jeroen"
  }, 
  "origin": "106.161.101.127", 
  "url": "https://httpbin.org/get"
}
```

<!-- ### Streaming data -->

### データをストリーミングする場合

<!-- The most flexible interface is the `curl` function, which has been designed as a drop-in replacement for base `url`. It will create a so-called connection object, which allows for incremental (asynchronous) reading of the response. -->

最も柔軟なインターフェイスは `curl()` 関数です．これは base R の`url()` を簡単に代替できるように設計されています．この関数はいわゆるコネクションオブジェクトを作成し，レスポンスを漸進的に（非同期に）読み込むことを可能にします．


```r
con <- curl("https://httpbin.org/get")
open(con)

# 3行取得
out <- readLines(con, n = 3)
cat(out, sep = "\n")
```

```
{
  "args": {}, 
  "headers": {
```

```r
# さらに3行取得
out <- readLines(con, n = 3)
cat(out, sep = "\n")
```

```
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Host": "httpbin.org", 
```

```r
# 残りの行を取得
out <- readLines(con)
close(con)
cat(out, sep = "\n")
```

```
    "User-Agent": "r/curl/jeroen"
  }, 
  "origin": "106.161.101.127", 
  "url": "https://httpbin.org/get"
}
```

<!-- The example shows how to use `readLines` on an opened connection to read `n` lines at a time. Similarly `readBin` is used to read `n` bytes at a time for stream parsing binary data. -->

この例では開いたコネクションに対して `readLines()` を使い，一度に `n` 行ずつ読み込む方法を示しています．同様に，ストリームから一度にデータを `n` バイトずつ読み込んでパースするには `readBin()` を使います．

<!-- ### Non-blocking requests -->

### ノンブロッキングリクエスト

<!-- As of `curl 2.0` the package provides a non-blocking interface which can perform multiple simultaneous requests. The `curl_fetch_multi` adds a request to a pool and returns immediately; it does not actually perform the request.  -->

curl 2.0 から，curl パッケージは同時に多数のリクエストを実行するノンブロッキングインターフェイスを提供しています．`curl_fetch_multi()`はリクエストをプールに追加したらすぐに返ってきて，実際にはリクエストを実行しません．


```r
pool <- new_pool()
cb <- function(req){cat("done:", req$url, ": HTTP:", req$status, "\n")}
curl_fetch_multi('https://www.google.com', done = cb, pool = pool)
curl_fetch_multi('https://cloud.r-project.org', done = cb, pool = pool)
curl_fetch_multi('https://httpbin.org/blabla', done = cb, pool = pool)
```

<!-- When we call `multi_run()`, all scheduled requests are performed concurrently. The callback functions get triggered when the request completes. -->

`multi_run()` を呼ぶと，登録されたすべてのリクエストが並行的に実行されます．リクエストが完了するとコールバック関数が呼ばれます．


```r
# これで実際にリクエストが実行される
out <- multi_run(pool = pool)
```

```
done: https://cloud.r-project.org/ : HTTP: 200 
done: https://www.google.co.jp/?gfe_rd=cr&ei=XC0CWKXAL4SL8QfUgJ6ICA : HTTP: 200 
done: https://httpbin.org/blabla : HTTP: 404 
```

```r
print(out)
```

```
$success
[1] 3

$error
[1] 0

$pending
[1] 0
```

<!-- The system allows for running many concurrent non-blocking requests. However it is quite complex and requires careful specification of handler functions. -->

このシステムによって多数の並行的なノンブロッキングリクエストを実行することができますが，かなり複雑ですし，ハンドラ関数を注意深く設計する必要があります．

<!-- ## Exception handling -->

## 例外処理

<!-- A HTTP requests can encounter two types of errors: -->

HTTPリクエストには2種類のエラーがあり得ます．

<!--
1. Connection failure: network down, host not found, invalid SSL certficate, etc
2. HTTP non-success status: 401 (DENIED), 404 (NOT FOUND), 503 (SERVER PROBLEM), etc
-->

1. 接続失敗：ネットワークがダウンしている，ホストが見つからない，SSL証明書が不正，等

1. HTTPステータスが非成功：401（アクセス拒否），404（リソースが見つからない），503（サーバの問題），等

<!-- The first type of errors (connection failures) will always raise an error in R for each interface. However if the requests succeeds and the server returns a non-success HTTP status code, only `curl()` and `curl_download()` will raise an error. Let's dive a little deeper into this. -->

ひとつめの種類のエラー（接続失敗）は，各インターフェイスにおいて必ずRのエラーを発生させます．しかし，リクエストは成功したもののサーバが非成功のHTTPステータスコードを返したという場合には， `curl()` と `curl_download()` だけがエラーを発生させます．これについてもう少し詳しく見てみましょう．

<!-- ### Error automatically -->

### 自動的にエラーを発生させる場合

<!-- The `curl` and `curl_download` functions are safest to use because they automatically raise an error if the request was completed but the server returned a non-success (400 or higher) HTTP status. This mimics behavior of base functions `url` and `download.file`. Therefore we can safely write code like this: -->

`curl()` 関数と `curl_download()` 関数が最も安全に使えるものです．というのもこれらの関数は，リクエストは完了したがサーバが非成功の（400やそれより大きい）HTTPステータスを返した場合にエラーを発生させるからです．これは base R の `url()` 関数と `download.file()` 関数のふるまいを真似たものです．これによって，以下のようなコードを安全に書くことができます．


```r
# これでOK
curl_download('https://cran.r-project.org/CRAN_mirrors.csv', 'mirrors.csv')
mirros <- read.csv('mirrors.csv')
unlink('mirrors.csv')
```

<!-- If the HTTP request was unsuccesful, R will not continue: -->

もしHTTPリクエストが失敗した場合，Rは実行を停止します．


```r
# おっと！URLを書き間違えた！
curl_download('https://cran.r-project.org/CRAN_mirrorZ.csv', 'mirrors.csv')
```

```
Error in curl_download("https://cran.r-project.org/CRAN_mirrorZ.csv", : HTTP error 404.
```

```r
con <- curl('https://cran.r-project.org/CRAN_mirrorZ.csv')
open(con)
```

```
Error in open.connection(con): HTTP error 404.
```




<!-- ### Check manually -->

### 手動で確認する場合

<!-- When using any of the `curl_fetch_*` functions it is important to realize that these do **not** raise an error if the request was completed but returned a non-200 status code. When using `curl_fetch_memory` or `curl_fetch_disk` you need to implement such application logic yourself and check if the response was successful. -->

`curl_fetch_*()` 系関数のいずれかを使う場合，これらの関数は，リクエストは完了したが200以外のステータスコードが返ってきた場合にエラーを発生**させない**，ということを理解しておくのが重要です．`curl_fetch_memory()` や `curl_fetch_disk()` を使うときには，自分でそのようなアプリケーションのロジックを実装して，レスポンスが成功かどうか確認する必要があります．


```r
req <- curl_fetch_memory('https://cran.r-project.org/CRAN_mirrors.csv')
print(req$status_code)
```

```
[1] 200
```

<!-- Same for downloading to disk. If you do not check your status, you might have downloaded an error page! -->

ディスクにダウンロードする場合も同様です．ステータスをチェックしないと，エラーページをダウンロードしてしまっているかもしれません！


```r
# おっと書き間違えた！
req <- curl_fetch_disk('https://cran.r-project.org/CRAN_mirrorZ.csv', 'mirrors.csv')
print(req$status_code)
```

```
[1] 404
```

```r
# 思ってたCSVファイルと違うぞ！
head(readLines('mirrors.csv'))
```

```
[1] "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"                               
[2] "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\""               
[3] "  \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"                 
[4] "<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" xml:lang=\"en\">"
[5] "<head>"                                                                   
[6] "<title>Object not found!</title>"                                         
```

```r
unlink('mirrors.csv')
```

<!-- If you *do* want the `curl_fetch_*` functions to automatically raise an error, you should set the [`FAILONERROR`](https://curl.haxx.se/libcurl/c/CURLOPT_FAILONERROR.html) option to `TRUE` in the handle of the request. -->

もし**本当に** `curl_fetch_*()` 系関数が自動的にエラーを発生させるようにしたいのであれば，リクエストハンドルの [`FAILONERROR`](https://curl.haxx.se/libcurl/c/CURLOPT_FAILONERROR.html) オプションを `TRUE` に設定するべきです．


```r
h <- new_handle(failonerror = TRUE)
curl_fetch_memory('https://cran.r-project.org/CRAN_mirrorZ.csv', handle = h)
```

```
Error in curl_fetch_memory("https://cran.r-project.org/CRAN_mirrorZ.csv", : HTTP response code said error
```

<!-- ## Customizing requests -->

## リクエストのカスタマイズ

<!-- By default libcurl uses HTTP GET to issue a request to an HTTP url. To send a customized request, we first need to create and configure a curl handle object that is passed to the specific download interface.   -->

デフォルトの設定では， libcurl は HTTP URL へのリクエストを発行するのに HTTP GET を使います．カスタマイズしたリクエストを送るには，ダウンロードインターフェイスに渡すための curl ハンドルオブジェクトの作成と設定をはじめに行う必要があります．

<!-- ### Configuring a handle -->

### ハンドルの設定

<!-- Creating a new handle is done using `new_handle`. After creating a handle object, we can set the libcurl options and http request headers.  -->

`new_handle()`を使うと新しいハンドルが作成されます．ハンドルオブジェクトを作成したら， libcurl のオプションと HTTP リクエストのヘッダを設定することができます．


```r
h <- new_handle()
handle_setopt(h, copypostfields = "moo=moomooo");
handle_setheaders(h,
  "Content-Type" = "text/moo",
  "Cache-Control" = "no-cache",
  "User-Agent" = "A cow"
)
```

<!-- Use the `curl_options()` function to get a list of the options supported by your version of libcurl. The [libcurl documentation](http://curl.haxx.se/libcurl/c/curl_easy_setopt.html) explains what each option does. Option names are not case sensitive.  -->

自分が使っているバージョンの libcurl でサポートされているオプションのリストを見るには，`curl_options()` 関数を使ってください．各オプションが何をするものなのかは [libcurl のドキュメント](http://curl.haxx.se/libcurl/c/curl_easy_setopt.html)で解説されています．オプション名の大文字と小文字は区別されません．

<!-- After the handle has been configured, it can be used with any of the download interfaces to perform the request. For example `curl_fetch_memory` will load store the output of the request in memory: -->

設定が終わったら，ハンドルはどのダウンロードインターフェイスでリクエストを実行するのにも使えます．


```r
req <- curl_fetch_memory("http://httpbin.org/post", handle = h)
cat(rawToChar(req$content))
```

```
{
  "args": {}, 
  "data": "moo=moomooo", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Cache-Control": "no-cache", 
    "Content-Length": "11", 
    "Content-Type": "text/moo", 
    "Host": "httpbin.org", 
    "User-Agent": "A cow"
  }, 
  "json": null, 
  "origin": "106.161.101.127", 
  "url": "http://httpbin.org/post"
}
```

<!-- Alternatively we can use `curl()` to read the data of via a connetion interface: -->

代わりに `curl()` を使ってコネクションインターフェイスでデータを読むこともできます．


```r
con <- curl("http://httpbin.org/post", handle = h)
cat(readLines(con), sep = "\n")
```

```
{
  "args": {}, 
  "data": "moo=moomooo", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Cache-Control": "no-cache", 
    "Content-Length": "11", 
    "Content-Type": "text/moo", 
    "Host": "httpbin.org", 
    "User-Agent": "A cow"
  }, 
  "json": null, 
  "origin": "106.161.101.127", 
  "url": "http://httpbin.org/post"
}
```



<!-- Or we can use `curl_download` to write the response to disk: -->

また， `curl_download()` を使ってレスポンスをディスクに書き込むこともできます．


```r
tmp <- tempfile()
curl_download("http://httpbin.org/post", destfile = tmp, handle = h)
cat(readLines(tmp), sep = "\n")
```

```
{
  "args": {}, 
  "data": "moo=moomooo", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Cache-Control": "no-cache", 
    "Content-Length": "11", 
    "Content-Type": "text/moo", 
    "Host": "httpbin.org", 
    "User-Agent": "A cow"
  }, 
  "json": null, 
  "origin": "106.161.101.127", 
  "url": "http://httpbin.org/post"
}
```

<!-- Or perform the same request with a multi pool: -->

あるいは，同じリクエストをプールして実行することもできます．


```r
curl_fetch_multi("http://httpbin.org/post", handle = h, done = function(res){
  cat("Request complete! Response content:\n")
  cat(rawToChar(res$content))
})

# リクエストの実行
out <- multi_run()
```

```
Request complete! Response content:
{
  "args": {}, 
  "data": "moo=moomooo", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Cache-Control": "no-cache", 
    "Content-Length": "11", 
    "Content-Type": "text/moo", 
    "Host": "httpbin.org", 
    "User-Agent": "A cow"
  }, 
  "json": null, 
  "origin": "106.161.101.127", 
  "url": "http://httpbin.org/post"
}
```

<!-- ### Reading cookies -->

### クッキーの読込

<!-- Curl handles automatically keep track of cookies set by the server. At any given point we can use `handle_cookies` to see a list of current cookies in the handle. -->

curl ハンドルはサーバが設定したクッキーを自動的に記録します．`handle_cookies()`を使って，現在ハンドルに記録されているクッキーのリストをいつでも見ることができます．


```r
# 新しいハンドル
h <- new_handle()

# サーバにクッキーを設定してくれるよう依頼
req <- curl_fetch_memory("http://httpbin.org/cookies/set?foo=123&bar=ftw", handle = h)
req <- curl_fetch_memory("http://httpbin.org/cookies/set?baz=moooo", handle = h)
handle_cookies(h)
```

```
       domain  flag path secure expiration name value
1 httpbin.org FALSE    /  FALSE       <NA>  foo   123
2 httpbin.org FALSE    /  FALSE       <NA>  bar   ftw
3 httpbin.org FALSE    /  FALSE       <NA>  baz moooo
```

```r
# クッキーの設定を解除
req <- curl_fetch_memory("http://httpbin.org/cookies/delete?foo", handle = h)
handle_cookies(h)
```

```
       domain  flag path secure          expiration name value
1 httpbin.org FALSE    /  FALSE 2016-10-15 22:21:50  foo  <NA>
2 httpbin.org FALSE    /  FALSE                <NA>  bar   ftw
3 httpbin.org FALSE    /  FALSE                <NA>  baz moooo
```

<!-- The `handle_cookies` function returns a data frame with 7 columns as specified in the [netscape cookie file format](http://www.cookiecentral.com/faq/#3.5). -->
`handle_cookies()` 関数は[netscapeのcookieファイル形式](http://www.cookiecentral.com/faq/#3.5)で指定されている7項目を列に持つデータフレームを返します．

<!-- ### Re-using handles -->

### ハンドルの再利用

<!-- As we have already seen, curl allows for reusing a single handle for multiple requests. However it is not always a good idea to do so. The performance overhead of creating and configuring a new handle object is usually negligible. The safest way to issue mutiple requests, either to a single server or multiple servers is by using a separate handle for each request.  -->

既にみたように， curl ではひとつのハンドルを複数のリクエストに対して使いまわすことが可能です．ですが，そうするのがいつでもよい考えというわけでははありません．新たなハンドルオブジェクトを作成して設定するためのパフォーマンス上のオーバーヘッドは，ふつうは無視できる程度です．複数のリクエストを単一あるいは複数のサーバに対して発行する最も安全な方法は，それぞれのリクエストで別々のハンドルを使うことです


```r
req1 <- curl_fetch_memory("https://httpbin.org/get", handle = new_handle())
req2 <- curl_fetch_memory("http://www.r-project.org", handle = new_handle())
```

<!-- There are two reasons why you might want to reuse a handle for multiple requests. The first one is that it will automatically keep track of cookies set by the server. This might be useful if your host requires use of a session cookies. -->

複数のリクエストに対してハンドルを再利用したくなる理由は2つあります．ひとつめの理由は，ハンドルがサーバによって設定されるクッキーを自動的に記録してくれることです．これはホストがセッションクッキーの使用を要求してくる場合に有用かもしません．

<!-- The other reason is to take advantage of http Keep-Alive. Curl automatically maintains a pool of open http connections within each handle. When using a single handle to issue many requests to the same server, curl uses existing connections when possible. This eliminites a little bit of connection overhead, although on a decent network this might not be very significant. -->

もうひとつの理由は， HTTP Keep-Alive の利用です． curl は，各ハンドル内の開いているHTTP接続のプールを自動的に維持してくれます．ひとつのハンドルを使って同一のサーバに多数のリクエストを発行する場合， curl は可能なら既存の接続を使います．これによって接続のオーバヘッドが少し削減されます．ただし，よいネットワークであればそれほど大きな効果はないでしょう．


```r
h <- new_handle()
system.time(curl_fetch_memory("https://api.github.com/users/ropensci", handle = h))
```

```
   user  system elapsed 
   0.03    0.00    1.19 
```

```r
system.time(curl_fetch_memory("https://api.github.com/users/rstudio", handle = h))
```

```
   user  system elapsed 
   0.00    0.00    0.33 
```

<!-- The argument against reusing handles is that curl does not cleanup the handle after each request. All of the options and internal fields will linger around for all future request until explicitly reset or overwritten. This can sometimes leads to unexpected behavior.  -->

ハンドルの再利用に反対する論拠は， curl が各リクエストの後でハンドルを片付けないということです．明示的にリセットや上書きを行わない限り，オプションや内部で持っている項目のすべてが将来のリクエストでも残ってしまいます．


```r
handle_reset(h)
```

<!-- The `handle_reset` function will reset all curl options and request headers to the default values. It will **not** erease cookies and it will still keep alive the connections. Therefore it is good practice to call `handle_reset` after performing a request if you want to reuse the handle for a subsequent request. Still it is always safer to create a new fresh handle when possible, rather than recycling old ones. -->

`handle_reset()` 関数は curl のすべてのオプションとリクエストヘッダをデフォルトの値にリセットします．クッキーは削除**されません**し，接続は keep-alive なままです．したがって，後続のリクエストでハンドルを再利用したい場合には，リクエストの実行後に `handle_reset()` を呼ぶのがよいやり方です．とはいえ可能であれば新しいハンドルを作成するほうが，古いものを使いまわすより常に安全です．

<!-- ### Posting forms -->

### フォームの送信

<!-- The `handle_setform` function is used to perform a `multipart/form-data` HTTP POST request (a.k.a. posting a form). Values can be either strings, raw vectors (for binary data) or files.  -->

`handle_setform()` 関数は `multipart/form-data` の HTTP POST リクエスト（つまりフォームの送信）を行うために使います．値には文字列，rawベクトル（バイナリデータの場合），ファイルのいずれかが指定できます．


```r
# マルチパートの送信
h <- new_handle()
handle_setform(h,
  foo = "blabla",
  bar = charToRaw("boeboe"),
  description = form_file(system.file("DESCRIPTION")),
  logo = form_file(file.path(Sys.getenv("R_DOC_DIR"), "html/logo.jpg"), "image/jpeg")
)
req <- curl_fetch_memory("http://httpbin.org/post", handle = h)
```

<!-- The `form_file` function is used to upload files with the form post. It has two arguments: a file path, and optionally a content-type value. If no content-type is set, curl will guess the content type of the file based on the file extention. -->

`form_file()` 関数はフォーム送信でファイルをアップロードするために使います．この関数には2つの引数があります．ファイルパスと，オプションとして指定できる content-type の値です． content-type が何も指定されなかった場合， curl は content-type をファイルの拡張子から推測します．

<!-- ### Using pipes -->

### パイプの使用

<!-- All of the `handle_xxx` functions return the handle object so that function calls can be chained using the popular pipe operators: -->

`handle_xxx()` 系関数はどれもハンドルオブジェクトを返すので，人気のパイプ演算子を使って関数呼び出しを連鎖させることができます．


```r
library(magrittr)

new_handle() %>% 
  handle_setopt(copypostfields = "moo=moomooo") %>% 
  handle_setheaders("Content-Type" = "text/moo", "Cache-Control" = "no-cache", "User-Agent" = "A cow") %>%
  curl_fetch_memory(url = "http://httpbin.org/post") %$% content %>% rawToChar %>% cat
```

```
{
  "args": {}, 
  "data": "moo=moomooo", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Cache-Control": "no-cache", 
    "Content-Length": "11", 
    "Content-Type": "text/moo", 
    "Host": "httpbin.org", 
    "User-Agent": "A cow"
  }, 
  "json": null, 
  "origin": "106.161.101.127", 
  "url": "http://httpbin.org/post"
}
```


----

訳注：翻訳の際，コードは以下の環境で実行した．

```r
devtools::session_info()
```

```
Session info --------------------------------------------------------------
 setting  value                       
 version  R version 3.3.1 (2016-06-21)
 system   x86_64, mingw32             
 ui       RTerm                       
 language (EN)                        
 collate  Japanese_Japan.932          
 tz       Asia/Tokyo                  
 date     2016-10-15                  
Packages ------------------------------------------------------------------
 package       * version  date       source                            
 assertthat      0.1      2013-12-06 CRAN (R 3.3.1)                    
 curl          * 2.1      2016-09-22 CRAN (R 3.3.1)                    
 devtools        1.12.0   2016-06-24 CRAN (R 3.3.1)                    
 digest          0.6.10   2016-08-02 CRAN (R 3.3.1)                    
 evaluate        0.9      2016-04-29 CRAN (R 3.3.1)                    
 formatR         1.4      2016-05-09 CRAN (R 3.3.1)                    
 htmltools       0.3.5    2016-03-21 CRAN (R 3.3.1)                    
 knitr           1.14     2016-08-13 CRAN (R 3.3.1)                    
 magrittr      * 1.5      2014-11-22 CRAN (R 3.3.1)                    
 memoise         1.0.0    2016-01-29 CRAN (R 3.3.1)                    
 Rcpp            0.12.6   2016-07-19 CRAN (R 3.3.1)                    
 RevoUtils       10.0.1   2016-08-24 local                             
 RevoUtilsMath * 8.0.3    2016-04-13 local                             
 rmarkdown       1.0.9016 2016-10-13 Github (rstudio/rmarkdown@2158b9d)
 stringi         1.1.1    2016-05-27 CRAN (R 3.3.0)                    
 stringr         1.1.0    2016-08-19 CRAN (R 3.3.1)                    
 tibble          1.2      2016-08-26 CRAN (R 3.3.1)                    
 withr           1.0.2    2016-06-20 CRAN (R 3.3.1)                    
 yaml            2.1.13   2014-06-12 CRAN (R 3.3.1)                    
```