たとえばGET()
はこんな感じ。url
はいいとして、config
と...
が謎。
packageVersion("httr") #> [1] ‘1.2.1’ httr::GET #> function (url = NULL, config = list(), ..., handle = NULL) #> { #> hu <- handle_url(handle, url, ...) #> req <- request_build("GET", hu$url, as.request(config), ...) #> request_perform(req, hu$handle$handle) #> } #> <environment: namespace:httr>
config
のドキュメントはこうなっている。
Additional configuration settings such as http authentication (authenticate), additional headers (add_headers), cookies (set_cookies) etc. See config for full details and list of helpers.
...
のドキュメントはこう。
Further named parameters, such as
query
,path
, etc, passed on tomodify_url
. Unnamed parameters will be combined withconfig
.
handle_url
...
のうち名前付きの引数だけが使われる(named()
が名前付き引数だけ取り出す関数らしい)
handle_url <- function(handle = NULL, url = NULL, ...) { if (is.null(url) && is.null(handle)) { stop("Must specify at least one of url or handle") } if (is.null(handle)) handle <- handle_find(url) if (is.null(url)) url <- handle$url # If named components in ..., modify the url new <- named(list(...)) if (length(new) > 0 || is.url(url)) { old <- parse_url(url) url <- build_url(utils::modifyList(old, new)) } list(handle = handle, url = url) }
(https://github.com/hadley/httr/blob/7261a525ede1beb9880d1ce2e2009d27c8e8bef7/R/handle-url.r#L1-L17)
request_build
こっちは逆に、...
のうち名前がついていないものだけが使われる。(has_name()
がTRUE
になるものはextra
から除外されるらしい)
request_build <- function(method, url, ...) { extra <- list(...) extra[has_name(extra)] <- NULL req <- Reduce(request_combine, extra, init = request()) req$method <- method req$url <- url req }
(https://github.com/hadley/httr/blob/1647b0a02fe6504384f5a5dbd5643083e267f2d8/R/request.R#L55-L65)
as.request
config
引数はas.request(config)
として使われている。as.request()
の関数定義は以下のようになっている。
as.request <- function(x) UseMethod("as.request") as.request.list <- function(x) structure(x, class = "request") as.request.request <- function(x) x as.request.NULL <- function(x) request() as.request.Token <- function(x) request(auth_token = x)
(https://github.com/hadley/httr/blob/1647b0a02fe6504384f5a5dbd5643083e267f2d8/R/request.R#L49-L53)
ということで、config
として指定できるのは
list
request
Token
のどれか。ちなみにToken
の場合は最終的にこういう感じでsign()
メソッドが呼び出される。
signed_req <- token$sign(req$method, req$url)
(https://github.com/hadley/httr/blob/1647b0a02fe6504384f5a5dbd5643083e267f2d8/R/request.R#L115)
Token2.0だとas_header
というパラメータに応じて、Authorization
というヘッダになるかaccess_token
というクエリパラメータになる。LinkedInの例のように自前でsign()
を定義することも可能。
ヘッダとかトークンとかは名前なし引数かconfigとして渡さないといけない
例1: Content-Typeヘッダ
うっかりheaders=
とかつけてしまうと反映されない。名前をつけるとhandle_url(...)
の中でbuild_url(url)
に渡されるけど、そこではurl
からurl$schema
とか必要なものだけを取り出していて、余分なものがあっても特にエラーになったりしない。単純に無視される。
# これはOK GET("http://httpbin.org/headers", content_type_json()) # これもOK GET("http://httpbin.org/headers", config = content_type_json()) # これはNG GET("http://httpbin.org/headers", headers = content_type_json())
例2: OAuthトークン
トークンはちょっと扱いが別なのでconfig()
のtoken
引数として指定することもできる。
# これはOK GET("http://example.com", mytoken) # これもOK GET("http://example.com", config = mytoken) # これもOK GET("http://example.com", config = config(token = mytoken)) # でもこれはNG GET("http://example.com", token = mytoken)
たぶん、config
引数にはひとつだけしか指定できないので、名前なし引数で指定する方が並べて書くことができて便利な気がする。
request
同士はc()
で合成することができるので、Token
はrequest
に手動で変換しておけばあらかじめconfigオブジェクトをつくっておくことはできる。
cfg <- c(content_type_json(), httr:::as.request.Token(mytoken)) cfg #> <request> #> Headers: #> * Content-Type: application/json #> Auth token: Token2.0 GET(url, config = cfg)
という感じ。
でも、httrのデモではconfig
引数にconfig(token = token)
を指定しているからこれがいいのかな…