diff --git a/dev/articles/httr2.html b/dev/articles/httr2.html index 0f58f323..07f0ad85 100644 --- a/dev/articles/httr2.html +++ b/dev/articles/httr2.html @@ -105,7 +105,7 @@

Create a requestreq <- request(example_url()) req #> <httr2_request> -#> GET http://127.0.0.1:39341/ +#> GET http://127.0.0.1:46815/ #> Body: empty

Here, instead of an external website, we use a test server that’s built-in to httr2 itself. That ensures that this vignette will work @@ -115,7 +115,7 @@

Create a request
 req |> req_dry_run()
 #> GET / HTTP/1.1
-#> Host: 127.0.0.1:39341
+#> Host: 127.0.0.1:46815
 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0
 #> Accept: */*
 #> Accept-Encoding: deflate, gzip, br, zstd
@@ -130,7 +130,7 @@

Create a request

The path, which is the URL stripped of details that the server already knows, i.e. the protocol (http or https), the host (localhost), and the port -(39341).

+(46815).

  • The version of the HTTP protocol. This is unimportant for our purposes because it’s handled at a lower level.

  • @@ -147,7 +147,7 @@

    Create a request ) |> req_dry_run() #> GET / HTTP/1.1 -#> Host: 127.0.0.1:39341 +#> Host: 127.0.0.1:46815 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept-Encoding: deflate, gzip, br, zstd #> Name: Hadley @@ -166,7 +166,7 @@

    Create a request req_body_json(list(x = 1, y = "a")) |> req_dry_run() #> POST / HTTP/1.1 -#> Host: 127.0.0.1:39341 +#> Host: 127.0.0.1:46815 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd @@ -193,7 +193,7 @@

    Create a request req_body_form(x = "1", y = "a") |> req_dry_run() #> POST / HTTP/1.1 -#> Host: 127.0.0.1:39341 +#> Host: 127.0.0.1:46815 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd @@ -209,22 +209,22 @@

    Create a request req_body_multipart(x = "1", y = "a") |> req_dry_run() #> POST / HTTP/1.1 -#> Host: 127.0.0.1:39341 +#> Host: 127.0.0.1:46815 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Content-Length: 228 -#> Content-Type: multipart/form-data; boundary=------------------------7c5a2eec62d6565e +#> Content-Type: multipart/form-data; boundary=------------------------daec775293434987 #> -#> --------------------------7c5a2eec62d6565e +#> --------------------------daec775293434987 #> Content-Disposition: form-data; name="x" #> #> 1 -#> --------------------------7c5a2eec62d6565e +#> --------------------------daec775293434987 #> Content-Disposition: form-data; name="y" #> #> a -#> --------------------------7c5a2eec62d6565e-- +#> --------------------------daec775293434987--

    If you need to send data encoded in a different form, you can use req_body_raw() to add the data to the body and set the Content-Type header.

    @@ -239,7 +239,7 @@

    Perform a request and fetch th resp <- req |> req_perform() resp #> <httr2_response> -#> GET http://127.0.0.1:39341/json +#> GET http://127.0.0.1:46815/json #> Status: 200 OK #> Content-Type: application/json #> Body: In memory (407 bytes) @@ -249,7 +249,7 @@

    Perform a request and fetch th resp |> resp_raw() #> HTTP/1.1 200 OK #> Connection: close -#> Date: Wed, 23 Oct 2024 18:13:51 GMT +#> Date: Wed, 23 Oct 2024 22:11:02 GMT #> Content-Type: application/json #> Content-Length: 407 #> ETag: "de760e6d" @@ -302,7 +302,7 @@

    Perform a request and fetch th resp |> resp_headers() #> <httr2_headers> #> Connection: close -#> Date: Wed, 23 Oct 2024 18:13:51 GMT +#> Date: Wed, 23 Oct 2024 22:11:02 GMT #> Content-Type: application/json #> Content-Length: 407 #> ETag: "de760e6d" diff --git a/dev/articles/oauth.html b/dev/articles/oauth.html index 3e539fe4..617cc42a 100644 --- a/dev/articles/oauth.html +++ b/dev/articles/oauth.html @@ -234,7 +234,7 @@

    Client secret
     obfuscate("secret")
    -#> obfuscated("wOLRVKseS250r5jH-7XtK9xsqkyOEQ")
    +#> obfuscated("f5LXTegwNUQuMsVtP4Y6gSR-tBNENQ")

    Here’s what a complete client specification for GitHub looks like, using a real app that I created specifically for this vignette:

    Errors @@ -162,7 +162,7 @@

    Errors #> Connection: keep-alive #> X-Powered-By: PHP/8.3.8 #> Cache-Control: no-cache, private -#> Date: Wed, 23 Oct 2024 18:13:59 GMT +#> Date: Wed, 23 Oct 2024 22:11:09 GMT #> X-RateLimit-Limit: 60 #> X-RateLimit-Remaining: 56 #> Access-Control-Allow-Origin: *

    @@ -234,8 +234,8 @@

    Core request function#> $ total : int 1 #> $ data :List of 1 #> ..$ :List of 3 -#> .. ..$ title : chr "Et voluptatem hic iure nam." -#> .. ..$ description: chr "Eius praesentium excepturi sint aut quis ipsa. Asperiores dolorem omnis sed officiis. Repellat et omnis amet re"| __truncated__ +#> .. ..$ title : chr "Neque est sit itaque." +#> .. ..$ description: chr "Provident deleniti dolor officiis. Amet saepe cumque eos id expedita sint. Eius odio maiores qui debitis ut cul"| __truncated__ #> .. ..$ url : chr "https://picsum.photos/300/480"

    I’ve made a few important choices here:

    resp_stream_sse() and resp_stream_aws() will return NULL to signal that +the end of the stream has been reached or, if in nonblocking mode, that +no event is currently available.

    + diff --git a/dev/reference/resp_url.html b/dev/reference/resp_url.html index 91b7d16e..1d39d268 100644 --- a/dev/reference/resp_url.html +++ b/dev/reference/resp_url.html @@ -101,7 +101,7 @@

    Examples req_perform() resp |> resp_url() -#> [1] "http://127.0.0.1:34151/get?hello=world" +#> [1] "http://127.0.0.1:36861/get?hello=world" resp |> resp_url_path() #> [1] "/get" resp |> resp_url_queries() diff --git a/dev/reference/resps_successes.html b/dev/reference/resps_successes.html index 4b17c31e..bfddf563 100644 --- a/dev/reference/resps_successes.html +++ b/dev/reference/resps_successes.html @@ -114,14 +114,14 @@

    Examplesresps |> resps_successes() #> [[1]] #> <httr2_response> -#> GET http://127.0.0.1:34151/ip +#> GET http://127.0.0.1:36861/ip #> Status: 200 OK #> Content-Type: application/json #> Body: In memory (27 bytes) #> #> [[2]] #> <httr2_response> -#> GET http://127.0.0.1:34151/user-agent +#> GET http://127.0.0.1:36861/user-agent #> Status: 200 OK #> Content-Type: application/json #> Body: In memory (66 bytes) @@ -140,7 +140,7 @@

    Examplesresps |> resps_failures() |> resps_requests() #> [[1]] #> <httr2_request> -#> GET http://127.0.0.1:34151/status/404 +#> GET http://127.0.0.1:36861/status/404 #> Body: empty #> #> [[2]] diff --git a/dev/reference/secrets.html b/dev/reference/secrets.html index d8265ad7..38be6622 100644 --- a/dev/reference/secrets.html +++ b/dev/reference/secrets.html @@ -228,7 +228,7 @@

    Examples x <- secret_encrypt("This is a secret", "MY_KEY") x -#> [1] "skw86WojAwJCvQY4wNnXJYCbj-fGpVsDhJg3ia2tbJ0" +#> [1] "eEsy_KyOO1gCv-928d7NXuA48sPE41dbroIO_31fFI8" secret_decrypt(x, "MY_KEY") #> [1] "This is a secret" diff --git a/dev/reference/with_verbosity.html b/dev/reference/with_verbosity.html index 71366680..debf45be 100644 --- a/dev/reference/with_verbosity.html +++ b/dev/reference/with_verbosity.html @@ -97,24 +97,24 @@

    Examples#> <- HTTP/2 200 #> <- server: GitHub.com #> <- content-type: text/html; charset=utf-8 -#> <- last-modified: Wed, 23 Oct 2024 14:55:26 GMT +#> <- last-modified: Wed, 23 Oct 2024 18:14:33 GMT #> <- access-control-allow-origin: * -#> <- etag: W/"67190e5e-4983" -#> <- expires: Wed, 23 Oct 2024 18:22:09 GMT +#> <- etag: W/"67193d09-4983" +#> <- expires: Wed, 23 Oct 2024 22:20:36 GMT #> <- cache-control: max-age=600 #> <- content-encoding: gzip #> <- x-proxy-cache: MISS -#> <- x-github-request-id: D2CE:1451B9:19BD01:1A2D21:67193C77 +#> <- x-github-request-id: 97CB:344448:46EAD9:50CD81:67197452 #> <- accept-ranges: bytes -#> <- date: Wed, 23 Oct 2024 18:13:48 GMT +#> <- date: Wed, 23 Oct 2024 22:10:59 GMT #> <- via: 1.1 varnish -#> <- age: 23 -#> <- x-served-by: cache-pao-kpao1770054-PAO +#> <- age: 24 +#> <- x-served-by: cache-chi-kigq8000144-CHI #> <- x-cache: HIT #> <- x-cache-hits: 5 -#> <- x-timer: S1729707229.662431,VS0,VE0 +#> <- x-timer: S1729721460.616774,VS0,VE0 #> <- vary: Accept-Encoding -#> <- x-fastly-request-id: 910c2a82cac2fc81ccae9741896220af58026967 +#> <- x-fastly-request-id: cf58bf43c862894d96a084fe00b673e6c23154d8 #> <- content-length: 4636 #> <- #> <httr2_response> diff --git a/dev/search.json b/dev/search.json index a9840c01..7a142196 100644 --- a/dev/search.json +++ b/dev/search.json @@ -1 +1 @@ -[{"path":"https://httr2.r-lib.org/dev/LICENSE.html","id":null,"dir":"","previous_headings":"","what":"MIT License","title":"MIT License","text":"Copyright (c) 2021 httr2 authors Permission hereby granted, free charge, person obtaining copy software associated documentation files (“Software”), deal Software without restriction, including without limitation rights use, copy, modify, merge, publish, distribute, sublicense, /sell copies Software, permit persons Software furnished , subject following conditions: copyright notice permission notice shall included copies substantial portions Software. SOFTWARE PROVIDED “”, WITHOUT WARRANTY KIND, EXPRESS IMPLIED, INCLUDING LIMITED WARRANTIES MERCHANTABILITY, FITNESS PARTICULAR PURPOSE NONINFRINGEMENT. EVENT SHALL AUTHORS COPYRIGHT HOLDERS LIABLE CLAIM, DAMAGES LIABILITY, WHETHER ACTION CONTRACT, TORT OTHERWISE, ARISING , CONNECTION SOFTWARE USE DEALINGS SOFTWARE.","code":""},{"path":"https://httr2.r-lib.org/dev/articles/httr2.html","id":"create-a-request","dir":"Articles","previous_headings":"","what":"Create a request","title":"httr2","text":"httr2, start creating request. ’re familiar httr, big change: httr submit request, immediately receiving response. explicit request object makes easier build complex request piece piece works well pipe. Every request starts URL: , instead external website, use test server ’s built-httr2 . ensures vignette work regardless run . can see exactly request send server dry run: first line request contains three important pieces information: HTTP method, verb tells server want . ’s GET, common verb, indicating want get resource. verbs include POST, create new resource, PUT, replace existing resource, DELETE, delete resource. path, URL stripped details server already knows, .e. protocol (http https), host (localhost), port (39341). version HTTP protocol. unimportant purposes ’s handled lower level. following lines specify HTTP headers, series name-value pairs separated :. headers request automatically added httr2, can override add req_headers(): Header names case-insensitive, servers ignore headers don’t understand. headers finish blank line followed body. requests (like GET requests) don’t body, let’s add one see happens. req_body_*() functions provide variety ways add data body. ’ll use req_body_json() add data encoded JSON: ’s changed? method changed GET POST. POST standard method sending data website, automatically used whenever add body. Use req_method() different method. two new headers: Content-Type Content-Length. tell server interpret body — ’s encoded JSON 15 bytes long. body, consisting JSON. Different servers want data encoded differently httr2 provides selection common formats. example, req_body_form() uses encoding used submit form web browser: req_body_multipart() uses multipart encoding particularly important need send larger amounts data complete files: need send data encoded different form, can use req_body_raw() add data body set Content-Type header.","code":"req <- request(example_url()) req #> #> GET http://127.0.0.1:39341/ #> Body: empty req |> req_dry_run() #> GET / HTTP/1.1 #> Host: 127.0.0.1:39341 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd req |> req_headers( Name = \"Hadley\", `Shoe-Size` = \"11\", Accept = \"application/json\" ) |> req_dry_run() #> GET / HTTP/1.1 #> Host: 127.0.0.1:39341 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept-Encoding: deflate, gzip, br, zstd #> Name: Hadley #> Shoe-Size: 11 #> Accept: application/json req |> req_body_json(list(x = 1, y = \"a\")) |> req_dry_run() #> POST / HTTP/1.1 #> Host: 127.0.0.1:39341 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Content-Type: application/json #> Content-Length: 15 #> #> {\"x\":1,\"y\":\"a\"} req |> req_body_form(x = \"1\", y = \"a\") |> req_dry_run() #> POST / HTTP/1.1 #> Host: 127.0.0.1:39341 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Content-Type: application/x-www-form-urlencoded #> Content-Length: 7 #> #> x=1&y=a req |> req_body_multipart(x = \"1\", y = \"a\") |> req_dry_run() #> POST / HTTP/1.1 #> Host: 127.0.0.1:39341 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Content-Length: 228 #> Content-Type: multipart/form-data; boundary=------------------------7c5a2eec62d6565e #> #> --------------------------7c5a2eec62d6565e #> Content-Disposition: form-data; name=\"x\" #> #> 1 #> --------------------------7c5a2eec62d6565e #> Content-Disposition: form-data; name=\"y\" #> #> a #> --------------------------7c5a2eec62d6565e--"},{"path":"https://httr2.r-lib.org/dev/articles/httr2.html","id":"perform-a-request-and-fetch-the-response","dir":"Articles","previous_headings":"","what":"Perform a request and fetch the response","title":"httr2","text":"actually perform request fetch response back server, call req_perform(): can see simulation httr2 actually received resp_raw(): HTTP response similar structure HTTP request. first line gives version HTTP used, status code ’s optionally followed short description. headers, followed blank line, followed body. majority responses body, unlike requests. can extract data response using resp_() functions: resp_status() returns status code resp_status_desc() returns description: can extract headers resp_headers() specific header resp_header(): Headers case insensitive: can extract body various forms using resp_body_*() family functions. Since response returns JSON can use resp_body_json(): Responses status codes 4xx 5xx HTTP errors. httr2 automatically turns R errors: another important difference httr, required explicitly call httr::stop_for_status() turn HTTP errors R errors. can revert httr behaviour req_error(req, is_error = ~ FALSE).","code":"req <- request(example_url()) |> req_url_path(\"/json\") resp <- req |> req_perform() resp #> #> GET http://127.0.0.1:39341/json #> Status: 200 OK #> Content-Type: application/json #> Body: In memory (407 bytes) resp |> resp_raw() #> HTTP/1.1 200 OK #> Connection: close #> Date: Wed, 23 Oct 2024 18:13:51 GMT #> Content-Type: application/json #> Content-Length: 407 #> ETag: \"de760e6d\" #> #> { #> \"firstName\": \"John\", #> \"lastName\": \"Smith\", #> \"isAlive\": true, #> \"age\": 27, #> \"address\": { #> \"streetAddress\": \"21 2nd Street\", #> \"city\": \"New York\", #> \"state\": \"NY\", #> \"postalCode\": \"10021-3100\" #> }, #> \"phoneNumbers\": [ #> { #> \"type\": \"home\", #> \"number\": \"212 555-1234\" #> }, #> { #> \"type\": \"office\", #> \"number\": \"646 555-4567\" #> } #> ], #> \"children\": [], #> \"spouse\": null #> } resp |> resp_status() #> [1] 200 resp |> resp_status_desc() #> [1] \"OK\" resp |> resp_headers() #> #> Connection: close #> Date: Wed, 23 Oct 2024 18:13:51 GMT #> Content-Type: application/json #> Content-Length: 407 #> ETag: \"de760e6d\" resp |> resp_header(\"Content-Length\") #> [1] \"407\" resp |> resp_header(\"ConTEnT-LeNgTH\") #> [1] \"407\" resp |> resp_body_json() |> str() #> List of 8 #> $ firstName : chr \"John\" #> $ lastName : chr \"Smith\" #> $ isAlive : logi TRUE #> $ age : int 27 #> $ address :List of 4 #> ..$ streetAddress: chr \"21 2nd Street\" #> ..$ city : chr \"New York\" #> ..$ state : chr \"NY\" #> ..$ postalCode : chr \"10021-3100\" #> $ phoneNumbers:List of 2 #> ..$ :List of 2 #> .. ..$ type : chr \"home\" #> .. ..$ number: chr \"212 555-1234\" #> ..$ :List of 2 #> .. ..$ type : chr \"office\" #> .. ..$ number: chr \"646 555-4567\" #> $ children : list() #> $ spouse : NULL request(example_url()) |> req_url_path(\"/status/404\") |> req_perform() #> Error in `req_perform()`: #> ! HTTP 404 Not Found. request(example_url()) |> req_url_path(\"/status/500\") |> req_perform() #> Error in `req_perform()`: #> ! HTTP 500 Internal Server Error."},{"path":"https://httr2.r-lib.org/dev/articles/httr2.html","id":"control-the-request-process","dir":"Articles","previous_headings":"","what":"Control the request process","title":"httr2","text":"number req_ functions don’t directly affect HTTP request instead control overall process submitting request handling response. include: req_cache() sets cache repeated requests return results, can avoid trip server. req_throttle() automatically add small delay request can avoid hammering server many requests. req_retry() sets retry strategy request either fails get transient HTTP error, ’ll automatically retry short delay. details see documentation, well examples usage real APIs vignette(\"wrapping-apis\").","code":""},{"path":"https://httr2.r-lib.org/dev/articles/oauth.html","id":"oauth-basics","dir":"Articles","previous_headings":"","what":"OAuth basics","title":"OAuth","text":"OAuth broad framework many different variants, called flows, makes hard provide sweeping generalisations, basic idea OAuth create hierarchy increasingly specific shorter-lived credentials, impact credential lost small possible. longest lived powerful credential typically user name password. people don’t change passwords regularly, often (advice) reuse password multiple websites. user name password, total control account; can even use change password actual user can’t log . means programmer never want touch user name-password pairs ’re lost stolen, give wide access. Avoiding problem lead creation OAuth. basic idea instead package asking user give user name password, instead ask log give package permission use API behalf. API gives permission form access token essentially random string numbers letters, e.g. UfNlXaEog03hdRPTUPpEInEiIW01jI1WcjOB. access token short lived, lasting maybe days, bound specified scope access. access token big advantages user name password: ’s short-lived ’s lost stolen, ’s limited amount time can abused. limited scope, even stolen, can’t used something particularly nefarious like changing password contact details. ’s bound specific application, can invalidated (cancelled) without affecting uses. access token can use authenticate API passing bearer token Authorization header, can req_auth_bearer_token(). However, cases want let httr2 manage calling one req_oauth_ functions ’ll talk shortly. One reasons want httr2 manage tokens access tokens short lived, ’re often accompanied refresh token. refresh token lasts longer amount time one job: allows get new access token previous one expires. need look refresh token little carefully access token. particular, never include refresh token HTTP request ’s job access token. Overall leads hierarchy credentials weakest strongest: access token usually lasts couple hours needs submitted every request. refresh token lasts days weeks ’s designed stored locally can regenerate access tokens. (’ll talk Caching, .) user name + password gives access everything code never touch ! Now ’ve got basic idea OAuth, lets talk details.","code":""},{"path":"https://httr2.r-lib.org/dev/articles/oauth.html","id":"clients","dir":"Articles","previous_headings":"","what":"Clients","title":"OAuth","text":"first step working OAuth API create application client. ’s called application client wider world OAuth usually used web, phone, tv app, “app” going R package. reason, httr2 calls application client client, many APIs call OAuth application. create client, ’ll need first register developer account API’s website. cases easy, totally automated, takes couple minutes. give access sort developer portal can use register new OAuth app (aka client). process varies API API (’s normal spend time hunting docs settings), end ’ll get client id (another random string numbers letters). Sometimes client id need, can create httr2 client oauth_client(), e.g.: call oauth_client() also includes name token_url. name human-facing, typically package (thing prompted create client). bunch apps ’ve used testing, ’ve used name hadley-oauth-test-2 remind app client corresponds . token_url points URL ’s used obtain access token. ’ll need find documentation API ’re wrapping; typically found section describes OAuth process endpoint returns access token. Don’t surprised endpoint feels different rest API; auth often implemented third-party package slightly different conventions rest API.","code":"client <- oauth_client( id = \"28acfec0674bb3da9f38\", token_url = \"https://github.com/login/oauth/access_token\", name = \"hadley-oauth-test-2\" )"},{"path":"https://httr2.r-lib.org/dev/articles/oauth.html","id":"client-secret","dir":"Articles","previous_headings":"Clients","what":"Client secret","title":"OAuth","text":"cases, however, API also require client secret. called secret, ’s typically important keep secret two reasons: ’s typically easy create new app developer website stealing wouldn’t save much time. ’s unusual OAuth client able anything right, stealing secret doesn’t much benefit. means unless paid app given private information creating , ’s ok embed client package. said, httr2 provides tooling obfuscate client secret client secret isn’t directly embedded source code, hence vulnerable scraping. obfuscate string, call obfuscate(), copy paste result package. example, client secret “secret”, ’d call obfuscate() ’d copy paste obfuscated(\"B4Evdd5x4wl0XTWvtTpuGaw7nM7GEg\") client specification. ’s complete client specification GitHub looks like, using real app created specifically vignette: can certainly uncover client secret experienced R programmer willing spend bit time experimenting, ’m pretty sure ’d easy just create app GitHub.","code":"obfuscate(\"secret\") #> obfuscated(\"wOLRVKseS250r5jH-7XtK9xsqkyOEQ\") client <- oauth_client( id = \"28acfec0674bb3da9f38\", secret = obfuscated(\"J9iiGmyelHltyxqrHXW41ZZPZamyUNxSX1_uKnvPeinhhxET_7FfUs2X0LLKotXY2bpgOMoHRCo\"), token_url = \"https://github.com/login/oauth/access_token\", name = \"hadley-oauth-test\" )"},{"path":"https://httr2.r-lib.org/dev/articles/oauth.html","id":"packaging","dir":"Articles","previous_headings":"Clients","what":"Packaging","title":"OAuth","text":"recommend wrapping client creation function package, e.g.: ’ll need order run tests package, ’ll probably also want use default client users. cases, necessary user create app matching client (e.g. rate limits applied app, user), much less user friendly avoid possible. said, always provide way user supply client bundle default. can see example googledrive package.","code":"github_client <- function() { oauth_client( id = \"28acfec0674bb3da9f38\", secret = obfuscated(\"J9iiGmyelHltyxqrHXW41ZZPZamyUNxSX1_uKnvPeinhhxET_7FfUs2X0LLKotXY2bpgOMoHRCo\"), token_url = \"https://github.com/login/oauth/access_token\", name = \"hadley-oauth-test\" ) }"},{"path":"https://httr2.r-lib.org/dev/articles/oauth.html","id":"authorization-code-flow","dir":"Articles","previous_headings":"","what":"Authorization code flow","title":"OAuth","text":"client need use flow order get token. ’ll need read docs API figure flows supports, common authorization code2 flow, works something like : httr2 opens browser using authorization URL provided API. URL includes parameters identify app scope access ’re looking (e.g. tweet.read, userinfo.write). user logs using user name password (hopefully using password manager) approves request. API sends authorization code back httr2 using callback URL supplied initial request. httr2 sends authorization code token URL get access token. httr2 flow implemented pair functions: oauth_flow_auth_code() req_oauth_auth_code(). Start oauth_flow_auth_code() check parameters correctly specified, use req_oauth_auth_code() authenticate requests. two steps described following sections.","code":""},{"path":"https://httr2.r-lib.org/dev/articles/oauth.html","id":"creating-a-token","dir":"Articles","previous_headings":"Authorization code flow","what":"Creating a token","title":"OAuth","text":"oauth_flow_auth_code() best way verify ’ve correctly specified parameters client auth_url, without depending correctly understanding part API. example, get token access GitHub API (using client defined ) code: flow can’t used inside vignette ’s designed specifically interactive use, run print token, ’ll see something like : ’s much see httr2 automatically redacts access token (used perform actions behalf user). call oauth_flow_auth_code() succeeds ’ve got everything set correctly can proceed next step. Otherwise, ’ll get HTTP error. ’re lucky, error informative help figure want went wrong. However, cases, ’ll need carefully double check ’ve correctly copied pasted client id secret, check ’ve supplied correct authorization token urls (auth_url token_url). docs multiple candidates ’re unclear , ’ll need systematic experimentation.","code":"token <- oauth_flow_auth_code( client = client, auth_url = \"https://github.com/login/oauth/authorize\" ) token #> #> token_type: bearer #> access_token: #> scope: ''"},{"path":"https://httr2.r-lib.org/dev/articles/oauth.html","id":"authenticating-a-request","dir":"Articles","previous_headings":"Authorization code flow","what":"Authenticating a request","title":"OAuth","text":"Initial configuration time ’ll see httr2_token object ’ll generally want rely httr2 manage tokens . ’ll req_oauth_auth_code(). check ’s working correctly, recommend finding simplest possible API endpoint test . good place start endpoint provides information “current” user, API provides one. example, GitHub API provides GET endpoint /user returns information current user. make request endpoint without authentication, ’ll get error: can authenticate request req_oauth_auth_code(), using arguments previous call oauth_flow_auth_code(): run code, ’ll see something like , obviously contain information , .","code":"req <- request(\"https://api.github.com/user\") req |> req_perform() #> Error in `req_perform()`: #> ! HTTP 401 Unauthorized. req |> req_oauth_auth_code( client = github_client(), auth_url = \"https://github.com/login/oauth/authorize\" ) |> req_perform() |> resp_body_json() |> str() #> List of 32 #> $ login : chr \"hadley\" #> $ id : int 4196 #> $ node_id : chr \"MDQ6VXNlcjQxOTY=\" #> $ avatar_url : chr \"https://avatars.githubusercontent.com/u/4196?v=4\" #> $ gravatar_id : chr \"\" #> $ url : chr \"https://api.github.com/users/hadley\" #> $ html_url : chr \"https://github.com/hadley\" #> ... #> $ type : chr \"User\" #> $ site_admin : logi FALSE #> $ name : chr \"Hadley Wickham\" #> $ company : chr \"@posit-pbc\" #> $ blog : chr \"http://hadley.nz\" #> $ location : chr \"Houston, TX\""},{"path":"https://httr2.r-lib.org/dev/articles/oauth.html","id":"caching","dir":"Articles","previous_headings":"Authorization code flow","what":"Caching","title":"OAuth","text":"two big reasons allow httr2 manage tokens . first httr2 automatically refresh token ’s expired. second cross-session caching, described . default, OAuth token cached memory. means need authenticate current session, ’ll need re-authenticate restart R. cases, may want save tokens (refresh access) can used across sessions. easy (just set cache_disk = TRUE) need think consequences saving refresh token disk. httr2 best can save credentials securely. stored local cache directory (oauth_cache_path()) accessible current user, encrypted hard package httr2 read. However, ’s way prevent R code using httr2 access , choose cache tokens, inform user give ability opt-. httr2 automatically deletes cached tokens older 30 days whenever ’s loaded. means ’ll need re-auth least month, prevents tokens hanging around disk long ’ve forgotten created . can see clients cached tokens looking cache directory used httr2: client gets subdirectory named using client name, turn caching , ’s particularly important give client good name user can easily tell package tokens belong .","code":"dir(oauth_cache_path(), recursive = TRUE)"},{"path":"https://httr2.r-lib.org/dev/articles/oauth.html","id":"other-flows","dir":"Articles","previous_headings":"","what":"Other flows","title":"OAuth","text":"wrapping API, ’ll need carefully read documentation figure flows provides. possible ’ll want use authorization code flow since generally provides best experience, ’s available ’ll need carefully consider others. Currently, httr2 supports following flows: req_oauth_device() uses “device” flow designed devices like TVs don’t easy way enter data. also works well console. req_oauth_client_credentials() req_oauth_bearer_jwt() often needed service accounts, accounts represent automated services, people, often used non-interactive environments. req_oauth_password() exchanges user name password access token. req_oauth_refresh() works directly refresh token already . ’s useful testing automation. httr2 doesn’t support implicit grant flow. historically important now mostly deprecated never particularly good fit R relies technique returning access token reliably works inside web browser. Regardless flow use, ’ll need follow process example : first figure get token using oauth_flow_ function, actually use oauth request, calling matching req_oauth_ function. One additional wrinkle many APIs don’t implement flow exactly way spec httr2’s built-flows might work . initial attempt doesn’t work, ’re going need sleuthing. going painful, unfortunately ’s way around . recommend wrapping httr2 code with_verbosity() can see exactly httr2 sending server. ’ll need carefully compare API documentation play “spot difference”. ’re welcome file issue ’ll best help .","code":""},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"faker-api","dir":"Articles","previous_headings":"","what":"Faker API","title":"Wrapping APIs","text":"’ll start simple API, faker API, provides collection techniques generating fake data. start writing sort functions might put package, ’ll perform request just see basics work:","code":"# We start by creating a request that uses the base API url req <- request(\"https://fakerapi.it/api/v1\") resp <- req |> # Then we add on the images path req_url_path_append(\"images\") |> # Add query parameters _width and _quantity req_url_query(`_width` = 380, `_quantity` = 1) |> req_perform() # The result comes back as JSON resp |> resp_body_json() |> str() #> List of 6 #> $ status: chr \"OK\" #> $ code : int 200 #> $ locale: chr \"en_US\" #> $ seed : NULL #> $ total : int 1 #> $ data :List of 1 #> ..$ :List of 3 #> .. ..$ title : chr \"Officia vel voluptatem ut.\" #> .. ..$ description: chr \"Quo libero ipsam laborum magni assumenda. Corrupti laborum et magnam ex eos enim voluptatem. Quisquam enim reru\"| __truncated__ #> .. ..$ url : chr \"https://picsum.photos/380/480\""},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"errors","dir":"Articles","previous_headings":"Faker API","what":"Errors","title":"Wrapping APIs","text":"’s always worth little early experimentation see get useful information errors. httr2 defaults get way , retrieve unsuccessful HTTP response, automatically get error prevents inspecting body: However, can access last response (successful ) last_response(): doesn’t look like ’s anything useful . Sometimes useful info returned headers, let’s check: doesn’t look like ’re getting useful information, can leave req_error() default . ’ll another go later API provide details.","code":"req |> req_url_path_append(\"invalid\") |> req_perform() #> Error in `req_perform()`: #> ! HTTP 400 Bad Request. resp <- last_response() resp |> resp_body_json() #> $message #> [1] \"Resource invalid not supported in version v1\" resp |> resp_headers() #> #> Server: nginx #> Content-Type: application/json #> Transfer-Encoding: chunked #> Connection: keep-alive #> X-Powered-By: PHP/8.3.8 #> Cache-Control: no-cache, private #> Date: Wed, 23 Oct 2024 18:13:59 GMT #> X-RateLimit-Limit: 60 #> X-RateLimit-Remaining: 56 #> Access-Control-Allow-Origin: *"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"user-agent","dir":"Articles","previous_headings":"Faker API","what":"User agent","title":"Wrapping APIs","text":"’re wrapping code package, ’s considered polite set user agent, , package accidentally something horribly wrong, developers website can figure reach . can req_user_agent() function:","code":"req |> req_user_agent(\"my_package_name (http://my.package.web.site)\") |> req_dry_run() #> GET /api/v1 HTTP/1.1 #> Host: fakerapi.it #> User-Agent: my_package_name (http://my.package.web.site) #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"core-request-function","dir":"Articles","previous_headings":"Faker API","what":"Core request function","title":"Wrapping APIs","text":"’ve made successful requests, ’s worth seeing can figure general pattern can wrap function become core package. faker, spent little time documentation noting commonalities: Every URL form https://fakerapi./api/v1/{resource}, data passed resource query parameters. parameters start _. Every resource three common query parameters: _locale, _quantity, _seed. endpoints return JSON data. led construct following function: ’ve made important choices : ’ve decided supply default values quantity locale parameters. makes function easier demo vignette. ’ve used default NULL seed argument. req_url_query() automatically drop NULL arguments means default value sent API, read function definition can still see seed accepted. automatically prefix query parameters _ argument names starting _ hard type R. function generates request, performs , extracts body response. works well simple cases, complex APIs might want return request object can modified performed. also used one cool trick: req_url_query() uses dynamic dots, can use !!! convert (e.g.) req_url_query(req, !!!list(`_quantity` = 1, `_locale` = \"en_US\")) req_url_query(req, `_quantity` = 1, `_locale` = \"en_US\").","code":"faker <- function(resource, ..., quantity = 1, locale = \"en_US\", seed = NULL) { params <- list( ..., quantity = quantity, locale = locale, seed = seed ) names(params) <- paste0(\"_\", names(params)) request(\"https://fakerapi.it/api/v1\") |> req_url_path_append(resource) |> req_url_query(!!!params) |> req_user_agent(\"my_package_name (http://my.package.web.site)\") |> req_perform() |> resp_body_json() } str(faker(\"images\", width = 300)) #> List of 6 #> $ status: chr \"OK\" #> $ code : int 200 #> $ locale: chr \"en_US\" #> $ seed : NULL #> $ total : int 1 #> $ data :List of 1 #> ..$ :List of 3 #> .. ..$ title : chr \"Et voluptatem hic iure nam.\" #> .. ..$ description: chr \"Eius praesentium excepturi sint aut quis ipsa. Asperiores dolorem omnis sed officiis. Repellat et omnis amet re\"| __truncated__ #> .. ..$ url : chr \"https://picsum.photos/300/480\""},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"wrapping-individual-endpoints","dir":"Articles","previous_headings":"Faker API","what":"Wrapping individual endpoints","title":"Wrapping APIs","text":"faker() quite general — ’s good tool package developer can read faker documentation translate function call. ’s friendly package user might know anything web APIs. typically next step process wrap individual endpoints functions. example, let’s take persons endpoint three additional parameters: gender (male female), birthday_start, birthday_end. simple wrapper start something like : make user friendly checking input types, returning result tibble. quick dirty conversion using purrr; depending needs use base R code tidyr::hoist(). next steps export document function; ’ll leave .","code":"faker_person <- function(gender = NULL, birthday_start = NULL, birthday_end = NULL, quantity = 1, locale = \"en_US\", seed = NULL) { faker( \"persons\", gender = gender, birthday_start = birthday_start, birthday_end = birthday_end, quantity = quantity, locale = locale, seed = seed ) } str(faker_person(\"male\")) #> List of 6 #> $ status: chr \"OK\" #> $ code : int 200 #> $ locale: chr \"en_US\" #> $ seed : NULL #> $ total : int 1 #> $ data :List of 1 #> ..$ :List of 10 #> .. ..$ id : int 1 #> .. ..$ firstname: chr \"Edward\" #> .. ..$ lastname : chr \"Prosacco\" #> .. ..$ email : chr \"terry.theresia@hotmail.com\" #> .. ..$ phone : chr \"+18206010897\" #> .. ..$ birthday : chr \"1971-06-22\" #> .. ..$ gender : chr \"male\" #> .. ..$ address :List of 10 #> .. .. ..$ id : int 1 #> .. .. ..$ street : chr \"954 McClure Harbor\" #> .. .. ..$ streetName : chr \"Schroeder Overpass\" #> .. .. ..$ buildingNumber: chr \"57961\" #> .. .. ..$ city : chr \"Constantinside\" #> .. .. ..$ zipcode : chr \"37687-3597\" #> .. .. ..$ country : chr \"Tokelau\" #> .. .. ..$ country_code : chr \"TK\" #> .. .. ..$ latitude : num -70.9 #> .. .. ..$ longitude : num -134 #> .. ..$ website : chr \"http://connelly.com\" #> .. ..$ image : chr \"http://placeimg.com/640/480/people\" library(purrr) faker_person <- function(gender = NULL, birthday_start = NULL, birthday_end = NULL, quantity = 1, locale = \"en_US\", seed = NULL) { if (!is.null(gender)) { gender <- match.arg(gender, c(\"male\", \"female\")) } if (!is.null(birthday_start)) { if (!inherits(birthday_start, \"Date\")) { stop(\"`birthday_start` must be a date\") } birthday_start <- format(birthday_start, \"%Y-%m-%d\") } if (!is.null(birthday_end)) { if (!inherits(birthday_end, \"Date\")) { stop(\"`birthday_end` must be a date\") } birthday_end <- format(birthday_end, \"%Y-%m-%d\") } json <- faker( \"persons\", gender = gender, birthday_start = birthday_start, birthday_end = birthday_end, quantity = quantity, locale = locale, seed = seed ) tibble::tibble( firstname = map_chr(json$data, \"firstname\"), lastname = map_chr(json$data, \"lastname\"), email = map_chr(json$data, \"email\"), gender = map_chr(json$data, \"gender\") ) } faker_person(\"male\", quantity = 5) #> # A tibble: 5 × 4 #> firstname lastname email gender #> #> 1 Moshe Shields cierra.lindgren@hotmail.com male #> 2 Deangelo Pacocha dboyle@morissette.net male #> 3 Turner Lynch amely83@yahoo.com male #> 4 Tyrell Keebler udietrich@sipes.biz male #> 5 Gillian Koelpin mason.waters@waelchi.net male"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"secret-management","dir":"Articles","previous_headings":"","what":"Secret management","title":"Wrapping APIs","text":"need take quick break APIs talk secrets. Secrets important, every API (except simple APIs like faker) going require identify way, typically API key token. even plan require users supply information, ’ll still need record credentials order test package. system described likely overkill one secret needs shared couple places: can just put .Renviron access Sys.getenv(). probably accumulate secrets time, ’ll need figure share people computers, think spending little time understand system set package pay long term.","code":""},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"basics","dir":"Articles","previous_headings":"Secret management","what":"Basics","title":"Wrapping APIs","text":"httr2 provides secret_encrypt() secret_decrypt() scramble secrets can include public source code without worrying others can read . three basic steps process: create encryption key secret_make_key() used scramble descramble secrets using symmetric cryptography: (Note secret_make_key() uses cryptographically secure random number generator provided OpenSSL; affected R’s RNG settings, ’s way make reproducible.) scramble secrets secret_encrypt() store resulting text directly source code package: needed, descramble secret using secret_decrypt():","code":"key <- secret_make_key() key #> [1] \"3GGd9TcOii4JRyNmK2angw\" secret_scrambled <- secret_encrypt(\"secret I need to work with an API\", key) secret_scrambled #> [1] \"8dyoF1ZJDsiz6L1A3R_I4AINduOmgJQi-S53iEmp1KyviDoxYmvg5cZyec8VV2IpmQ\" secret_decrypt(secret_scrambled, key) #> [1] \"secret I need to work with an API\""},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"package-keys-and-secrets","dir":"Articles","previous_headings":"Secret management","what":"Package keys and secrets","title":"Wrapping APIs","text":"can create number encryption keys, highly recommend create one key per package, ’ll call package key. section, ’ll show store key (automated tests) can use , one else can. httr2 built around notion key live environment variable. first step make package key available local development machine adding line user-level .Renviron (can easily open usethis::edit_r_environ()): Now (restart R), ’ll able take advantage special secret_encrypt() secret_decrypt() feature: key argument can name environment variable, instead encryption key . fact, natural usage. ’ll also need make key available GitHub Actions (check pkgdown) automated tests can use . requires two steps: Add key repository secrets. Share key workflows need adding line appropriate workflow: can see httr2 GitHub workflow. continuous integration platforms offer similar ways make key available secure environment variable.","code":"YOURPACKAGE_KEY=key_you_generated_with_secret_make_key secret_scrambled <- secret_encrypt(\"secret I need to work with an API\", \"YOURPACKAGE_KEY\") secret_scrambled #> [1] \"vcVaWmIEYj72LltkbTCdEmLApqOlOQDp94ybx78OhbLC1jFpuw24yJCP4dgf447uQQ\" secret_decrypt(secret_scrambled, \"YOURPACKAGE_KEY\") #> [1] \"secret I need to work with an API\" env: YOURPACKAGE_KEY: ${{ secrets.YOURPACKAGE_KEY }}"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"when-the-package-key-isnt-available","dir":"Articles","previous_headings":"Secret management","what":"When the package key isn’t available","title":"Wrapping APIs","text":"important cases code won’t access package key: CRAN, personal machines external contributors, automated checks PRs. want share package CRAN make easy others contribute, need make sure examples, vignettes, tests work without error: vignettes, can run knitr::opts_chunk(eval = secret_has_key(\"YOURPACKAGE_KEY\")) chunks evaluated key available. examples, can surround code blocks require key (httr2::secret_has_key(\"YOURPACKAGE_KEY\")) {} don’t need anything tests secret_decrypt() run testthat, automatically skip() test key isn’t available.","code":""},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"nytimes-books-api","dir":"Articles","previous_headings":"","what":"NYTimes Books API","title":"Wrapping APIs","text":"Next ’ll take look NYTimes Books API. requires simple authentication API key ’s included every request. ’re wrapping API key ’re going face two struggles: test package without sharing key whole world? allow users supply key, without pass every function? now can understand following code works get NYTimes Book API key: ’ll start tackling first problem otherwise ’s way show API works vignette 😃. ’ll come back second end section, ’s easiest tackle function place.","code":"my_key <- secret_decrypt(\"4Nx84VPa83dMt3X6bv0fNBlLbv3U4D1kHM76YisKEfpCarBm1UHJHARwJHCFXQSV\", \"HTTR2_KEY\")"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"security-considerations","dir":"Articles","previous_headings":"NYTimes Books API","what":"Security considerations","title":"Wrapping APIs","text":"Note including API key query parameter relatively insecure; API uses method auth, ’s typically key relatively easy create gives relatively privileges. takes couple minutes generate NYTimes API key, ’s little incentive someone try steal . main problem conveying credentials via url ’s easily exposed, httr2 makes efforts redact confidential information stored query parameters. means ’s relatively easy leak key use req_perform(verbosity = 1), req_dry_run(), even just print request object. indeed, ’ll see examples — bad practice real package, think ’s ok key doesn’t allow anything valuable makes teaching APIs much easier.","code":""},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"basic-request","dir":"Articles","previous_headings":"NYTimes Books API","what":"Basic request","title":"Wrapping APIs","text":"Now let’s perform test request look response: Like modern APIs, one returns results JSON: start wrapping function, let’s consider happens errors.","code":"resp <- request(\"https://api.nytimes.com/svc/books/v3\") |> req_url_path_append(\"/reviews.json\") |> req_url_query(`api-key` = my_key, isbn = 9780307476463) |> req_perform() resp resp |> resp_body_json() |> str()"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"error-handling","dir":"Articles","previous_headings":"NYTimes Books API","what":"Error handling","title":"Wrapping APIs","text":"happens ’s error? example, deliberately supply invalid key: see ’s extra useful information can look last_response(): looks like ’s useful additional info faultstring: add information future errors can use body argument req_error(). function takes response returns character vector additional information include error. re-fetch request, see additional information displayed R error:","code":"resp <- request(\"https://api.nytimes.com/svc/books/v3\") |> req_url_path_append(\"/reviews.json\") |> req_url_query(`api-key` = \"invalid\", isbn = 9780307476463) |> req_perform() resp <- last_response() resp resp |> resp_body_json() resp |> resp_body_json() |> _$fault |> _$faultstring nytimes_error_body <- function(resp) { resp |> resp_body_json() |> _$fault |> _$faultstring } resp <- request(\"https://api.nytimes.com/svc/books/v3\") |> req_url_path_append(\"/reviews.json\") |> req_url_query(`api-key` = \"invalid\", isbn = 9780307476463) |> req_error(body = nytimes_error_body) |> req_perform()"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"rate-limits","dir":"Articles","previous_headings":"NYTimes Books API","what":"Rate limits","title":"Wrapping APIs","text":"Another common source errors rate-limiting — used many servers prevent one unruly client consuming many resources. frequently asked questions page describes rate limits NYT APIs: Yes, two rate limits per API: 4,000 requests per day 10 requests per minute. sleep 6 seconds calls avoid hitting per minute rate limit. need higher rate limit, please contact us code@nytimes.com. Many APIs return additional information long wait rate limit exceeded (often using Retry-header). deliberately violated rate limit quickly making 11 requests; unfortunately response standard 429 (many requests), include information long wait either response body headers. means can’t use req_retry(), automatically waits amount time server requests. Instead, ’ll use req_throttle() ensure don’t make 10 requests every 60 seconds: default, req_throttle() shares limit across requests made host (.e. api.nytimes.com). Since docs suggest rate limit applies per API, might want use realm argument bit specific:","code":"req <- request(\"https://api.nytimes.com/svc/books/v3\") |> req_url_path_append(\"/reviews.json\") |> req_url_query(`api-key` = \"invalid\", isbn = 9780307476463) |> req_throttle(10 / 60) req <- request(\"https://api.nytimes.com/svc/books/v3\") |> req_url_path_append(\"/reviews.json\") |> req_url_query(`api-key` = \"invalid\", isbn = 9780307476463) |> req_throttle(10 / 60, realm = \"https://api.nytimes.com/svc/books\")"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"wrapping-it-up","dir":"Articles","previous_headings":"NYTimes Books API","what":"Wrapping it up","title":"Wrapping APIs","text":"Putting together pieces yields function something like : finish real package, ’d want : Add explicit arguments check correct type. Export document function. Convert nested list user-friendly data structure (probably data frame one row per review). ’d also want provide convenient way user supply API key.","code":"nytimes_books <- function(api_key, path, ...) { request(\"https://api.nytimes.com/svc/books/v3\") |> req_url_path_append(path) |> req_url_query(..., `api-key` = api_key) |> req_error(body = nytimes_error_body) |> req_throttle(10 / 60, realm = \"https://api.nytimes.com/svc/books\") |> req_perform() |> resp_body_json() } drunk <- nytimes_books(my_key, \"/reviews.json\", isbn = \"0316453382\") drunk$results[[1]]$summary"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"user-supplied-key","dir":"Articles","previous_headings":"NYTimes Books API","what":"User-supplied key","title":"Wrapping APIs","text":"good place start environment variable, environment variables easy set without typing anything console (can get accidentally shared via .Rhistory) easily set automated processes. ’d write function retrieve API key, returning helpful message ’s found: modify nytimes_books() use get_api_key() default value api_key. Since argument now optional, can move end argument list, since ’ll needed exceptional circumstances. can make approach little user friendly providing helper sets environment variable: Using askpass (similar) good practice since don’t want encourage user type secret key console, mentioned . ’s good idea extend get_api_key() automatically use encrypted key make easier write tests:","code":"get_api_key <- function() { key <- Sys.getenv(\"NYTIMES_KEY\") if (identical(key, \"\")) { stop(\"No API key found, please supply with `api_key` argument or with NYTIMES_KEY env var\") } key } nytimes_books <- function(path, ..., api_key = get_api_key()) { ... } set_api_key <- function(key = NULL) { if (is.null(key)) { key <- askpass::askpass(\"Please enter your API key\") } Sys.setenv(\"NYTIMES_KEY\" = key) } get_api_key <- function() { key <- Sys.getenv(\"NYTIMES_KEY\") if (!identical(key, \"\")) { return(key) } if (is_testing()) { return(testing_key()) } else { stop(\"No API key found, please supply with `api_key` argument or with NYTIMES_KEY env var\") } } is_testing <- function() { identical(Sys.getenv(\"TESTTHAT\"), \"true\") } testing_key <- function() { secret_decrypt(\"4Nx84VPa83dMt3X6bv0fNBlLbv3U4D1kHM76YisKEfpCarBm1UHJHARwJHCFXQSV\", \"HTTR2_KEY\") }"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"github-gists-api","dir":"Articles","previous_headings":"","what":"Github Gists API","title":"Wrapping APIs","text":"Next ’ll take look API can make changes behalf user, just retrieve data: GitHub’s gist API. uses different HTTP methods perform different actions, like creating, updating, deleting gists. can get , let’s handle authentication, rate-limiting, errors.","code":""},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"authentication","dir":"Articles","previous_headings":"Github Gists API","what":"Authentication","title":"Wrapping APIs","text":"easiest way authenticate GitHub API use personal access token. token alternative username password. one username + password per site; can one token per use case. lets use case minimal set permissions, can easily revoke one token without affecting use case. created personal access token specifically vignette can access gists, , last example, stored encrypted version vignette: want run vignette , ’ll need create new token GitHub settings; just make sure includes “gist” scope. ’s also good idea give every token descriptive name, reminds motivating use case, update re-generate expired. authenticate request token, need put Authorization header “token” prefix: authorization header usually contains secret information, httr2 automatically redacts it1:","code":"token <- secret_decrypt(\"Guz59woxKoIO_JVtp2IzU3mFIU3ULtaUEa8xvvpYUBdVthR8jhxzc3bMZFhA9HL-ZK6YZudOI6g\", \"HTTR2_KEY\") req <- request(\"https://api.github.com/gists\") |> req_headers(Authorization = paste(\"token\", token)) req |> req_perform() req req |> req_dry_run()"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"errors-1","dir":"Articles","previous_headings":"Github Gists API","what":"Errors","title":"Wrapping APIs","text":"’ve got authentication working, ’s always good idea work errors next, since help debug failed requests. experience APIs rarely good job documenting errors, ’ll often little experimentation. add pain, large APIs different endpoints often return different amounts information different forms. ’ll typically need tackle error handling iteratively, improving code time encounter new problem. GitHub document errors, ’m sufficiently distrustful still want construct deliberately malformed query see happens: documented get 422 “Unprocessable Entity” error. response rather different documentation suggests string message list errors: ’ll proceed anyway, writing function extracts data formats presentation user: Now can pass function body argument req_error() automatically included error request fails: Notice element character vector produced gh_error_body() becomes bullet resulting error.","code":"resp <- request(\"https://api.github.com/gists\") |> req_url_query(since = \"abcdef\") |> req_headers(Authorization = paste(\"token\", token)) |> req_perform() resp <- last_response() resp resp |> resp_body_json() gist_error_body <- function(resp) { body <- resp_body_json(resp) message <- body$message if (!is.null(body$documentation_url)) { message <- c(message, paste0(\"See docs at <\", body$documentation_url, \">\")) } message } gist_error_body(resp) request(\"https://api.github.com/gists\") |> req_url_query(since = \"yesterday\") |> req_headers(Authorization = paste(\"token\", token)) |> req_error(body = gist_error_body) |> req_perform()"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"rate-limiting","dir":"Articles","previous_headings":"Github Gists API","what":"Rate-limiting","title":"Wrapping APIs","text":"’re thinking errors, ’s useful look happens requests rate limited. Luckily, GitHub consistently uses response headers provide information remaining rate limits. can teach httr2 can automatically wait reset rate limit hit. need define two functions. first tells us whether response transient error, .e. ’s worth waiting trying . GitHub, rate limit exceeded, response 403 status X-RateLimit-Remaining: 0 header: need function tells long wait. GitHub tells us rate limit resets (number seconds since 1970-01-01) X-RateLimit-Reset header. convert number seconds wait first convert number (since HTTP headers always strings), subtract current time (number seconds since 1970-01-01): pass functions req_retry() httr2 information needs handle rate-limiting automatically: also need supply either max_tries max_seconds order activate req_retry().","code":"resp <- req |> req_perform() resp |> resp_headers(\"ratelimit\") gist_is_transient <- function(resp) { resp_status(resp) == 403 && resp_header(resp, \"X-RateLimit-Remaining\") == \"0\" } gist_is_transient(resp) gist_after <- function(resp) { time <- as.numeric(resp_header(resp, \"X-RateLimit-Reset\")) time - unclass(Sys.time()) } gist_after(resp) request(\"http://api.github.com\") |> req_retry( is_transient = gist_is_transient, after = gist_after, max_seconds = 60 )"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"wrapping-it-all-up","dir":"Articles","previous_headings":"Github Gists API","what":"Wrapping it all up","title":"Wrapping APIs","text":"Let’s wrap everything ’ve learned far single function creates request: ’ll use basis solve next challenge: uploading gist.","code":"req_gist <- function(token) { request(\"https://api.github.com/gists\") |> req_headers(Authorization = paste(\"token\", token)) |> req_error(body = gist_error_body) |> req_retry( is_transient = gist_is_transient, after = gist_after ) } # Check it works: req_gist(token) |> req_perform()"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"sending-data","dir":"Articles","previous_headings":"Github Gists API","what":"Sending data","title":"Wrapping APIs","text":"create gist need change method POST add body contains data encoded JSON. httr2 provides one function things: req_body_json(): Depending API ’re wrapping, might need send data different way. req_body_form() req_body_multipart() make easier encode data two common forms. API requires something different can use req_body_raw(). Typically, API return useful data resource ’ve just created. ’ll extract gist ID can use next examples, culminating deleting gist don’t end bunch duplicated gists 😃.","code":"req <- req_gist(token) |> req_body_json(list( description = \"This is my cool gist!\", files = list(test.R = list(content = \"print('Hi!')\")), public = FALSE )) req |> req_dry_run() resp <- req |> req_perform() id <- resp |> resp_body_json() |> _$id id"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"changing-a-gist","dir":"Articles","previous_headings":"Github Gists API","what":"Changing a gist","title":"Wrapping APIs","text":"Actually, description wasn’t true want change . , need send JSON encoded data, time need use PATCH verb. adding data request, use req_method() override default method:","code":"req <- req_gist(token) |> req_url_path_append(id) |> req_body_json(list(description = \"This is a simple gist\")) |> req_method(\"PATCH\") req |> req_dry_run()"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"deleting-a-gist","dir":"Articles","previous_headings":"Github Gists API","what":"Deleting a gist","title":"Wrapping APIs","text":"Deleting gist similar, except don’t send data, just need adjust default method GET DELETE.","code":"req <- req_gist(token) |> req_url_path_append(id) |> req_method(\"DELETE\") req |> req_dry_run() req |> req_perform()"},{"path":"https://httr2.r-lib.org/dev/authors.html","id":null,"dir":"","previous_headings":"","what":"Authors","title":"Authors and Citation","text":"Hadley Wickham. Author, maintainer. . Copyright holder, funder. Maximilian Girlich. Contributor.","code":""},{"path":"https://httr2.r-lib.org/dev/authors.html","id":"citation","dir":"","previous_headings":"","what":"Citation","title":"Authors and Citation","text":"Wickham H (2024). httr2: Perform HTTP Requests Process Responses. R package version 1.0.5.9000, https://github.com/r-lib/httr2, https://httr2.r-lib.org.","code":"@Manual{, title = {httr2: Perform HTTP Requests and Process the Responses}, author = {Hadley Wickham}, year = {2024}, note = {R package version 1.0.5.9000, https://github.com/r-lib/httr2}, url = {https://httr2.r-lib.org}, }"},{"path":"https://httr2.r-lib.org/dev/index.html","id":"httr2-","dir":"","previous_headings":"","what":"Perform HTTP Requests and Process the Responses","title":"Perform HTTP Requests and Process the Responses","text":"httr2 (pronounced hitter2) ground-rewrite httr provides pipeable API explicit request object solves problems felt packages wrap APIs (e.g. built-rate-limiting, retries, OAuth, secure secrets, ).","code":""},{"path":"https://httr2.r-lib.org/dev/index.html","id":"installation","dir":"","previous_headings":"","what":"Installation","title":"Perform HTTP Requests and Process the Responses","text":"can install httr2 CRAN :","code":"install.packages(\"httr2\")"},{"path":"https://httr2.r-lib.org/dev/index.html","id":"usage","dir":"","previous_headings":"","what":"Usage","title":"Perform HTTP Requests and Process the Responses","text":"use httr2, start creating request: can tailor request req_ family functions: see exactly httr2 send server req_dry_run(): Use req_perform() perform request, retrieving response: resp_ functions help extract various useful components response:","code":"library(httr2) req <- request(\"https://r-project.org\") req #> #> GET https://r-project.org #> Body: empty # Add custom headers req |> req_headers(\"Accept\" = \"application/json\") #> #> GET https://r-project.org #> Headers: #> • Accept: 'application/json' #> Body: empty # Add a body, turning it into a POST req |> req_body_json(list(x = 1, y = 2)) #> #> POST https://r-project.org #> Body: json encoded data # Modify the path in the url req |> req_url_path(path = \"path/to/my/file\") #> #> GET https://r-project.org/path/to/my/file #> Body: empty # Automatically retry if the request fails req |> req_retry(max_tries = 5) #> #> GET https://r-project.org #> Body: empty #> Policies: #> • retry_max_tries: 5 #> • retry_on_failure: FALSE # Change the HTTP method req |> req_method(\"PATCH\") #> #> PATCH https://r-project.org #> Body: empty req |> req_dry_run() #> GET / HTTP/1.1 #> Host: r-project.org #> User-Agent: httr2/1.0.3.9000 r-curl/5.2.2 libcurl/8.6.0 #> Accept: */* #> Accept-Encoding: deflate, gzip resp <- req_perform(req) resp #> #> GET https://www.r-project.org/ #> Status: 200 OK #> Content-Type: text/html #> Body: In memory (6951 bytes) resp |> resp_content_type() #> [1] \"text/html\" resp |> resp_status_desc() #> [1] \"OK\" resp |> resp_body_html() #> {html_document} #> #> [1] \\n [2] \\n
    \\n
    \\n ..."},{"path":"https://httr2.r-lib.org/dev/index.html","id":"major-differences-to-httr","dir":"","previous_headings":"","what":"Major differences to httr","title":"Perform HTTP Requests and Process the Responses","text":"can now create modify request without performing . means ’s now single function perform request fetch result: req_perform(). req_perform() replaces httr::GET(), httr::POST(), httr::DELETE(), . HTTP errors automatically converted R errors. Use req_error() override defaults (turn 4xx 5xx responses errors) add additional details error message. can automatically retry request fails encounters transient HTTP error (e.g. 429 rate limit request). req_retry() defines maximum number retries, errors transient, long wait tries. OAuth support totally overhauled directly support many flows make much easier customise built-flows create . can manage secrets (often needed testing) secret_encrypt() friends. can obfuscate mildly confidential data obfuscate(), preventing scraped published code. can automatically cache cacheable results req_cache(). Relatively API responses cacheable, typically makes big difference.","code":""},{"path":"https://httr2.r-lib.org/dev/index.html","id":"acknowledgements","dir":"","previous_headings":"","what":"Acknowledgements","title":"Perform HTTP Requests and Process the Responses","text":"httr2 wouldn’t possible without curl, openssl, jsonlite, jose, maintained Jeroen Ooms. big thanks also go Jenny Bryan Craig Citro given much useful feedback design internals user facing API.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/curl_translate.html","id":null,"dir":"Reference","previous_headings":"","what":"Translate curl syntax to httr2 — curl_translate","title":"Translate curl syntax to httr2 — curl_translate","text":"curl command line tool commonly used demonstrate HTTP APIs can easily generated browser developer tools. curl_translate() saves pain manually translating calls implementing partial, frequently used, subset curl options. Use curl_help() see supported options, curl_translate() translate curl invocation copy pasted elsewhere. Inspired curlconverter written Bob Rudis.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/curl_translate.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Translate curl syntax to httr2 — curl_translate","text":"","code":"curl_translate(cmd, simplify_headers = TRUE) curl_help()"},{"path":"https://httr2.r-lib.org/dev/reference/curl_translate.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Translate curl syntax to httr2 — curl_translate","text":"cmd Call curl. omitted clipr package installed, retrieved clipboard. simplify_headers Remove typically unimportant headers included copying curl command browser. includes: sec-fetch-* sec-ch-ua* referer, pragma, connection","code":""},{"path":"https://httr2.r-lib.org/dev/reference/curl_translate.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Translate curl syntax to httr2 — curl_translate","text":"string containing translated httr2 code. input copied clipboard, translation copied back clipboard.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/curl_translate.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Translate curl syntax to httr2 — curl_translate","text":"","code":"curl_translate(\"curl http://example.com\") #> request(\"http://example.com\") |> #> req_perform() curl_translate(\"curl http://example.com -X DELETE\") #> request(\"http://example.com\") |> #> req_method(\"DELETE\") |> #> req_perform() curl_translate(\"curl http://example.com --header A:1 --header B:2\") #> request(\"http://example.com\") |> #> req_headers( #> A = \"1\", #> B = \"2\", #> ) |> #> req_perform() curl_translate(\"curl http://example.com --verbose\") #> request(\"http://example.com\") |> #> req_perform(verbosity = 1)"},{"path":"https://httr2.r-lib.org/dev/reference/example_url.html","id":null,"dir":"Reference","previous_headings":"","what":"Code for examples — example_url","title":"Code for examples — example_url","text":"example_url() runs simple websever using webfakes package following endpoints: ones webfakes::httpbin_app() /iris: paginate iris dataset. query parameters page limit control pagination. example_github_client() OAuth client GitHub.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/example_url.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Code for examples — example_url","text":"","code":"example_url() example_github_client()"},{"path":"https://httr2.r-lib.org/dev/reference/httr2-package.html","id":null,"dir":"Reference","previous_headings":"","what":"httr2: Perform HTTP Requests and Process the Responses — httr2-package","title":"httr2: Perform HTTP Requests and Process the Responses — httr2-package","text":"Tools creating modifying HTTP requests, performing processing results. 'httr2' modern re-imagining 'httr' uses pipe-based interface solves problems API wrapping packages face.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/httr2-package.html","id":"author","dir":"Reference","previous_headings":"","what":"Author","title":"httr2: Perform HTTP Requests and Process the Responses — httr2-package","text":"Maintainer: Hadley Wickham hadley@posit.co contributors: Posit Software, PBC [copyright holder, funder] Maximilian Girlich [contributor]","code":""},{"path":"https://httr2.r-lib.org/dev/reference/iterate_with_offset.html","id":null,"dir":"Reference","previous_headings":"","what":"Iteration helpers — iterate_with_offset","title":"Iteration helpers — iterate_with_offset","text":"functions intended use next_req argument req_perform_iterative(). implements iteration common pagination pattern: iterate_with_offset() increments query parameter, e.g. ?page=1, ?page=2, ?offset=1, offset=21. iterate_with_cursor() updates query parameter value cursor found somewhere response. iterate_with_link_url() follows url found Link header. See resp_link_url() details.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/iterate_with_offset.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Iteration helpers — iterate_with_offset","text":"","code":"iterate_with_offset( param_name, start = 1, offset = 1, resp_pages = NULL, resp_complete = NULL ) iterate_with_cursor(param_name, resp_param_value) iterate_with_link_url(rel = \"next\")"},{"path":"https://httr2.r-lib.org/dev/reference/iterate_with_offset.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Iteration helpers — iterate_with_offset","text":"param_name Name query parameter. start Starting value. offset Offset page. default set 1 get (e.g.) ?page=1, ?page=2, ... param_name refers element index (rather page index) want set larger number get (e.g.) ?items=20, ?items=40, ... resp_pages callback function takes response (resp) returns total number pages, NULL unknown. called . resp_complete callback function takes response (resp) returns TRUE pages. resp_param_value callback function takes response (resp) returns next cursor value. Return NULL pages. rel \"link relation type\" use retrieve next page.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/iterate_with_offset.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Iteration helpers — iterate_with_offset","text":"","code":"req <- request(example_url()) |> req_url_path(\"/iris\") |> req_throttle(10) |> req_url_query(limit = 50) # If you don't know the total number of pages in advance, you can # provide a `resp_complete()` callback is_complete <- function(resp) { length(resp_body_json(resp)$data) == 0 } resps <- req_perform_iterative( req, next_req = iterate_with_offset(\"page_index\", resp_complete = is_complete), max_reqs = Inf ) if (FALSE) { # \\dontrun{ # Alternatively, if the response returns the total number of pages (or you # can easily calculate it), you can use the `resp_pages()` callback which # will generate a better progress bar. resps <- req_perform_iterative( req |> req_url_query(limit = 1), next_req = iterate_with_offset( \"page_index\", resp_pages = function(resp) resp_body_json(resp)$pages ), max_reqs = Inf ) } # }"},{"path":"https://httr2.r-lib.org/dev/reference/jwt_claim.html","id":null,"dir":"Reference","previous_headings":"","what":"Create and encode a JWT — jwt_claim","title":"Create and encode a JWT — jwt_claim","text":"jwt_claim() wrapper around jose::jwt_claim() creates JWT claim set extra default values. jwt_encode_sig() jwt_encode_hmac() thin wrappers around jose::jwt_encode_sig() jose::jwt_encode_hmac() exist primarily make specification functions little simpler.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/jwt_claim.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Create and encode a JWT — jwt_claim","text":"","code":"jwt_claim( iss = NULL, sub = NULL, aud = NULL, exp = unix_time() + 5L * 60L, nbf = unix_time(), iat = unix_time(), jti = NULL, ... ) jwt_encode_sig(claim, key, size = 256, header = list()) jwt_encode_hmac(claim, secret, size = 256, header = list())"},{"path":"https://httr2.r-lib.org/dev/reference/jwt_claim.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Create and encode a JWT — jwt_claim","text":"iss Issuer claim. Identifies principal issued JWT. sub Subject claim. Identifies principal subject JWT (.e. entity claims apply ). aud Audience claim. Identifies recipients JWT intended. principle intended process JWT must identified unique value. exp Expiration claim. Identifies expiration time JWT MUST accepted processing. Defaults 5 minutes. nbf claim. Identifies time JWT MUST accepted processing. Defaults current time. iat Issued claim. Identifies time JWT issued. Defaults current time. jti JWT ID claim. Provides unique identifier JWT. omitted, uses random 32-byte sequence encoded base64url. ... additional claims include claim set. claim Claim set produced jwt_claim(). key RSA EC private key either specified path file, connection, string (PEM/SSH format), raw vector (DER format). size Size, bits, sha2 signature, .e. 256, 384 512. HMAC/RSA, applicable ECDSA keys. header named list giving additional fields include JWT header. secret String raw vector secret passphrase.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/jwt_claim.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Create and encode a JWT — jwt_claim","text":"S3 list class jwt_claim.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/jwt_claim.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Create and encode a JWT — jwt_claim","text":"","code":"claim <- jwt_claim() str(claim) #> List of 4 #> $ exp: num 1.73e+09 #> $ nbf: num 1.73e+09 #> $ iat: num 1.73e+09 #> $ jti: chr \"3lE_9sXqjVacozKM_TBiDMpW_Eku1D4d1rvDY_CLZck\" #> - attr(*, \"class\")= chr [1:2] \"jwt_claim\" \"list\""},{"path":"https://httr2.r-lib.org/dev/reference/last_response.html","id":null,"dir":"Reference","previous_headings":"","what":"Retrieve most recent request/response — last_response","title":"Retrieve most recent request/response — last_response","text":"functions retrieve recent request made httr2 response received, facilitate debugging problems occur. request succeed (requests made) last_response() NULL.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/last_response.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Retrieve most recent request/response — last_response","text":"","code":"last_response() last_request()"},{"path":"https://httr2.r-lib.org/dev/reference/last_response.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Retrieve most recent request/response — last_response","text":"HTTP response/request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/last_response.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Retrieve most recent request/response — last_response","text":"","code":"invisible(request(\"http://httr2.r-lib.org\") |> req_perform()) last_request() #> #> GET http://httr2.r-lib.org #> Body: empty last_response() #> #> GET https://httr2.r-lib.org/ #> Status: 200 OK #> Content-Type: text/html #> Body: In memory (18819 bytes)"},{"path":"https://httr2.r-lib.org/dev/reference/multi_req_perform.html","id":null,"dir":"Reference","previous_headings":"","what":"Perform a list of requests in parallel — multi_req_perform","title":"Perform a list of requests in parallel — multi_req_perform","text":"Please use req_perform_parallel() instead, note: cancel_on_error = FALSE now on_error = \"continue\" cancel_on_error = TRUE now on_error = \"return\"","code":""},{"path":"https://httr2.r-lib.org/dev/reference/multi_req_perform.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Perform a list of requests in parallel — multi_req_perform","text":"","code":"multi_req_perform(reqs, paths = NULL, pool = NULL, cancel_on_error = FALSE)"},{"path":"https://httr2.r-lib.org/dev/reference/multi_req_perform.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Perform a list of requests in parallel — multi_req_perform","text":"reqs list requests. paths optional character vector paths, want download request bodies disk. supplied, must length reqs. pool Optionally, curl pool made curl::new_pool(). Supply want override defaults total concurrent connections (100) concurrent connections per host (6). cancel_on_error pending requests cancelled hit error? Set TRUE stop requests soon hit error. Responses never performed NULL result.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_cache_path.html","id":null,"dir":"Reference","previous_headings":"","what":"httr2 OAuth cache location — oauth_cache_path","title":"httr2 OAuth cache location — oauth_cache_path","text":"opted-, httr2 caches OAuth tokens directory. default, uses OS-standard cache directory, , needed, can override location setting HTTR2_OAUTH_CACHE env var.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_cache_path.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"httr2 OAuth cache location — oauth_cache_path","text":"","code":"oauth_cache_path()"},{"path":"https://httr2.r-lib.org/dev/reference/oauth_client.html","id":null,"dir":"Reference","previous_headings":"","what":"Create an OAuth client — oauth_client","title":"Create an OAuth client — oauth_client","text":"OAuth app combination client, set endpoints (.e. urls various requests sent), authentication mechanism. client consists least client_id, also often client_secret. get values create client API's website.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_client.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Create an OAuth client — oauth_client","text":"","code":"oauth_client( id, token_url, secret = NULL, key = NULL, auth = c(\"body\", \"header\", \"jwt_sig\"), auth_params = list(), name = hash(id) )"},{"path":"https://httr2.r-lib.org/dev/reference/oauth_client.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Create an OAuth client — oauth_client","text":"id Client identifier. token_url Url retrieve access token. secret Client secret. apps, technically confidential principle avoid storing source code. However, many APIs require order provide user friendly authentication experience, risks including usually low. make things little safer, recommend using obfuscate() recording client secret public code. key Client key. alternative using secret, can instead supply confidential private key. never included package. auth Authentication mechanism used client prove API. Can one three built-methods (\"body\", \"header\", \"jwt\"), function called arguments req, client, contents auth_params. common mechanism wild \"body\" client_id (optionally) client_secret added body. \"header\" sends client_id client_secret HTTP Authorization header. \"jwt_sig\" generate JWT, include client_assertion field body. See oauth_client_req_auth() details. auth_params Additional parameters passed function specified auth. name Optional name client. Used generating cache directory. NULL, generated hash client_id. defining client use package, recommend use package name.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_client.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Create an OAuth client — oauth_client","text":"OAuth client: S3 list class httr2_oauth_client.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_client.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Create an OAuth client — oauth_client","text":"","code":"oauth_client(\"myclient\", \"http://example.com/token_url\", secret = \"DONTLOOK\") #> #> name: 920903ca1274bc747bb367c6b5abe4a4 #> id: myclient #> secret: #> token_url: http://example.com/token_url #> auth: oauth_client_req_auth_body"},{"path":"https://httr2.r-lib.org/dev/reference/oauth_client_req_auth.html","id":null,"dir":"Reference","previous_headings":"","what":"OAuth client authentication — oauth_client_req_auth","title":"OAuth client authentication — oauth_client_req_auth","text":"oauth_client_req_auth() authenticates request using authentication strategy defined auth auth_param arguments oauth_client(). used authenticate client part OAuth flow, authenticate request behalf user. three built-strategies: oauth_client_req_body() adds client id (optionally) secret request body, described Section 2.3.1 RFC 6749. oauth_client_req_header() adds client id secret using HTTP basic authentication Authorization header, described Section 2.3.1 RFC 6749. oauth_client_jwt_rs256() adds client assertion body using JWT signed jwt_sign_rs256() using private key, described Section 2.2 RFC 7523. generally call functions directly instead specify auth argument oauth_client(). req client parameters automatically filled ; parameters come auth_params argument.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_client_req_auth.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"OAuth client authentication — oauth_client_req_auth","text":"","code":"oauth_client_req_auth(req, client) oauth_client_req_auth_header(req, client) oauth_client_req_auth_body(req, client) oauth_client_req_auth_jwt_sig(req, client, claim, size = 256, header = list())"},{"path":"https://httr2.r-lib.org/dev/reference/oauth_client_req_auth.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"OAuth client authentication — oauth_client_req_auth","text":"req httr2 request object. client oauth_client. claim Claim set produced jwt_claim(). size Size, bits, sha2 signature, .e. 256, 384 512. HMAC/RSA, applicable ECDSA keys. header named list giving additional fields include JWT header.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_client_req_auth.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"OAuth client authentication — oauth_client_req_auth","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_client_req_auth.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"OAuth client authentication — oauth_client_req_auth","text":"","code":"# Show what the various forms of client authentication look like req <- request(\"https://example.com/whoami\") client1 <- oauth_client( id = \"12345\", secret = \"56789\", token_url = \"https://example.com/oauth/access_token\", name = \"oauth-example\", auth = \"body\" # the default ) # calls oauth_client_req_auth_body() req_dry_run(oauth_client_req_auth(req, client1)) #> POST /whoami HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Content-Type: application/x-www-form-urlencoded #> Content-Length: 35 #> #> client_id=12345&client_secret=56789 client2 <- oauth_client( id = \"12345\", secret = \"56789\", token_url = \"https://example.com/oauth/access_token\", name = \"oauth-example\", auth = \"header\" ) # calls oauth_client_req_auth_header() req_dry_run(oauth_client_req_auth(req, client2)) #> GET /whoami HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Authorization: #> client3 <- oauth_client( id = \"12345\", key = openssl::rsa_keygen(), token_url = \"https://example.com/oauth/access_token\", name = \"oauth-example\", auth = \"jwt_sig\", auth_params = list(claim = jwt_claim()) ) # calls oauth_client_req_auth_header_jwt_sig() req_dry_run(oauth_client_req_auth(req, client3)) #> POST /whoami HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Content-Type: application/x-www-form-urlencoded #> Content-Length: 623 #> #> client_assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJleHAiOjE3Mjk3MDc1MDcsIm5iZiI6MTcyOTcwNzIwNywiaWF0IjoxNzI5NzA3MjA3LCJqdGkiOiJJT1B0Yld4Q1pGaEYtWHM2YkE1UlE4a0V0OW16cHptUW1uSk5iT3NzU2dVIn0.FWpA-6loLT5U34Qu1hxiGUagKK6mDgDdWD3AObT6nUgs13OcWGRA0HKGhuI-JyIUsSR5pn2cqq7xAeJKuRKYhQisZzQfukRNNsqW-ofFPAM71RAObIydcNfYQIxkg4AzX_S32lJ6Y4cLXDT1ONSgB9ICLVhfMk9rchSCibRhjZekzbH6tdVNVuZnFAfis_fL4TLUdRSls0WKNQN02CMpI7Sb3R3ATeTL3TCmE-4Wms8D9SatQG7Mw57z_55GZqVfTTpKQ6cJtn7f_c_9AZat1ahOh3_RTzc_wr7_AdFe1eyg5iZd7WqOkgCmQCvDEDgnfd1zwomNmssZjim8O76QwQ&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer"},{"path":"https://httr2.r-lib.org/dev/reference/oauth_flow_auth_code_url.html","id":null,"dir":"Reference","previous_headings":"","what":"OAuth authorization code components — oauth_flow_auth_code_url","title":"OAuth authorization code components — oauth_flow_auth_code_url","text":"low-level functions can used assemble custom flow APIs spec: oauth_flow_auth_code_url() generates url opened browser. oauth_flow_auth_code_listen() starts temporary local webserver listens response resource server. oauth_flow_auth_code_parse() parses query parameters returned server redirect, verifying state correct, returning authorisation code. oauth_flow_auth_code_pkce() generates code verifier, method, challenge components needed PKCE, defined RFC 7636.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_flow_auth_code_url.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"OAuth authorization code components — oauth_flow_auth_code_url","text":"","code":"oauth_flow_auth_code_url( client, auth_url, redirect_uri = NULL, scope = NULL, state = NULL, auth_params = list() ) oauth_flow_auth_code_listen(redirect_uri = \"http://localhost:1410\") oauth_flow_auth_code_parse(query, state) oauth_flow_auth_code_pkce()"},{"path":"https://httr2.r-lib.org/dev/reference/oauth_flow_auth_code_url.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"OAuth authorization code components — oauth_flow_auth_code_url","text":"state Random state generated oauth_flow_auth_code(). Used verify working authentication request created. (unlikely threat R packages since webserver listens authorization responses transient.) query List query parameters returned oauth_flow_auth_code_listen().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_redirect_uri.html","id":null,"dir":"Reference","previous_headings":"","what":"Default redirect url for OAuth — oauth_redirect_uri","title":"Default redirect url for OAuth — oauth_redirect_uri","text":"default redirect uri used req_oauth_auth_code(). Defaults http://localhost unless HTTR2_OAUTH_REDIRECT_URL envvar set.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_redirect_uri.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Default redirect url for OAuth — oauth_redirect_uri","text":"","code":"oauth_redirect_uri()"},{"path":"https://httr2.r-lib.org/dev/reference/oauth_token.html","id":null,"dir":"Reference","previous_headings":"","what":"Create an OAuth token — oauth_token","title":"Create an OAuth token — oauth_token","text":"Creates S3 object class representing OAuth token returned access token endpoint.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_token.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Create an OAuth token — oauth_token","text":"","code":"oauth_token( access_token, token_type = \"bearer\", expires_in = NULL, refresh_token = NULL, ..., .date = Sys.time() )"},{"path":"https://httr2.r-lib.org/dev/reference/oauth_token.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Create an OAuth token — oauth_token","text":"access_token access token used authenticate request token_type Type token; \"bearer\" currently supported. expires_in Number seconds token expires. refresh_token Optional refresh token; supplied, can used cheaply get new access token one expires. ... Additional components returned endpoint .date Date request made; used convert relative expires_in absolute expires_at.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_token.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Create an OAuth token — oauth_token","text":"OAuth token: S3 list class httr2_token.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/oauth_token.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Create an OAuth token — oauth_token","text":"","code":"oauth_token(\"abcdef\") #> #> token_type: bearer #> access_token: oauth_token(\"abcdef\", expires_in = 3600) #> #> token_type: bearer #> access_token: #> expires_at: 2024-10-23 19:13:28 oauth_token(\"abcdef\", refresh_token = \"ghijkl\") #> #> token_type: bearer #> access_token: #> refresh_token: "},{"path":"https://httr2.r-lib.org/dev/reference/oauth_token_cached.html","id":null,"dir":"Reference","previous_headings":"","what":"Retrieve an OAuth token using the cache — oauth_token_cached","title":"Retrieve an OAuth token using the cache — oauth_token_cached","text":"function wraps around oauth_flow_ function retrieve token cache, generate cache token needed. Use manual token management still takes advantage httr2's caching system. need use function passing token","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_token_cached.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Retrieve an OAuth token using the cache — oauth_token_cached","text":"","code":"oauth_token_cached( client, flow, flow_params = list(), cache_disk = FALSE, cache_key = NULL, reauth = FALSE )"},{"path":"https://httr2.r-lib.org/dev/reference/oauth_token_cached.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Retrieve an OAuth token using the cache — oauth_token_cached","text":"client oauth_client(). flow oauth_flow_ function used generate access token. flow_params Parameters flow. named list whose names match argument names flow. cache_disk access token cached disk? reduces number times need re-authenticate cost storing access credentials disk. Learn https://httr2.r-lib.org/articles/oauth.html. cache_key want cache multiple tokens per app, use key disambiguate . reauth Set TRUE force re-authentication via flow, regardless whether token expired.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_token_cached.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Retrieve an OAuth token using the cache — oauth_token_cached","text":"","code":"if (FALSE) { # \\dontrun{ token <- oauth_token_cached( client = example_github_client(), flow = oauth_flow_auth_code, flow_params = list( auth_url = \"https://github.com/login/oauth/authorize\" ), cache_disk = TRUE ) token } # }"},{"path":"https://httr2.r-lib.org/dev/reference/obfuscate.html","id":null,"dir":"Reference","previous_headings":"","what":"Obfuscate mildly secret information — obfuscate","title":"Obfuscate mildly secret information — obfuscate","text":"Use obfuscate(\"value\") generate call obfuscated(), unobfuscate value last possible moment. Obfuscated values work limited locations: secret argument oauth_client() Elements data argument req_body_form(), req_body_json(), req_body_multipart(). Working together pair functions provides way obfuscate mildly confidential information, like OAuth client secrets. secret can revealed inspecting source code, skilled R programmer figure effort. main goal protect scraping; way automated tool grab obfuscated secrets.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/obfuscate.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Obfuscate mildly secret information — obfuscate","text":"","code":"obfuscate(x) obfuscated(x)"},{"path":"https://httr2.r-lib.org/dev/reference/obfuscate.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Obfuscate mildly secret information — obfuscate","text":"x string obfuscate, mark obfuscated.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/obfuscate.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Obfuscate mildly secret information — obfuscate","text":"obfuscate() prints obfuscated() call include code. obfuscated() returns S3 class marking string obfuscated can unobfuscated needed.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/obfuscate.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Obfuscate mildly secret information — obfuscate","text":"","code":"obfuscate(\"good morning\") #> obfuscated(\"aX256ciizh3YeXZx-3DE1sNtXXYk35jLAHKJew\") # Every time you obfuscate you'll get a different value because it # includes 16 bytes of random data which protects against certain types of # brute force attack obfuscate(\"good morning\") #> obfuscated(\"wxc9Ekc98yJRBjovnFOCmmS6om3gAbkInz6d_w\")"},{"path":"https://httr2.r-lib.org/dev/reference/pipe.html","id":null,"dir":"Reference","previous_headings":"","what":"Pipe operator — %>%","title":"Pipe operator — %>%","text":"See magrittr::%>% details.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/pipe.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Pipe operator — %>%","text":"","code":"lhs %>% rhs"},{"path":"https://httr2.r-lib.org/dev/reference/pipe.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Pipe operator — %>%","text":"lhs value magrittr placeholder. rhs function call using magrittr semantics.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/pipe.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Pipe operator — %>%","text":"result calling rhs(lhs).","code":""},{"path":"https://httr2.r-lib.org/dev/reference/progress_bars.html","id":null,"dir":"Reference","previous_headings":"","what":"Progress bars in httr2 — progress_bars","title":"Progress bars in httr2 — progress_bars","text":"httr2's perform functions progress argument can use create progress bar. progress can : FALSE, default: create progress bar. TRUE: creates basic unnamed progress bar. string: creates basic progress bar given name. named list progress bar parameters, described . good practice name progress bars, make clear calculation process belong . recommend keeping names 20 characters, whole progress bar fits comfortably even narrower displays.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/progress_bars.html","id":"progress-bar-parameters","dir":"Reference","previous_headings":"","what":"Progress bar parameters","title":"Progress bars in httr2 — progress_bars","text":"clear: whether remove progress bar screen termination. Defaults TRUE. format: format string. overrides default format string progress bar type. must given custom type. Format strings may contain R expressions evaluate braces. support cli pluralization, styling can contain special progress variables. format_done: format string successful termination. default format. format_failed: format string unsuccessful termination. default format. name: progress bar name. default empty string displayed beginning progress bar. show_after: numeric scalar. show progress bar number seconds. overrides cli.progress_show_after global option. type: progress bar type. Currently supported types : iterator: default, loop mapping function, tasks: (typically small) number tasks, download: download one file, custom: custom type, format must NULL type. default display different progress bar type.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/progress_bars.html","id":"further-documentation","dir":"Reference","previous_headings":"","what":"Further documentation","title":"Progress bars in httr2 — progress_bars","text":"purrr's progress bars powered cli, see Introduction progress bars cli Advanced cli progress bars details.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_aws_v4.html","id":null,"dir":"Reference","previous_headings":"","what":"Sign a request with the AWS SigV4 signing protocol — req_auth_aws_v4","title":"Sign a request with the AWS SigV4 signing protocol — req_auth_aws_v4","text":"custom auth protocol implemented AWS.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_aws_v4.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Sign a request with the AWS SigV4 signing protocol — req_auth_aws_v4","text":"","code":"req_auth_aws_v4( req, aws_access_key_id, aws_secret_access_key, aws_session_token = NULL, aws_service = NULL, aws_region = NULL )"},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_aws_v4.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Sign a request with the AWS SigV4 signing protocol — req_auth_aws_v4","text":"req httr2 request object. aws_access_key_id, aws_secret_access_key AWS key secret. aws_session_token AWS session token, required. aws_service, aws_region AWS service region use request. supplied, automatically parsed URL hostname.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_aws_v4.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Sign a request with the AWS SigV4 signing protocol — req_auth_aws_v4","text":"","code":"if (FALSE) { # httr2:::has_paws_credentials() creds <- paws.common::locate_credentials() model_id <- \"anthropic.claude-3-5-sonnet-20240620-v1:0\" req <- request(\"https://bedrock-runtime.us-east-1.amazonaws.com\") # https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_Converse.html req <- req_url_path_append(req, \"model\", model_id, \"converse\") req <- req_body_json(req, list( messages = list(list( role = \"user\", content = list(list(text = \"What's your name?\")) )) )) req <- req_auth_aws_v4( req, aws_access_key_id = creds$access_key_id, aws_secret_access_key = creds$secret_access_key, aws_session_token = creds$session_token ) resp <- req_perform_connection(req) str(resp_body_json(resp)) }"},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_basic.html","id":null,"dir":"Reference","previous_headings":"","what":"Authenticate request with HTTP basic authentication — req_auth_basic","title":"Authenticate request with HTTP basic authentication — req_auth_basic","text":"sets Authorization header. See details https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_basic.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Authenticate request with HTTP basic authentication — req_auth_basic","text":"","code":"req_auth_basic(req, username, password = NULL)"},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_basic.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Authenticate request with HTTP basic authentication — req_auth_basic","text":"req httr2 request object. username User name. password Password. avoid entering password directly calling function captured .Rhistory. Instead, leave unset default behaviour prompt interactively.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_basic.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Authenticate request with HTTP basic authentication — req_auth_basic","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_basic.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Authenticate request with HTTP basic authentication — req_auth_basic","text":"","code":"req <- request(\"http://example.com\") |> req_auth_basic(\"hadley\", \"SECRET\") req #> #> GET http://example.com #> Headers: #> • Authorization: '' #> Body: empty req |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Authorization: #> # httr2 does its best to redact the Authorization header so that you don't # accidentally reveal confidential data. Use `redact_headers` to reveal it: print(req, redact_headers = FALSE) #> #> GET http://example.com #> Headers: #> • Authorization: 'Basic aGFkbGV5OlNFQ1JFVA==' #> Body: empty req |> req_dry_run(redact_headers = FALSE) #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Authorization: Basic aGFkbGV5OlNFQ1JFVA== #> # We do this because the authorization header is not encrypted and the # so password can easily be discovered: rawToChar(jsonlite::base64_dec(\"aGFkbGV5OlNFQ1JFVA==\")) #> [1] \"hadley:SECRET\""},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_bearer_token.html","id":null,"dir":"Reference","previous_headings":"","what":"Authenticate request with bearer token — req_auth_bearer_token","title":"Authenticate request with bearer token — req_auth_bearer_token","text":"bearer token gives bearer access confidential resources (keep secure like user name password). usually produced large authentication scheme (like various OAuth 2.0 flows), sometimes given directly.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_bearer_token.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Authenticate request with bearer token — req_auth_bearer_token","text":"","code":"req_auth_bearer_token(req, token)"},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_bearer_token.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Authenticate request with bearer token — req_auth_bearer_token","text":"req httr2 request object. token bearer token","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_bearer_token.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Authenticate request with bearer token — req_auth_bearer_token","text":"modified HTTP request.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_bearer_token.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Authenticate request with bearer token — req_auth_bearer_token","text":"","code":"req <- request(\"http://example.com\") |> req_auth_bearer_token(\"sdaljsdf093lkfs\") req #> #> GET http://example.com #> Headers: #> • Authorization: '' #> Body: empty # httr2 does its best to redact the Authorization header so that you don't # accidentally reveal confidential data. Use `redact_headers` to reveal it: print(req, redact_headers = FALSE) #> #> GET http://example.com #> Headers: #> • Authorization: 'Bearer sdaljsdf093lkfs' #> Body: empty"},{"path":"https://httr2.r-lib.org/dev/reference/req_body.html","id":null,"dir":"Reference","previous_headings":"","what":"Send data in request body — req_body","title":"Send data in request body — req_body","text":"req_body_file() sends local file. req_body_raw() sends string raw vector. req_body_json() sends JSON encoded data. Named components data can later modified req_body_json_modify(). req_body_form() sends form encoded data. req_body_multipart() creates multi-part body. Adding body request automatically switch method POST.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_body.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Send data in request body — req_body","text":"","code":"req_body_raw(req, body, type = NULL) req_body_file(req, path, type = NULL) req_body_json( req, data, auto_unbox = TRUE, digits = 22, null = \"null\", type = \"application/json\", ... ) req_body_json_modify(req, ...) req_body_form(.req, ..., .multi = c(\"error\", \"comma\", \"pipe\", \"explode\")) req_body_multipart(.req, ...)"},{"path":"https://httr2.r-lib.org/dev/reference/req_body.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Send data in request body — req_body","text":"req, .req httr2 request object. body literal string raw vector send body. type MIME content type. ignored manually set Content-Type header. path Path file upload. data Data include body. auto_unbox length-1 vectors automatically \"unboxed\" JSON scalars? digits many digits precision numbers use JSON? null NULL translated JSON's null (\"null\") empty list (\"list\"). ... Name-data pairs used send data body. req_body_form(), values must strings (things easily coerced strings); req_body_multipart() values must strings objects produced curl::form_file()/curl::form_data(). req_body_json_modify(), simple data made atomic vectors lists. req_body_json() uses argument differently; takes additional arguments passed jsonlite::toJSON(). .multi Controls happens element ... vector containing multiple values: \"error\", default, throws error. \"comma\", separates values ,, e.g. ?x=1,2. \"pipe\", separates values |, e.g. ?x=1|2. \"explode\", turns element parameter, e.g. ?x=1&x=2. none functions work, can alternatively supply function takes character vector returns string.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_body.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Send data in request body — req_body","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_body.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Send data in request body — req_body","text":"","code":"req <- request(example_url()) |> req_url_path(\"/post\") # Most APIs expect small amounts of data in either form or json encoded: req |> req_body_form(x = \"A simple text string\") |> req_dry_run() #> POST /post HTTP/1.1 #> Host: 127.0.0.1:34151 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Content-Type: application/x-www-form-urlencoded #> Content-Length: 28 #> #> x=A%20simple%20text%20string req |> req_body_json(list(x = \"A simple text string\")) |> req_dry_run() #> POST /post HTTP/1.1 #> Host: 127.0.0.1:34151 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Content-Type: application/json #> Content-Length: 28 #> #> {\"x\":\"A simple text string\"} # For total control over the body, send a string or raw vector req |> req_body_raw(\"A simple text string\") |> req_dry_run() #> POST /post HTTP/1.1 #> Host: 127.0.0.1:34151 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Content-Length: 20 #> #> A simple text string # There are two main ways that APIs expect entire files path <- tempfile() writeLines(letters[1:6], path) # You can send a single file as the body: req |> req_body_file(path) |> req_dry_run() #> POST /post HTTP/1.1 #> Host: 127.0.0.1:34151 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Content-Length: 12 #> #> a #> b #> c #> d #> e #> f # You can send multiple files, or a mix of files and data # with multipart encoding req |> req_body_multipart(a = curl::form_file(path), b = \"some data\") |> req_dry_run() #> POST /post HTTP/1.1 #> Host: 127.0.0.1:34151 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Content-Length: 316 #> Content-Type: multipart/form-data; boundary=------------------------1805e5a43150490a #> #> --------------------------1805e5a43150490a #> Content-Disposition: form-data; name=\"a\"; filename=\"file16e24ec9a003\" #> Content-Type: application/octet-stream #> #> a #> b #> c #> d #> e #> f #> #> --------------------------1805e5a43150490a #> Content-Disposition: form-data; name=\"b\" #> #> some data #> --------------------------1805e5a43150490a--"},{"path":"https://httr2.r-lib.org/dev/reference/req_cache.html","id":null,"dir":"Reference","previous_headings":"","what":"Automatically cache requests — req_cache","title":"Automatically cache requests — req_cache","text":"Use req_perform() automatically cache HTTP requests. API requests cacheable, static files often . req_cache() caches responses GET requests status code 200 least one standard caching headers (e.g. Expires, Etag, Last-Modified, Cache-Control), unless caching expressly prohibited Cache-Control: -store. Typically, request still sent server check cached value still --date, need re-download body value. learn HTTP caching, recommend MDN article HTTP caching.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_cache.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Automatically cache requests — req_cache","text":"","code":"req_cache( req, path, use_on_error = FALSE, debug = getOption(\"httr2_cache_debug\", FALSE), max_age = Inf, max_n = Inf, max_size = 1024^3 )"},{"path":"https://httr2.r-lib.org/dev/reference/req_cache.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Automatically cache requests — req_cache","text":"req httr2 request object. path Path cache directory. created automatically exist. quick easy caching within session, can use tempfile(). cache requests within package, can use something like file.path(tools::R_user_dir(\"pkgdown\", \"cache\"), \"httr2\"). httr2 provide helpers manage cache, want empty , can use something like unlink(dir(cache_path, full.names = TRUE)). use_on_error request errors, cache response, req_perform() return instead generating error? debug TRUE emit useful messages telling cache hits misses. can helpful understand whether caching actually anything use case. max_n, max_age, max_size Automatically prune cache specifying one : max_age: delete files older number seconds. max_n: delete files (oldest newest) preserve many files. max_size: delete files (oldest newest) preserve many bytes. cache pruning performed per minute.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_cache.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Automatically cache requests — req_cache","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_cache.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Automatically cache requests — req_cache","text":"","code":"# GitHub uses HTTP caching for all raw files. url <- paste0( \"https://raw.githubusercontent.com/allisonhorst/palmerpenguins/\", \"master/inst/extdata/penguins.csv\" ) # Here I set debug = TRUE so you can see what's happening req <- request(url) |> req_cache(tempdir(), debug = TRUE) # First request downloads the data resp <- req |> req_perform() #> Pruning cache #> Saving response to cache \"d5d1ddd7f99f55dbc920c63f942804c0\" # Second request retrieves it from the cache resp <- req |> req_perform() #> Found url in cache \"d5d1ddd7f99f55dbc920c63f942804c0\" #> Cached value is fresh; using response from cache"},{"path":"https://httr2.r-lib.org/dev/reference/req_cookie_preserve.html","id":null,"dir":"Reference","previous_headings":"","what":"Set and preserve cookies — req_cookie_preserve","title":"Set and preserve cookies — req_cookie_preserve","text":"Use req_cookie_set() set client side cookies sent server. default, httr2 uses clean slate every request meaning cookies automatically preserved across requests. preserve cookies, use req_cookie_preserve() along path cookie file read updated request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_cookie_preserve.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Set and preserve cookies — req_cookie_preserve","text":"","code":"req_cookie_preserve(req, path) req_cookies_set(req, ...)"},{"path":"https://httr2.r-lib.org/dev/reference/req_cookie_preserve.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Set and preserve cookies — req_cookie_preserve","text":"req httr2 request object. path path file cookies read updated request. ... Name-value pairs define query parameters. value must atomic vector, automatically escaped. opt-escaping, wrap strings ().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_cookie_preserve.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Set and preserve cookies — req_cookie_preserve","text":"","code":"# Use `req_cookies_set()` to set client-side cookies request(example_url()) |> req_cookies_set(a = 1, b = 1) |> req_dry_run() #> GET / HTTP/1.1 #> Host: 127.0.0.1:34151 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Cookie: a=1;b=1 #> # Use `req_cookie_preserve()` to preserve server-side cookies across requests path <- tempfile() # Set a server-side cookie request(example_url()) |> req_cookie_preserve(path) |> req_template(\"/cookies/set/:name/:value\", name = \"chocolate\", value = \"chip\") |> req_perform() |> resp_body_json() #> $cookies #> $cookies$chocolate #> [1] \"chip\" #> #> # Set another sever-side cookie request(example_url()) |> req_cookie_preserve(path) |> req_template(\"/cookies/set/:name/:value\", name = \"oatmeal\", value = \"raisin\") |> req_perform() |> resp_body_json() #> $cookies #> $cookies$chocolate #> [1] \"chip\" #> #> $cookies$oatmeal #> [1] \"raisin\" #> #> # Add a client side cookie request(example_url()) |> req_url_path(\"/cookies/set\") |> req_cookie_preserve(path) |> req_cookies_set(snicker = \"doodle\") |> req_perform() |> resp_body_json() #> $cookies #> $cookies$chocolate #> [1] \"chip\" #> #> $cookies$oatmeal #> [1] \"raisin\" #> #> $cookies$snicker #> [1] \"doodle\" #> #> # The cookie path has a straightforward format cat(readChar(path, nchars = 1e4)) #> # Netscape HTTP Cookie File #> # https://curl.se/docs/http-cookies.html #> # This file was generated by libcurl! Edit at your own risk. #> #> 127.0.0.1\tFALSE\t/\tFALSE\t0\tchocolate\tchip #> 127.0.0.1\tFALSE\t/\tFALSE\t0\toatmeal\traisin"},{"path":"https://httr2.r-lib.org/dev/reference/req_dry_run.html","id":null,"dir":"Reference","previous_headings":"","what":"Perform a dry run — req_dry_run","title":"Perform a dry run — req_dry_run","text":"shows exactly httr2 send server, without actually sending anything. requires httpuv package works sending real HTTP request local webserver, thanks magic curl::curl_echo().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_dry_run.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Perform a dry run — req_dry_run","text":"","code":"req_dry_run(req, quiet = FALSE, redact_headers = TRUE)"},{"path":"https://httr2.r-lib.org/dev/reference/req_dry_run.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Perform a dry run — req_dry_run","text":"req httr2 request object. quiet TRUE print anything. redact_headers Redact confidential data headers? Currently redacts contents Authorization header prevent accidentally leaking credentials debugging/reprexing.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_dry_run.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Perform a dry run — req_dry_run","text":"Invisibly, list containing information request, including method, path, headers.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_dry_run.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Perform a dry run — req_dry_run","text":"","code":"# httr2 adds default User-Agent, Accept, and Accept-Encoding headers request(\"http://example.com\") |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> # the Authorization header is automatically redacted to avoid leaking # credentials on the console req <- request(\"http://example.com\") |> req_auth_basic(\"user\", \"password\") req |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Authorization: #> # if you need to see it, use redact_headers = FALSE req |> req_dry_run(redact_headers = FALSE) #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Authorization: Basic dXNlcjpwYXNzd29yZA== #>"},{"path":"https://httr2.r-lib.org/dev/reference/req_error.html","id":null,"dir":"Reference","previous_headings":"","what":"Control handling of HTTP errors — req_error","title":"Control handling of HTTP errors — req_error","text":"req_perform() automatically convert HTTP errors (.e. 4xx 5xx status code) R errors. Use req_error() either override defaults, extract additional information response useful expose user.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_error.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Control handling of HTTP errors — req_error","text":"","code":"req_error(req, is_error = NULL, body = NULL)"},{"path":"https://httr2.r-lib.org/dev/reference/req_error.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Control handling of HTTP errors — req_error","text":"req httr2 request object. is_error predicate function takes single argument (response) returns TRUE FALSE indicating whether R error signalled. body callback function takes single argument (response) returns character vector additional information include body error. vector passed along message argument rlang::abort() can use formatting supports.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_error.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Control handling of HTTP errors — req_error","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_error.html","id":"error-handling","dir":"Reference","previous_headings":"","what":"Error handling","title":"Control handling of HTTP errors — req_error","text":"req_perform() designed succeed get valid HTTP response. two ways request can fail: HTTP request might fail, example connection dropped server exist. type error class c(\"httr2_failure\", \"httr2_error\"). HTTP request might succeed, return HTTP status code represents error, e.g. 404 Found specified resource found. type error (e.g.) class c(\"httr2_http_404\", \"httr2_http\", \"httr2_error\"). error classes designed used conjunction R's condition handling tools (https://adv-r.hadley.nz/conditions.html). example, want return default value server returns 404, use tryCatch(): want re-throw error additional context, use withCallingHandlers(), e.g.: Learn error chaining rlang::topic-error-chaining.","code":"tryCatch( req |> req_perform() |> resp_body_json(), httr2_http_404 = function(cnd) NULL ) withCallingHandlers( req |> req_perform() |> resp_body_json(), httr2_http_404 = function(cnd) { rlang::abort(\"Couldn't find user\", parent = cnd) } )"},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_error.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Control handling of HTTP errors — req_error","text":"","code":"# Performing this request usually generates an error because httr2 # converts HTTP errors into R errors: req <- request(example_url()) |> req_url_path(\"/status/404\") try(req |> req_perform()) #> Error in req_perform(req) : HTTP 404 Not Found. # You can still retrieve it with last_response() last_response() #> #> GET http://127.0.0.1:34151/status/404 #> Status: 404 Not Found #> Content-Type: text/plain #> Body: None # But you might want to suppress this behaviour: resp <- req |> req_error(is_error = \\(resp) FALSE) |> req_perform() resp #> #> GET http://127.0.0.1:34151/status/404 #> Status: 404 Not Found #> Content-Type: text/plain #> Body: None # Or perhaps you're working with a server that routinely uses the # wrong HTTP error codes only 500s are really errors request(\"http://example.com\") |> req_error(is_error = \\(resp) resp_status(resp) == 500) #> #> GET http://example.com #> Body: empty #> Policies: #> • error_is_error: a function # Most typically you'll use req_error() to add additional information # extracted from the response body (or sometimes header): error_body <- function(resp) { resp_body_json(resp)$error } request(\"http://example.com\") |> req_error(body = error_body) #> #> GET http://example.com #> Body: empty #> Policies: #> • error_body: a function # Learn more in https://httr2.r-lib.org/articles/wrapping-apis.html"},{"path":"https://httr2.r-lib.org/dev/reference/req_headers.html","id":null,"dir":"Reference","previous_headings":"","what":"Modify request headers — req_headers","title":"Modify request headers — req_headers","text":"req_headers() allows set value header.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_headers.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Modify request headers — req_headers","text":"","code":"req_headers(.req, ..., .redact = NULL)"},{"path":"https://httr2.r-lib.org/dev/reference/req_headers.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Modify request headers — req_headers","text":".req request. ... Name-value pairs headers values. Use NULL reset value httr2's default Use \"\" remove header Use character vector repeat header. .redact Headers redact. NULL, default, added headers redacted.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_headers.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Modify request headers — req_headers","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_headers.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Modify request headers — req_headers","text":"","code":"req <- request(\"http://example.com\") # Use req_headers() to add arbitrary additional headers to the request req |> req_headers(MyHeader = \"MyValue\") |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> MyHeader: MyValue #> # Repeated use overrides the previous value: req |> req_headers(MyHeader = \"Old value\") |> req_headers(MyHeader = \"New value\") |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> MyHeader: New value #> # Setting Accept to NULL uses curl's default: req |> req_headers(Accept = NULL) |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> # Setting it to \"\" removes it: req |> req_headers(Accept = \"\") |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept-Encoding: deflate, gzip, br, zstd #> # If you need to repeat a header, provide a vector of values # (this is rarely needed, but is important in a handful of cases) req |> req_headers(HeaderName = c(\"Value 1\", \"Value 2\", \"Value 3\")) |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> HeaderName: Value 1 #> HeaderName: Value 2 #> HeaderName: Value 3 #> # If you have headers in a list, use !!! headers <- list(HeaderOne = \"one\", HeaderTwo = \"two\") req |> req_headers(!!!headers, HeaderThree = \"three\") |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> HeaderOne: one #> HeaderTwo: two #> HeaderThree: three #> # Use `.redact` to hide a header in the output req |> req_headers(Secret = \"this-is-private\", Public = \"but-this-is-not\", .redact = \"Secret\") |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Secret: #> Public: but-this-is-not #>"},{"path":"https://httr2.r-lib.org/dev/reference/req_method.html","id":null,"dir":"Reference","previous_headings":"","what":"Set HTTP method in request — req_method","title":"Set HTTP method in request — req_method","text":"Use function use custom HTTP method like HEAD, DELETE, PATCH, UPDATE, OPTIONS. default method GET requests without body, POST requests body.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_method.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Set HTTP method in request — req_method","text":"","code":"req_method(req, method)"},{"path":"https://httr2.r-lib.org/dev/reference/req_method.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Set HTTP method in request — req_method","text":"req httr2 request object. method Custom HTTP method","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_method.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Set HTTP method in request — req_method","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_method.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Set HTTP method in request — req_method","text":"","code":"request(example_url()) |> req_method(\"PATCH\") #> #> PATCH http://127.0.0.1:34151/ #> Body: empty request(example_url()) |> req_method(\"PUT\") #> #> PUT http://127.0.0.1:34151/ #> Body: empty request(example_url()) |> req_method(\"HEAD\") #> #> HEAD http://127.0.0.1:34151/ #> Body: empty"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth.html","id":null,"dir":"Reference","previous_headings":"","what":"OAuth authentication — req_oauth","title":"OAuth authentication — req_oauth","text":"low-level helper automatically authenticating request OAuth flow, caching access token refreshing possible. need use function implementing OAuth flow.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"OAuth authentication — req_oauth","text":"","code":"req_oauth(req, flow, flow_params, cache)"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"OAuth authentication — req_oauth","text":"req httr2 request object. flow oauth_flow_ function used generate access token. flow_params Parameters flow. named list whose names match argument names flow. cache object controls token cached. list containing three functions: get() retrieves token cache, returning NULL cached yet. set() saves token cache. clear() removes token cache","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"OAuth authentication — req_oauth","text":"oauth_token.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_auth_code.html","id":null,"dir":"Reference","previous_headings":"","what":"OAuth with authorization code — req_oauth_auth_code","title":"OAuth with authorization code — req_oauth_auth_code","text":"Authenticate using OAuth authorization code flow, defined Section 4.1 RFC 6749. flow commonly used OAuth flow user opens page browser, approves access, returns R. possible, redirects browser back temporary local webserver capture authorization code. possible (e.g. running hosted platform like RStudio Server), provide custom redirect_uri httr2 prompt user enter code manually. Learn overall OAuth authentication flow https://httr2.r-lib.org/articles/oauth.html.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_auth_code.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"OAuth with authorization code — req_oauth_auth_code","text":"","code":"req_oauth_auth_code( req, client, auth_url, scope = NULL, pkce = TRUE, auth_params = list(), token_params = list(), redirect_uri = oauth_redirect_uri(), cache_disk = FALSE, cache_key = NULL, host_name = deprecated(), host_ip = deprecated(), port = deprecated() ) oauth_flow_auth_code( client, auth_url, scope = NULL, pkce = TRUE, auth_params = list(), token_params = list(), redirect_uri = oauth_redirect_uri(), host_name = deprecated(), host_ip = deprecated(), port = deprecated() )"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_auth_code.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"OAuth with authorization code — req_oauth_auth_code","text":"req httr2 request object. client oauth_client(). auth_url Authorization url; need discover reading documentation. scope Scopes requested resource owner. pkce Use \"Proof Key Code Exchange\"? adds extra layer security always used supported server. auth_params list containing additional parameters passed oauth_flow_auth_code_url(). token_params List containing additional parameters passed token_url. redirect_uri URL redirect back authorization complete. Often must registered API advance. httr2 supports three forms redirect. Firstly, can use localhost url (default), httr2 set temporary webserver listen OAuth redirect. case, httr2 automatically append random port. need set fixed port API requires , specify (e.g.) \"http://localhost:1011\". technique works well working computer. Secondly, can provide URL website uses Javascript give user code copy paste back R session (see https://www.tidyverse.org/google-callback/ https://github.com/r-lib/gargle/blob/main/inst/pseudo-oob/google-callback/index.html examples). less convenient (requires user interaction) also works hosted environments like RStudio Server. Finally, hosted platforms might set HTTR2_OAUTH_REDIRECT_URL HTTR2_OAUTH_CODE_SOURCE_URL environment variables. case, httr2 use HTTR2_OAUTH_REDIRECT_URL redirects default, poll HTTR2_OAUTH_CODE_SOURCE_URL endpoint state parameter receives code response (encounters error). delegates completion authorization flow hosted platform. cache_disk access token cached disk? reduces number times need re-authenticate cost storing access credentials disk. Learn https://httr2.r-lib.org/articles/oauth.html. cache_key want cache multiple tokens per app, use key disambiguate . host_name, host_ip, port Now use redirect_uri instead.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_auth_code.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"OAuth with authorization code — req_oauth_auth_code","text":"req_oauth_auth_code() returns modified HTTP request use OAuth; oauth_flow_auth_code() returns oauth_token.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_auth_code.html","id":"security-considerations","dir":"Reference","previous_headings":"","what":"Security considerations","title":"OAuth with authorization code — req_oauth_auth_code","text":"authorization code flow used web applications native applications (equivalent R packages). RFC 8252 spells important considerations native apps. importantly way native apps keep secrets users. means server either require client_secret (.e. public client confidential client) ensure possession client_secret bestow meaningful rights. modern APIs bigger players (Azure, Google, etc) explicitly native apps. However, cases, even older APIs, possessing client_secret gives ability anything harmful, general principle fine include R package, long mildly obfuscated protect credential scraping. incentive steal client credentials takes less time create new client find client secret.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_auth_code.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"OAuth with authorization code — req_oauth_auth_code","text":"","code":"req_auth_github <- function(req) { req_oauth_auth_code( req, client = example_github_client(), auth_url = \"https://github.com/login/oauth/authorize\" ) } request(\"https://api.github.com/user\") |> req_auth_github() #> #> GET https://api.github.com/user #> Body: empty #> Policies: #> • auth_sign: a list #> • auth_oauth: TRUE"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_bearer_jwt.html","id":null,"dir":"Reference","previous_headings":"","what":"OAuth with a bearer JWT (JSON web token) — req_oauth_bearer_jwt","title":"OAuth with a bearer JWT (JSON web token) — req_oauth_bearer_jwt","text":"Authenticate using Bearer JWT (JSON web token) authorization grant get access token, defined Section 2.1 RFC 7523. often used service accounts, accounts used primarily automated environments. Learn overall OAuth authentication flow https://httr2.r-lib.org/articles/oauth.html.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_bearer_jwt.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"OAuth with a bearer JWT (JSON web token) — req_oauth_bearer_jwt","text":"","code":"req_oauth_bearer_jwt( req, client, claim, signature = \"jwt_encode_sig\", signature_params = list(), scope = NULL, token_params = list() ) oauth_flow_bearer_jwt( client, claim, signature = \"jwt_encode_sig\", signature_params = list(), scope = NULL, token_params = list() )"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_bearer_jwt.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"OAuth with a bearer JWT (JSON web token) — req_oauth_bearer_jwt","text":"req httr2 request object. client oauth_client(). claim list claims. elements claim set static apart iat, nbf, exp, jti, provide list jwt_claim() automatically fill dynamic components. components need vary, can instead provide zero-argument callback function call jwt_claim(). signature Function use sign claim, e.g. jwt_encode_sig(). signature_params Additional arguments passed signature, e.g. size, header. scope Scopes requested resource owner. token_params List containing additional parameters passed token_url.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_bearer_jwt.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"OAuth with a bearer JWT (JSON web token) — req_oauth_bearer_jwt","text":"req_oauth_bearer_jwt() returns modified HTTP request use OAuth; oauth_flow_bearer_jwt() returns oauth_token.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_bearer_jwt.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"OAuth with a bearer JWT (JSON web token) — req_oauth_bearer_jwt","text":"","code":"req_auth <- function(req) { req_oauth_bearer_jwt( req, client = oauth_client(\"example\", \"https://example.com/get_token\"), claim = jwt_claim() ) } request(\"https://example.com\") |> req_auth() #> #> GET https://example.com #> Body: empty #> Policies: #> • auth_sign: a list #> • auth_oauth: TRUE"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_client_credentials.html","id":null,"dir":"Reference","previous_headings":"","what":"OAuth with client credentials — req_oauth_client_credentials","title":"OAuth with client credentials — req_oauth_client_credentials","text":"Authenticate using OAuth client credentials flow, defined Section 4.4 RFC 6749. used allow client access resources controls directly, behalf user. Learn overall OAuth authentication flow https://httr2.r-lib.org/articles/oauth.html.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_client_credentials.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"OAuth with client credentials — req_oauth_client_credentials","text":"","code":"req_oauth_client_credentials(req, client, scope = NULL, token_params = list()) oauth_flow_client_credentials(client, scope = NULL, token_params = list())"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_client_credentials.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"OAuth with client credentials — req_oauth_client_credentials","text":"req httr2 request object. client oauth_client(). scope Scopes requested resource owner. token_params List containing additional parameters passed token_url.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_client_credentials.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"OAuth with client credentials — req_oauth_client_credentials","text":"req_oauth_client_credentials() returns modified HTTP request use OAuth; oauth_flow_client_credentials() returns oauth_token.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_client_credentials.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"OAuth with client credentials — req_oauth_client_credentials","text":"","code":"req_auth <- function(req) { req_oauth_client_credentials( req, client = oauth_client(\"example\", \"https://example.com/get_token\") ) } request(\"https://example.com\") |> req_auth() #> #> GET https://example.com #> Body: empty #> Policies: #> • auth_sign: a list #> • auth_oauth: TRUE"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_device.html","id":null,"dir":"Reference","previous_headings":"","what":"OAuth with device flow — req_oauth_device","title":"OAuth with device flow — req_oauth_device","text":"Authenticate using OAuth device flow, defined RFC 8628. designed devices access web browser (ever authenticated app TV, probably flow used), also works well within R. Learn overall OAuth authentication flow https://httr2.r-lib.org/articles/oauth.html.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_device.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"OAuth with device flow — req_oauth_device","text":"","code":"req_oauth_device( req, client, auth_url, scope = NULL, auth_params = list(), token_params = list(), cache_disk = FALSE, cache_key = NULL ) oauth_flow_device( client, auth_url, pkce = FALSE, scope = NULL, auth_params = list(), token_params = list() )"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_device.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"OAuth with device flow — req_oauth_device","text":"req httr2 request object. client oauth_client(). auth_url Authorization url; need discover reading documentation. scope Scopes requested resource owner. auth_params list containing additional parameters passed oauth_flow_auth_code_url(). token_params List containing additional parameters passed token_url. cache_disk access token cached disk? reduces number times need re-authenticate cost storing access credentials disk. Learn https://httr2.r-lib.org/articles/oauth.html. cache_key want cache multiple tokens per app, use key disambiguate . pkce Use \"Proof Key Code Exchange\"? adds extra layer security always used supported server.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_device.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"OAuth with device flow — req_oauth_device","text":"req_oauth_device() returns modified HTTP request use OAuth; oauth_flow_device() returns oauth_token.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_device.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"OAuth with device flow — req_oauth_device","text":"","code":"req_auth_github <- function(req) { req_oauth_device( req, client = example_github_client(), auth_url = \"https://github.com/login/device/code\" ) } request(\"https://api.github.com/user\") |> req_auth_github() #> #> GET https://api.github.com/user #> Body: empty #> Policies: #> • auth_sign: a list #> • auth_oauth: TRUE"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_password.html","id":null,"dir":"Reference","previous_headings":"","what":"OAuth with username and password — req_oauth_password","title":"OAuth with username and password — req_oauth_password","text":"function implements OAuth resource owner password flow, defined Section 4.3 RFC 6749. allows user supply password , exchanging access token can cached locally. Learn overall OAuth authentication flow https://httr2.r-lib.org/articles/oauth.html","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_password.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"OAuth with username and password — req_oauth_password","text":"","code":"req_oauth_password( req, client, username, password = NULL, scope = NULL, token_params = list(), cache_disk = FALSE, cache_key = username ) oauth_flow_password( client, username, password = NULL, scope = NULL, token_params = list() )"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_password.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"OAuth with username and password — req_oauth_password","text":"req httr2 request object. client oauth_client(). username User name. password Password. avoid entering password directly calling function captured .Rhistory. Instead, leave unset default behaviour prompt interactively. scope Scopes requested resource owner. token_params List containing additional parameters passed token_url. cache_disk access token cached disk? reduces number times need re-authenticate cost storing access credentials disk. Learn https://httr2.r-lib.org/articles/oauth.html. cache_key want cache multiple tokens per app, use key disambiguate .","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_password.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"OAuth with username and password — req_oauth_password","text":"req_oauth_password() returns modified HTTP request use OAuth; oauth_flow_password() returns oauth_token.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_password.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"OAuth with username and password — req_oauth_password","text":"","code":"req_auth <- function(req) { req_oauth_password(req, client = oauth_client(\"example\", \"https://example.com/get_token\"), username = \"username\" ) } if (interactive()) { request(\"https://example.com\") |> req_auth() }"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_refresh.html","id":null,"dir":"Reference","previous_headings":"","what":"OAuth with a refresh token — req_oauth_refresh","title":"OAuth with a refresh token — req_oauth_refresh","text":"Authenticate using refresh token, following process described Section 6 RFC 6749. technique primarily useful testing: can manually retrieve OAuth token using another OAuth flow (e.g. oauth_flow_auth_code()), extract refresh token result, save environment variable use automated tests. requesting access token, server may also return new refresh token. happens, oauth_flow_refresh() warn, retrieve new update refresh token update stored value. find happening lot, sign using different flow automated tests. Learn overall OAuth authentication flow https://httr2.r-lib.org/articles/oauth.html.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_refresh.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"OAuth with a refresh token — req_oauth_refresh","text":"","code":"req_oauth_refresh( req, client, refresh_token = Sys.getenv(\"HTTR2_REFRESH_TOKEN\"), scope = NULL, token_params = list() ) oauth_flow_refresh( client, refresh_token = Sys.getenv(\"HTTR2_REFRESH_TOKEN\"), scope = NULL, token_params = list() )"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_refresh.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"OAuth with a refresh token — req_oauth_refresh","text":"req httr2 request object. client oauth_client(). refresh_token refresh token. equivalent password typed console stored script. Instead, recommend placing environment variable; default behaviour look HTTR2_REFRESH_TOKEN. scope Scopes requested resource owner. token_params List containing additional parameters passed token_url.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_refresh.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"OAuth with a refresh token — req_oauth_refresh","text":"req_oauth_refresh() returns modified HTTP request use OAuth; oauth_flow_refresh() returns oauth_token.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_refresh.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"OAuth with a refresh token — req_oauth_refresh","text":"","code":"client <- oauth_client(\"example\", \"https://example.com/get_token\") req <- request(\"https://example.com\") req |> req_oauth_refresh(client) #> #> GET https://example.com #> Body: empty #> Policies: #> • auth_sign: a list #> • auth_oauth: TRUE"},{"path":"https://httr2.r-lib.org/dev/reference/req_options.html","id":null,"dir":"Reference","previous_headings":"","what":"Set arbitrary curl options in request — req_options","title":"Set arbitrary curl options in request — req_options","text":"req_options() expert use ; allows directly set libcurl options access features otherwise available httr2.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_options.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Set arbitrary curl options in request — req_options","text":"","code":"req_options(.req, ...)"},{"path":"https://httr2.r-lib.org/dev/reference/req_options.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Set arbitrary curl options in request — req_options","text":".req request. ... Name-value pairs. name valid curl option, found curl::curl_options().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_options.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Set arbitrary curl options in request — req_options","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_options.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Set arbitrary curl options in request — req_options","text":"","code":"# req_options() allows you to access curl options that are not otherwise # exposed by httr2. For example, in very special cases you may need to # turn off SSL verification. This is generally a bad idea so httr2 doesn't # provide a convenient wrapper, but if you really know what you're doing # you can still access this libcurl option: req <- request(\"https://example.com\") |> req_options(ssl_verifypeer = 0)"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform.html","id":null,"dir":"Reference","previous_headings":"","what":"Perform a request to get a response — req_perform","title":"Perform a request to get a response — req_perform","text":"preparing request, call req_perform() perform , fetching results back R response. default HTTP method GET unless body (set req_body_json friends) present, case POST. can override defaults req_method().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Perform a request to get a response — req_perform","text":"","code":"req_perform( req, path = NULL, verbosity = NULL, mock = getOption(\"httr2_mock\", NULL), error_call = current_env() )"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Perform a request to get a response — req_perform","text":"req httr2 request object. path Optionally, path save body response. useful large responses since avoids storing response memory. verbosity much information print? wrapper around req_verbose() uses integer control verbosity: 0: output 1: show headers 2: show headers bodies 3: show headers, bodies, curl status messages. Use with_verbosity() control verbosity requests affect directly. mock mocking function. supplied, function called request. return either NULL (want handle request) response (). See with_mock()/ local_mock() details. error_call execution environment currently running function, e.g. caller_env(). function mentioned error messages source error. See call argument abort() information.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Perform a request to get a response — req_perform","text":"HTTP request succeeds, status code ok (e.g. 200), HTTP response. HTTP request succeeds, status code error (e.g 404), error class c(\"httr2_http_404\", \"httr2_http\"). default, 400 500 status codes treated error, can customise req_error(). HTTP request fails (e.g. connection dropped server exist), error class \"httr2_failure\".","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform.html","id":"requests","dir":"Reference","previous_headings":"","what":"Requests","title":"Perform a request to get a response — req_perform","text":"Note one call req_perform() may perform multiple HTTP requests: url redirected 301, 302, 303, 307, curl automatically follow Location header new location. configured retries req_retry() request fails transient problem, req_perform() try waiting bit. See req_retry() details. using OAuth, cached token expired, req_perform() get new token either using refresh token (available) running OAuth flow.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform.html","id":"progress-bar","dir":"Reference","previous_headings":"","what":"Progress bar","title":"Perform a request to get a response — req_perform","text":"req_perform() automatically add progress bar needs wait requests req_throttle() req_retry(). can turn progress bar (just show total time wait) setting options(httr2_progress = FALSE).","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_perform.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Perform a request to get a response — req_perform","text":"","code":"request(\"https://google.com\") |> req_perform() #> #> GET https://www.google.com/ #> Status: 200 OK #> Content-Type: text/html #> Body: In memory (22162 bytes)"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_connection.html","id":null,"dir":"Reference","previous_headings":"","what":"Perform a request and return a streaming connection — req_perform_connection","title":"Perform a request and return a streaming connection — req_perform_connection","text":"Use req_perform_connection() perform request want stream response body. response returned req_perform_connection() includes connection body. can use resp_stream_raw(), resp_stream_lines(), resp_stream_sse() retrieve data chunk time. Always finish closing connection calling close(response). alternative interface req_perform_stream() returns connection can use pull data, rather providing callbacks data pushed . useful want work handling inputs stream.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_connection.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Perform a request and return a streaming connection — req_perform_connection","text":"","code":"req_perform_connection(req, blocking = TRUE)"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_connection.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Perform a request and return a streaming connection — req_perform_connection","text":"req httr2 request object. blocking retrieving data, connection block wait desired information immediately return (possibly nothing)?","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_connection.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Perform a request and return a streaming connection — req_perform_connection","text":"","code":"req <- request(example_url()) |> req_url_path(\"/stream-bytes/32768\") resp <- req_perform_connection(req) length(resp_stream_raw(resp, kb = 16)) #> [1] 16384 length(resp_stream_raw(resp, kb = 16)) #> [1] 16384 # When the stream has no more data, you'll get an empty result: length(resp_stream_raw(resp, kb = 16)) #> [1] 0 # Always close the response when you're done close(resp)"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_iterative.html","id":null,"dir":"Reference","previous_headings":"","what":"Perform requests iteratively, generating new requests from previous responses — req_perform_iterative","title":"Perform requests iteratively, generating new requests from previous responses — req_perform_iterative","text":"req_perform_iterative() iteratively generates performs requests, using callback function, next_req, define next request based current request response. probably want pair iteration helper use multi-response handler process result.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_iterative.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Perform requests iteratively, generating new requests from previous responses — req_perform_iterative","text":"","code":"req_perform_iterative( req, next_req, path = NULL, max_reqs = 20, on_error = c(\"stop\", \"return\"), progress = TRUE )"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_iterative.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Perform requests iteratively, generating new requests from previous responses — req_perform_iterative","text":"req first request perform. next_req function takes previous response (resp) request (req) returns request next page NULL iteration terminate. See details. path Optionally, path save body request. glue string uses {} distinguish different requests. Useful large responses avoids storing response memory. max_reqs maximum number requests perform. Use Inf perform requests next_req() returns NULL. on_error happen request fails? \"stop\", default: stop iterating error. \"return\": stop iterating, returning successful responses far, well error object failed request. progress Display progress bar? Use TRUE turn basic progress bar, use string give name, see progress_bars customise ways.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_iterative.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Perform requests iteratively, generating new requests from previous responses — req_perform_iterative","text":"list, length max_reqs, containing responses possibly one error object, on_error \"return\" one requests errors. present, error object always last element list. httr2 errors captured; see req_error() details.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_iterative.html","id":"next-req-","dir":"Reference","previous_headings":"","what":"next_req()","title":"Perform requests iteratively, generating new requests from previous responses — req_perform_iterative","text":"key piece makes req_perform_iterative() work next_req() argument. common cases, can use one canned helpers, like iterate_with_offset(). , however, API wrapping uses different pagination system, need write . section gives advice. Generally, function needs inspect response, extract data , use modify previous request. example, imagine response returns cursor, needs added body request. simplest version function might look like : one problem : pages return, cursor NULL, req_body_json_modify() still generate meaningful request. need handle specifically returning NULL: value NULL lets req_perform_iterative() know pages remaining. one last feature might want add iterator: know total number pages, nice let req_perform_iterative() know can adjust progress bar. (ever decrease number pages, increase .) can signal total number pages calling signal_total_pages(), like :","code":"next_req <- function(resp, req) { cursor <- resp_body_json(resp)$next_cursor req |> req_body_json_modify(cursor = cursor) } next_req <- function(resp, req) { cursor <- resp_body_json(resp)$next_cursor if (is.null(cursor)) return(NULL) req |> req_body_json_modify(cursor = cursor) } next_req <- function(resp, req) { body <- resp_body_json(resp) cursor <- body$next_cursor if (is.null(cursor)) return(NULL) signal_total_pages(body$pages) req |> req_body_json_modify(cursor = cursor) }"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_iterative.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Perform requests iteratively, generating new requests from previous responses — req_perform_iterative","text":"","code":"req <- request(example_url()) |> req_url_path(\"/iris\") |> req_throttle(10) |> req_url_query(limit = 5) resps <- req_perform_iterative(req, iterate_with_offset(\"page_index\")) #> Iterating ■■■■■■■■■■■■■■■■ 50% | ETA: 1s #> Iterating ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 100% | ETA: 0s data <- resps |> resps_data(function(resp) { data <- resp_body_json(resp)$data data.frame( Sepal.Length = sapply(data, `[[`, \"Sepal.Length\"), Sepal.Width = sapply(data, `[[`, \"Sepal.Width\"), Petal.Length = sapply(data, `[[`, \"Petal.Length\"), Petal.Width = sapply(data, `[[`, \"Petal.Width\"), Species = sapply(data, `[[`, \"Species\") ) }) str(data) #> 'data.frame':\t100 obs. of 5 variables: #> $ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ... #> $ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ... #> $ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ... #> $ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ... #> $ Species : chr \"setosa\" \"setosa\" \"setosa\" \"setosa\" ..."},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_parallel.html","id":null,"dir":"Reference","previous_headings":"","what":"Perform a list of requests in parallel — req_perform_parallel","title":"Perform a list of requests in parallel — req_perform_parallel","text":"variation req_perform_sequential() performs multiple requests parallel. Exercise caution using function; easy pummel server many simultaneous requests. use hosts designed serve many files , typically web servers, API servers. req_perform_parallel() limitations: retrieve new OAuth token expires part way requests. perform throttling req_throttle(). attempt retries described req_retry(). consults cache set req_cache() /requests. limitations problematic use case, recommend req_perform_sequential() instead.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_parallel.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Perform a list of requests in parallel — req_perform_parallel","text":"","code":"req_perform_parallel( reqs, paths = NULL, pool = NULL, on_error = c(\"stop\", \"return\", \"continue\"), progress = TRUE )"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_parallel.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Perform a list of requests in parallel — req_perform_parallel","text":"reqs list requests. paths optional character vector paths, want download request bodies disk. supplied, must length reqs. pool Optionally, curl pool made curl::new_pool(). Supply want override defaults total concurrent connections (100) concurrent connections per host (6). on_error happen one requests fails? stop, default: stop iterating error. return: stop iterating, returning successful responses received far, well error object failed request. continue: continue iterating, recording errors result. progress Display progress bar? Use TRUE turn basic progress bar, use string give name, see progress_bars customise ways.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_parallel.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Perform a list of requests in parallel — req_perform_parallel","text":"list, length reqs, containing responses possibly error objects, on_error \"return\" \"continue\" one responses errors. on_error \"return\" errors ith request, ith element result error object, remaining elements NULL. on_error \"continue\", mix requests error objects. httr2 errors captured; see req_error() details.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_parallel.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Perform a list of requests in parallel — req_perform_parallel","text":"","code":"# Requesting these 4 pages one at a time would take 2 seconds: request_base <- request(example_url()) reqs <- list( request_base |> req_url_path(\"/delay/0.5\"), request_base |> req_url_path(\"/delay/0.5\"), request_base |> req_url_path(\"/delay/0.5\"), request_base |> req_url_path(\"/delay/0.5\") ) # But it's much faster if you request in parallel system.time(resps <- req_perform_parallel(reqs)) #> user system elapsed #> 0.330 0.699 1.029 # req_perform_parallel() will fail on error reqs <- list( request_base |> req_url_path(\"/status/200\"), request_base |> req_url_path(\"/status/400\"), request(\"FAILURE\") ) try(resps <- req_perform_parallel(reqs)) #> Error in req_perform_parallel(reqs) : Could not resolve host: FAILURE # but can use on_error to capture all successful results resps <- req_perform_parallel(reqs, on_error = \"continue\") # Inspect the successful responses resps |> resps_successes() #> [[1]] #> #> GET http://127.0.0.1:34151/status/200 #> Status: 200 OK #> Content-Type: text/plain #> Body: None #> # And the failed responses resps |> resps_failures() |> resps_requests() #> [[1]] #> #> GET http://127.0.0.1:34151/status/400 #> Body: empty #> #> [[2]] #> #> GET FAILURE #> Body: empty #>"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_promise.html","id":null,"dir":"Reference","previous_headings":"","what":"Perform request asynchronously using the promises package — req_perform_promise","title":"Perform request asynchronously using the promises package — req_perform_promise","text":"variation req_perform() returns promises::promise() object immediately performs request background, returning program control request finished. See promises package documentation details work resulting promise object. Like req_perform_parallel(), exercise caution using function; easy pummel server many simultaneous requests. Also, servers can handle 1 request time, responses may still return sequentially. req_perform_promise() also similar limitations req_perform_parallel() function, : retrieve new OAuth token expires promised request created actually requested. perform throttling req_throttle(). attempt retries described req_retry(). consults cache set req_cache() request promised.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_promise.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Perform request asynchronously using the promises package — req_perform_promise","text":"","code":"req_perform_promise(req, path = NULL, pool = NULL)"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_promise.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Perform request asynchronously using the promises package — req_perform_promise","text":"req httr2 request object. path Optionally, path save body response. useful large responses since avoids storing response memory. pool Optionally, curl pool made curl::new_pool(). Supply want override defaults total concurrent connections (100) concurrent connections per host (6).","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_promise.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Perform request asynchronously using the promises package — req_perform_promise","text":"promises::promise() object resolves response successful rejects errors thrown req_perform().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_promise.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Perform request asynchronously using the promises package — req_perform_promise","text":"","code":"if (FALSE) { # \\dontrun{ library(promises) request_base <- request(example_url()) |> req_url_path_append(\"delay\") p <- request_base |> req_url_path_append(2) |> req_perform_promise() # A promise object, not particularly useful on its own p # Use promise chaining functions to access results p %...>% resp_body_json() %...>% print() # Can run two requests at the same time p1 <- request_base |> req_url_path_append(2) |> req_perform_promise() p2 <- request_base |> req_url_path_append(1) |> req_perform_promise() p1 %...>% resp_url_path %...>% paste0(., \" finished\") %...>% print() p2 %...>% resp_url_path %...>% paste0(., \" finished\") %...>% print() # See the [promises package documentation](https://rstudio.github.io/promises/) # for more information on working with promises } # }"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_sequential.html","id":null,"dir":"Reference","previous_headings":"","what":"Perform multiple requests in sequence — req_perform_sequential","title":"Perform multiple requests in sequence — req_perform_sequential","text":"Given list requests, function performs turn, returning list responses. slower req_perform_parallel() fewer limitations.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_sequential.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Perform multiple requests in sequence — req_perform_sequential","text":"","code":"req_perform_sequential( reqs, paths = NULL, on_error = c(\"stop\", \"return\", \"continue\"), progress = TRUE )"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_sequential.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Perform multiple requests in sequence — req_perform_sequential","text":"reqs list requests. paths optional character vector paths, want download request bodies disk. supplied, must length reqs. on_error happen one requests fails? stop, default: stop iterating error. return: stop iterating, returning successful responses received far, well error object failed request. continue: continue iterating, recording errors result. progress Display progress bar? Use TRUE turn basic progress bar, use string give name, see progress_bars customise ways.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_sequential.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Perform multiple requests in sequence — req_perform_sequential","text":"list, length reqs, containing responses possibly error objects, on_error \"return\" \"continue\" one responses errors. on_error \"return\" errors ith request, ith element result error object, remaining elements NULL. on_error \"continue\", mix requests error objects. httr2 errors captured; see req_error() details.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_sequential.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Perform multiple requests in sequence — req_perform_sequential","text":"","code":"# One use of req_perform_sequential() is if the API allows you to request # data for multiple objects, you want data for more objects than can fit # in one request. req <- request(\"https://api.restful-api.dev/objects\") # Imagine we have 50 ids: ids <- sort(sample(100, 50)) # But the API only allows us to request 10 at time. So we first use split # and some modulo arithmetic magic to generate chunks of length 10 chunks <- unname(split(ids, (seq_along(ids) - 1) %/% 10)) # Then we use lapply to generate one request for each chunk: reqs <- chunks |> lapply(\\(idx) req |> req_url_query(id = idx, .multi = \"comma\")) # Then we can perform them all and get the results if (FALSE) { # \\dontrun{ resps <- reqs |> req_perform_sequential() resps_data(resps, \\(resp) resp_body_json(resp)) } # }"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_stream.html","id":null,"dir":"Reference","previous_headings":"","what":"Perform a request and handle data as it streams back — req_perform_stream","title":"Perform a request and handle data as it streams back — req_perform_stream","text":"preparing request, call req_perform_stream() perform request handle result streaming callback. useful streaming HTTP APIs potentially stream never ends. callback called result successful. need stream error response, can use req_error() suppress error handling body streamed .","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_stream.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Perform a request and handle data as it streams back — req_perform_stream","text":"","code":"req_perform_stream( req, callback, timeout_sec = Inf, buffer_kb = 64, round = c(\"byte\", \"line\") )"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_stream.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Perform a request and handle data as it streams back — req_perform_stream","text":"req httr2 request object. callback single argument callback function. called repeatedly raw vector whenever least buffer_kb worth data process. must return TRUE continue streaming. timeout_sec Number seconds process stream . buffer_kb Buffer size, kilobytes. round raw vector sent callback rounded? Choose \"byte\", \"line\", supply function takes raw vector bytes returns locations possible cut points (integer() none).","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_stream.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Perform a request and handle data as it streams back — req_perform_stream","text":"HTTP response. body empty request successful (since callback function handled ). body contain HTTP response body request unsuccessful.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_stream.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Perform a request and handle data as it streams back — req_perform_stream","text":"","code":"show_bytes <- function(x) { cat(\"Got \", length(x), \" bytes\\n\", sep = \"\") TRUE } resp <- request(example_url()) |> req_url_path(\"/stream-bytes/100000\") |> req_perform_stream(show_bytes, buffer_kb = 32) #> Got 32768 bytes #> Got 32768 bytes #> Got 32768 bytes #> Got 1696 bytes resp #> #> GET http://127.0.0.1:34151/stream-bytes/100000 #> Status: 200 OK #> Content-Type: application/octet-stream #> Body: None"},{"path":"https://httr2.r-lib.org/dev/reference/req_progress.html","id":null,"dir":"Reference","previous_headings":"","what":"Add a progress bar to long downloads or uploads — req_progress","title":"Add a progress bar to long downloads or uploads — req_progress","text":"uploading downloading large file, often useful provide progress bar know long wait.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_progress.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Add a progress bar to long downloads or uploads — req_progress","text":"","code":"req_progress(req, type = c(\"down\", \"up\"))"},{"path":"https://httr2.r-lib.org/dev/reference/req_progress.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Add a progress bar to long downloads or uploads — req_progress","text":"req request. type Type progress display: either number bytes uploaded downloaded.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_progress.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Add a progress bar to long downloads or uploads — req_progress","text":"","code":"req <- request(\"https://r4ds.s3.us-west-2.amazonaws.com/seattle-library-checkouts.csv\") |> req_progress() if (FALSE) { # \\dontrun{ path <- tempfile() req |> req_perform(path = path) } # }"},{"path":"https://httr2.r-lib.org/dev/reference/req_proxy.html","id":null,"dir":"Reference","previous_headings":"","what":"Use a proxy for a request — req_proxy","title":"Use a proxy for a request — req_proxy","text":"Use proxy request","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_proxy.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Use a proxy for a request — req_proxy","text":"","code":"req_proxy( req, url, port = NULL, username = NULL, password = NULL, auth = \"basic\" )"},{"path":"https://httr2.r-lib.org/dev/reference/req_proxy.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Use a proxy for a request — req_proxy","text":"req httr2 request object. url, port Location proxy. username, password Login details proxy, needed. auth Type HTTP authentication use. one following: basic, digest, digest_ie, gssnegotiate, ntlm, .","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_proxy.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Use a proxy for a request — req_proxy","text":"","code":"# Proxy from https://www.proxynova.com/proxy-server-list/ if (FALSE) { # \\dontrun{ request(\"http://hadley.nz\") |> req_proxy(\"20.116.130.70\", 3128) |> req_perform() } # }"},{"path":"https://httr2.r-lib.org/dev/reference/req_retry.html","id":null,"dir":"Reference","previous_headings":"","what":"Control when a request will retry, and how long it will wait between tries — req_retry","title":"Control when a request will retry, and how long it will wait between tries — req_retry","text":"req_retry() alters req_perform() automatically retry case failure. activate , must specify either total number requests make max_tries total amount time spend max_seconds. req_perform() retry error \"transient\", .e. HTTP error can resolved waiting. default, 429 503 statuses treated transient, API wrapping transient status codes (conveys transient-ness property response), can override default is_transient. Additionally, set retry_on_failure = TRUE, request retry either HTTP request HTTP response complete successfully leading error curl, lower-level library httr2 uses perform HTTP request. occurs, example, wifi . bad idea immediately retry request, req_perform() wait little trying : response contains Retry-header, httr2 wait amount time specifies. API wrapping conveys information different header (property response) can override default behaviour retry_after. Otherwise, httr2 use \"truncated exponential backoff full jitter\", .e. wait random amount time one second 2 ^ tries seconds, capped 60 seconds. words, waits runif(1, 1, 2) seconds first failure, runif(1, 1, 4) second, runif(1, 1, 8) third, . prefer different strategy, can override default backoff.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_retry.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Control when a request will retry, and how long it will wait between tries — req_retry","text":"","code":"req_retry( req, max_tries = NULL, max_seconds = NULL, retry_on_failure = FALSE, is_transient = NULL, backoff = NULL, after = NULL )"},{"path":"https://httr2.r-lib.org/dev/reference/req_retry.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Control when a request will retry, and how long it will wait between tries — req_retry","text":"req httr2 request object. max_tries, max_seconds Cap maximum number attempts max_tries total elapsed time first request max_seconds. neither option supplied (default), req_perform() retry. max_tries total number attempts make, always greater one.` retry_on_failure Treat low-level failures transient errors, can retried. is_transient predicate function takes single argument (response) returns TRUE FALSE specifying whether response represents transient error. backoff function takes single argument (number failed attempts far) returns number seconds wait. function takes single argument (response) returns either number seconds wait NULL, indicates precise wait time available backoff strategy used instead..","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_retry.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Control when a request will retry, and how long it will wait between tries — req_retry","text":"modified HTTP request.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_retry.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Control when a request will retry, and how long it will wait between tries — req_retry","text":"","code":"# google APIs assume that a 500 is also a transient error request(\"http://google.com\") |> req_retry(is_transient = \\(resp) resp_status(resp) %in% c(429, 500, 503)) #> #> GET http://google.com #> Body: empty #> Policies: #> • retry_on_failure: FALSE #> • retry_is_transient: a function # use a constant 10s delay after every failure request(\"http://example.com\") |> req_retry(backoff = ~10) #> #> GET http://example.com #> Body: empty #> Policies: #> • retry_on_failure: FALSE #> • retry_backoff: a object # When rate-limited, GitHub's API returns a 403 with # `X-RateLimit-Remaining: 0` and an Unix time stored in the # `X-RateLimit-Reset` header. This takes a bit more work to handle: github_is_transient <- function(resp) { resp_status(resp) == 403 && identical(resp_header(resp, \"X-RateLimit-Remaining\"), \"0\") } github_after <- function(resp) { time <- as.numeric(resp_header(resp, \"X-RateLimit-Reset\")) time - unclass(Sys.time()) } request(\"http://api.github.com\") |> req_retry( is_transient = github_is_transient, after = github_after ) #> #> GET http://api.github.com #> Body: empty #> Policies: #> • retry_on_failure: FALSE #> • retry_is_transient: a function #> • retry_after: a function"},{"path":"https://httr2.r-lib.org/dev/reference/req_template.html","id":null,"dir":"Reference","previous_headings":"","what":"Set request method/path from a template — req_template","title":"Set request method/path from a template — req_template","text":"Many APIs document methods lightweight template mechanism looks like GET /user/{user} POST /organisation/:org. function makes easy copy paste snippets retrieve template variables either function arguments current environment. req_template() append existing path can set base url initial request(). means generally want avoid multiple req_template() calls request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_template.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Set request method/path from a template — req_template","text":"","code":"req_template(req, template, ..., .env = parent.frame())"},{"path":"https://httr2.r-lib.org/dev/reference/req_template.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Set request method/path from a template — req_template","text":"req httr2 request object. template template string consists optional HTTP method path containing variables labelled like either :foo {foo}. ... Template variables. .env Environment look template variables found .... Expert use .","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_template.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Set request method/path from a template — req_template","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_template.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Set request method/path from a template — req_template","text":"","code":"httpbin <- request(example_url()) # You can supply template parameters in `...` httpbin |> req_template(\"GET /bytes/{n}\", n = 100) #> #> GET http://127.0.0.1:34151/bytes/100 #> Body: empty # or you retrieve from the current environment n <- 200 httpbin |> req_template(\"GET /bytes/{n}\") #> #> GET http://127.0.0.1:34151/bytes/200 #> Body: empty # Existing path is preserved: httpbin_test <- request(example_url()) |> req_url_path(\"/test\") name <- \"id\" value <- \"a3fWa\" httpbin_test |> req_template(\"GET /set/{name}/{value}\") #> #> GET http://127.0.0.1:34151/test/set/id/a3fWa #> Body: empty"},{"path":"https://httr2.r-lib.org/dev/reference/req_throttle.html","id":null,"dir":"Reference","previous_headings":"","what":"Rate limit a request by automatically adding a delay — req_throttle","title":"Rate limit a request by automatically adding a delay — req_throttle","text":"Use req_throttle() ensure repeated calls req_perform() never exceed specified rate.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_throttle.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Rate limit a request by automatically adding a delay — req_throttle","text":"","code":"req_throttle(req, rate, realm = NULL)"},{"path":"https://httr2.r-lib.org/dev/reference/req_throttle.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Rate limit a request by automatically adding a delay — req_throttle","text":"req httr2 request object. rate Maximum rate, .e. maximum number requests per second. Usually easiest expressed fraction, number_of_requests / number_of_seconds, e.g. 15 requests per minute 15 / 60. realm string uniquely identifies throttle pool use (throttling limits always apply per pool). supplied, defaults hostname request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_throttle.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Rate limit a request by automatically adding a delay — req_throttle","text":"modified HTTP request.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_throttle.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Rate limit a request by automatically adding a delay — req_throttle","text":"","code":"# Ensure we never send more than 30 requests a minute req <- request(example_url()) |> req_throttle(rate = 30 / 60) resp <- req_perform(req) throttle_status() #> realm last_request #> 1 127.0.0.1 2024-10-23 18:13:41 resp <- req_perform(req) #> Waiting 2s for throttling delay ■■■■■■■■■■■■■■■ #> Waiting 2s for throttling delay ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ throttle_status() #> realm last_request #> 1 127.0.0.1 2024-10-23 18:13:43"},{"path":"https://httr2.r-lib.org/dev/reference/req_timeout.html","id":null,"dir":"Reference","previous_headings":"","what":"Set time limit for a request — req_timeout","title":"Set time limit for a request — req_timeout","text":"error thrown request complete time limit.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_timeout.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Set time limit for a request — req_timeout","text":"","code":"req_timeout(req, seconds)"},{"path":"https://httr2.r-lib.org/dev/reference/req_timeout.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Set time limit for a request — req_timeout","text":"req httr2 request object. seconds Maximum number seconds wait","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_timeout.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Set time limit for a request — req_timeout","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_timeout.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Set time limit for a request — req_timeout","text":"","code":"# Give up after at most 10 seconds request(\"http://example.com\") |> req_timeout(10) #> #> GET http://example.com #> Body: empty #> Options: #> • timeout_ms: 10000 #> • connecttimeout: 0"},{"path":"https://httr2.r-lib.org/dev/reference/req_url.html","id":null,"dir":"Reference","previous_headings":"","what":"Modify request URL — req_url","title":"Modify request URL — req_url","text":"req_url() replaces entire url req_url_query() modifies components query req_url_path() modifies path req_url_path_append() adds path","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_url.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Modify request URL — req_url","text":"","code":"req_url(req, url) req_url_query(.req, ..., .multi = c(\"error\", \"comma\", \"pipe\", \"explode\")) req_url_path(req, ...) req_url_path_append(req, ...)"},{"path":"https://httr2.r-lib.org/dev/reference/req_url.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Modify request URL — req_url","text":"req, .req httr2 request object. url New URL; completely replaces existing. ... req_url_query(): Name-value pairs define query parameters. value must either atomic vector NULL (removes corresponding parameters). want opt escaping, wrap strings (). req_url_path() req_url_path_append(): sequence path components combined /. .multi Controls happens element ... vector containing multiple values: \"error\", default, throws error. \"comma\", separates values ,, e.g. ?x=1,2. \"pipe\", separates values |, e.g. ?x=1|2. \"explode\", turns element parameter, e.g. ?x=1&x=2. none functions work, can alternatively supply function takes character vector returns string.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_url.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Modify request URL — req_url","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_url.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Modify request URL — req_url","text":"","code":"req <- request(\"http://example.com\") # Change url components req |> req_url_path_append(\"a\") |> req_url_path_append(\"b\") |> req_url_path_append(\"search.html\") |> req_url_query(q = \"the cool ice\") #> #> GET http://example.com/a/b/search.html?q=the%20cool%20ice #> Body: empty # Change complete url req |> req_url(\"http://google.com\") #> #> GET http://google.com #> Body: empty # Use .multi to control what happens with vector parameters: req |> req_url_query(id = 100:105, .multi = \"comma\") #> #> GET http://example.com?id=100,101,102,103,104,105 #> Body: empty req |> req_url_query(id = 100:105, .multi = \"explode\") #> #> GET http://example.com?id=100&id=101&id=102&id=103&id=104&id=105 #> Body: empty # If you have query parameters in a list, use !!! params <- list(a = \"1\", b = \"2\") req |> req_url_query(!!!params, c = \"3\") #> #> GET http://example.com?a=1&b=2&c=3 #> Body: empty"},{"path":"https://httr2.r-lib.org/dev/reference/req_user_agent.html","id":null,"dir":"Reference","previous_headings":"","what":"Set user-agent for a request — req_user_agent","title":"Set user-agent for a request — req_user_agent","text":"overrides default user-agent set httr2 includes version numbers httr2, curl package, libcurl.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_user_agent.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Set user-agent for a request — req_user_agent","text":"","code":"req_user_agent(req, string = NULL)"},{"path":"https://httr2.r-lib.org/dev/reference/req_user_agent.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Set user-agent for a request — req_user_agent","text":"req httr2 request object. string String sent User-Agent header. NULL, user default.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_user_agent.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Set user-agent for a request — req_user_agent","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_user_agent.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Set user-agent for a request — req_user_agent","text":"","code":"# Default user-agent: request(\"http://example.com\") |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> request(\"http://example.com\") |> req_user_agent(\"MyString\") |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: MyString #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> # If you're wrapping in an API in a package, it's polite to set the # user agent to identify your package. request(\"http://example.com\") |> req_user_agent(\"MyPackage (http://mypackage.com)\") |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: MyPackage (http://mypackage.com) #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #>"},{"path":"https://httr2.r-lib.org/dev/reference/req_verbose.html","id":null,"dir":"Reference","previous_headings":"","what":"Show extra output when request is performed — req_verbose","title":"Show extra output when request is performed — req_verbose","text":"req_verbose() uses following prefixes distinguish different components HTTP requests responses: * informative curl messages -> request headers >> request body <- response headers << response body","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_verbose.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Show extra output when request is performed — req_verbose","text":"","code":"req_verbose( req, header_req = TRUE, header_resp = TRUE, body_req = FALSE, body_resp = FALSE, info = FALSE, redact_headers = TRUE )"},{"path":"https://httr2.r-lib.org/dev/reference/req_verbose.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Show extra output when request is performed — req_verbose","text":"req httr2 request object. header_req, header_resp Show request/response headers? body_req, body_resp request/response bodies? response body compressed, show number bytes received \"chunk\". info Show informational text curl? mainly useful debugging https auth problems, disabled default. redact_headers Redact confidential data headers? Currently redacts contents Authorization header prevent accidentally leaking credentials debugging/reprexing.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_verbose.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Show extra output when request is performed — req_verbose","text":"modified HTTP request.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_verbose.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Show extra output when request is performed — req_verbose","text":"","code":"# Use `req_verbose()` to see the headers that are sent back and forth when # making a request resp <- request(\"https://httr2.r-lib.org\") |> req_verbose() |> req_perform() #> -> GET / HTTP/2 #> -> Host: httr2.r-lib.org #> -> user-agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> -> accept: */* #> -> accept-encoding: deflate, gzip, br, zstd #> -> #> <- HTTP/2 200 #> <- server: GitHub.com #> <- content-type: text/html; charset=utf-8 #> <- last-modified: Wed, 23 Oct 2024 14:55:26 GMT #> <- access-control-allow-origin: * #> <- etag: W/\"67190e5e-4983\" #> <- expires: Wed, 23 Oct 2024 18:22:09 GMT #> <- cache-control: max-age=600 #> <- content-encoding: gzip #> <- x-proxy-cache: MISS #> <- x-github-request-id: D2CE:1451B9:19BD01:1A2D21:67193C77 #> <- accept-ranges: bytes #> <- date: Wed, 23 Oct 2024 18:13:44 GMT #> <- via: 1.1 varnish #> <- age: 18 #> <- x-served-by: cache-pao-kpao1770054-PAO #> <- x-cache: HIT #> <- x-cache-hits: 1 #> <- x-timer: S1729707224.058465,VS0,VE2 #> <- vary: Accept-Encoding #> <- x-fastly-request-id: aa2bb30c1e05c8eba3c3075c929feccd45cfc113 #> <- content-length: 4636 #> <- # Or use one of the convenient shortcuts: resp <- request(\"https://httr2.r-lib.org\") |> req_perform(verbosity = 1) #> -> GET / HTTP/2 #> -> Host: httr2.r-lib.org #> -> user-agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> -> accept: */* #> -> accept-encoding: deflate, gzip, br, zstd #> -> #> <- HTTP/2 200 #> <- server: GitHub.com #> <- content-type: text/html; charset=utf-8 #> <- last-modified: Wed, 23 Oct 2024 14:55:26 GMT #> <- access-control-allow-origin: * #> <- etag: W/\"67190e5e-4983\" #> <- expires: Wed, 23 Oct 2024 18:22:09 GMT #> <- cache-control: max-age=600 #> <- content-encoding: gzip #> <- x-proxy-cache: MISS #> <- x-github-request-id: D2CE:1451B9:19BD01:1A2D21:67193C77 #> <- accept-ranges: bytes #> <- date: Wed, 23 Oct 2024 18:13:44 GMT #> <- via: 1.1 varnish #> <- age: 18 #> <- x-served-by: cache-pao-kpao1770054-PAO #> <- x-cache: HIT #> <- x-cache-hits: 2 #> <- x-timer: S1729707224.069477,VS0,VE0 #> <- vary: Accept-Encoding #> <- x-fastly-request-id: f0112ead41cb62188465a35974e94d410b7db0e2 #> <- content-length: 4636 #> <-"},{"path":"https://httr2.r-lib.org/dev/reference/request.html","id":null,"dir":"Reference","previous_headings":"","what":"Create a new HTTP request — request","title":"Create a new HTTP request — request","text":"three steps needed perform HTTP request httr2: Create request object request(url) (function). Define behaviour req_ functions, e.g.: req_headers() set header values. req_url_path() friends modify url. req_body_json() friends add body. req_auth_basic() perform basic HTTP authentication. req_oauth_auth_code() use OAuth auth code flow. Perform request fetch response req_perform().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/request.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Create a new HTTP request — request","text":"","code":"request(base_url)"},{"path":"https://httr2.r-lib.org/dev/reference/request.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Create a new HTTP request — request","text":"base_url Base URL request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/request.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Create a new HTTP request — request","text":"HTTP request: S3 list class httr2_request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/request.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Create a new HTTP request — request","text":"","code":"request(\"http://r-project.org\") #> #> GET http://r-project.org #> Body: empty"},{"path":"https://httr2.r-lib.org/dev/reference/resp_body_raw.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract body from response — resp_body_raw","title":"Extract body from response — resp_body_raw","text":"resp_body_raw() returns raw bytes. resp_body_string() returns UTF-8 string. resp_body_json() returns parsed JSON. resp_body_html() returns parsed HTML. resp_body_xml() returns parsed XML. resp_has_body() returns TRUE response body. resp_body_json() resp_body_xml() check content-type header correct; server returns incorrect type can suppress check check_type = FALSE. two functions also cache parsed object second subsequent calls low-cost.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_body_raw.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract body from response — resp_body_raw","text":"","code":"resp_body_raw(resp) resp_has_body(resp) resp_body_string(resp, encoding = NULL) resp_body_json(resp, check_type = TRUE, simplifyVector = FALSE, ...) resp_body_html(resp, check_type = TRUE, ...) resp_body_xml(resp, check_type = TRUE, ...)"},{"path":"https://httr2.r-lib.org/dev/reference/resp_body_raw.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract body from response — resp_body_raw","text":"resp httr2 response object, created req_perform(). encoding Character encoding body text. specified, use encoding specified content-type, falling back UTF-8 warning found. resulting string always re-encoded UTF-8. check_type Check response expected content type? Set FALSE suppress automated check simplifyVector JSON arrays containing primitives (.e. booleans, numbers, strings) caused atomic vectors? ... arguments passed jsonlite::fromJSON() xml2::read_xml() respectively.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_body_raw.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract body from response — resp_body_raw","text":"resp_body_raw() returns raw vector. resp_body_string() returns string. resp_body_json() returns NULL, atomic vector, list. resp_body_html() resp_body_xml() return xml2::xml_document","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_body_raw.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract body from response — resp_body_raw","text":"","code":"resp <- request(\"https://httr2.r-lib.org\") |> req_perform() resp #> #> GET https://httr2.r-lib.org/ #> Status: 200 OK #> Content-Type: text/html #> Body: In memory (18819 bytes) resp |> resp_has_body() #> [1] TRUE resp |> resp_body_raw() #> [1] 3c 21 44 4f 43 54 59 50 45 20 68 74 6d 6c 3e 0a 3c 21 2d 2d 20 47 #> [23] 65 6e 65 72 61 74 65 64 20 62 79 20 70 6b 67 64 6f 77 6e 3a 20 64 #> [45] 6f 20 6e 6f 74 20 65 64 69 74 20 62 79 20 68 61 6e 64 20 2d 2d 3e #> [67] 3c 68 74 6d 6c 20 6c 61 6e 67 3d 22 65 6e 22 3e 0a 3c 68 65 61 64 #> [89] 3e 0a 3c 6d 65 74 61 20 68 74 74 70 2d 65 71 75 69 76 3d 22 43 6f #> [111] 6e 74 65 6e 74 2d 54 79 70 65 22 20 63 6f 6e 74 65 6e 74 3d 22 74 #> [133] 65 78 74 2f 68 74 6d 6c 3b 20 63 68 61 72 73 65 74 3d 55 54 46 2d #> [155] 38 22 3e 0a 3c 6d 65 74 61 20 63 68 61 72 73 65 74 3d 22 75 74 66 #> [177] 2d 38 22 3e 0a 3c 6d 65 74 61 20 68 74 74 70 2d 65 71 75 69 76 3d #> [199] 22 58 2d 55 41 2d 43 6f 6d 70 61 74 69 62 6c 65 22 20 63 6f 6e 74 #> [221] 65 6e 74 3d 22 49 45 3d 65 64 67 65 22 3e 0a 3c 6d 65 74 61 20 6e #> [243] 61 6d 65 3d 22 76 69 65 77 70 6f 72 74 22 20 63 6f 6e 74 65 6e 74 #> [265] 3d 22 77 69 64 74 68 3d 64 65 76 69 63 65 2d 77 69 64 74 68 2c 20 #> [287] 69 6e 69 74 69 61 6c 2d 73 63 61 6c 65 3d 31 2c 20 73 68 72 69 6e #> [309] 6b 2d 74 6f 2d 66 69 74 3d 6e 6f 22 3e 0a 3c 74 69 74 6c 65 3e 50 #> [331] 65 72 66 6f 72 6d 20 48 54 54 50 20 52 65 71 75 65 73 74 73 20 61 #> [353] 6e 64 20 50 72 6f 63 65 73 73 20 74 68 65 20 52 65 73 70 6f 6e 73 #> [375] 65 73 20 e2 80 a2 20 68 74 74 72 32 3c 2f 74 69 74 6c 65 3e 0a 3c #> [397] 21 2d 2d 20 66 61 76 69 63 6f 6e 73 20 2d 2d 3e 3c 6c 69 6e 6b 20 #> [419] 72 65 6c 3d 22 69 63 6f 6e 22 20 74 79 70 65 3d 22 69 6d 61 67 65 #> [441] 2f 70 6e 67 22 20 73 69 7a 65 73 3d 22 31 36 78 31 36 22 20 68 72 #> [463] 65 66 3d 22 66 61 76 69 63 6f 6e 2d 31 36 78 31 36 2e 70 6e 67 22 #> [485] 3e 0a 3c 6c 69 6e 6b 20 72 65 6c 3d 22 69 63 6f 6e 22 20 74 79 70 #> [507] 65 3d 22 69 6d 61 67 65 2f 70 6e 67 22 20 73 69 7a 65 73 3d 22 33 #> [529] 32 78 33 32 22 20 68 72 65 66 3d 22 66 61 76 69 63 6f 6e 2d 33 32 #> [551] 78 33 32 2e 70 6e 67 22 3e 0a 3c 6c 69 6e 6b 20 72 65 6c 3d 22 61 #> [573] 70 70 6c 65 2d 74 6f 75 63 68 2d 69 63 6f 6e 22 20 74 79 70 65 3d #> [595] 22 69 6d 61 67 65 2f 70 6e 67 22 20 73 69 7a 65 73 3d 22 31 38 30 #> [617] 78 31 38 30 22 20 68 72 65 66 3d 22 61 70 70 6c 65 2d 74 6f 75 63 #> [639] 68 2d 69 63 6f 6e 2e 70 6e 67 22 3e 0a 3c 6c 69 6e 6b 20 72 65 6c #> [661] 3d 22 61 70 70 6c 65 2d 74 6f 75 63 68 2d 69 63 6f 6e 22 20 74 79 #> [683] 70 65 3d 22 69 6d 61 67 65 2f 70 6e 67 22 20 73 69 7a 65 73 3d 22 #> [705] 31 32 30 78 31 32 30 22 20 68 72 65 66 3d 22 61 70 70 6c 65 2d 74 #> [727] 6f 75 63 68 2d 69 63 6f 6e 2d 31 32 30 78 31 32 30 2e 70 6e 67 22 #> [749] 3e 0a 3c 6c 69 6e 6b 20 72 65 6c 3d 22 61 70 70 6c 65 2d 74 6f 75 #> [771] 63 68 2d 69 63 6f 6e 22 20 74 79 70 65 3d 22 69 6d 61 67 65 2f 70 #> [793] 6e 67 22 20 73 69 7a 65 73 3d 22 37 36 78 37 36 22 20 68 72 65 66 #> [815] 3d 22 61 70 70 6c 65 2d 74 6f 75 63 68 2d 69 63 6f 6e 2d 37 36 78 #> [837] 37 36 2e 70 6e 67 22 3e 0a 3c 6c 69 6e 6b 20 72 65 6c 3d 22 61 70 #> [859] 70 6c 65 2d 74 6f 75 63 68 2d 69 63 6f 6e 22 20 74 79 70 65 3d 22 #> [881] 69 6d 61 67 65 2f 70 6e 67 22 20 73 69 7a 65 73 3d 22 36 30 78 36 #> [903] 30 22 20 68 72 65 66 3d 22 61 70 70 6c 65 2d 74 6f 75 63 68 2d 69 #> [925] 63 6f 6e 2d 36 30 78 36 30 2e 70 6e 67 22 3e 0a 3c 73 63 72 69 70 #> [947] 74 20 73 72 63 3d 22 64 65 70 73 2f 6a 71 75 65 72 79 2d 33 2e 36 #> [969] 2e 30 2f 6a 71 75 65 72 79 2d 33 2e 36 2e 30 2e 6d 69 6e 2e 6a 73 #> [991] 22 3e 3c 2f 73 63 72 69 70 74 3e 3c 6d 65 74 61 20 6e 61 6d 65 3d #> [1013] 22 76 69 65 77 70 6f 72 74 22 20 63 6f 6e 74 65 6e 74 3d 22 77 69 #> [1035] 64 74 68 3d 64 65 76 69 63 65 2d 77 69 64 74 68 2c 20 69 6e 69 74 #> [1057] 69 61 6c 2d 73 63 61 6c 65 3d 31 2c 20 73 68 72 69 6e 6b 2d 74 6f #> [1079] 2d 66 69 74 3d 6e 6f 22 3e 0a 3c 6c 69 6e 6b 20 68 72 65 66 3d 22 #> [1101] 64 65 70 73 2f 62 6f 6f 74 73 74 72 61 70 2d 35 2e 33 2e 31 2f 62 #> [1123] 6f 6f 74 73 74 72 61 70 2e 6d 69 6e 2e 63 73 73 22 20 72 65 6c 3d #> [1145] 22 73 74 79 6c 65 73 68 65 65 74 22 3e 0a 3c 73 63 72 69 70 74 20 #> [1167] 73 72 63 3d 22 64 65 70 73 2f 62 6f 6f 74 73 74 72 61 70 2d 35 2e #> [1189] 33 2e 31 2f 62 6f 6f 74 73 74 72 61 70 2e 62 75 6e 64 6c 65 2e 6d #> [1211] 69 6e 2e 6a 73 22 3e 3c 2f 73 63 72 69 70 74 3e 3c 6c 69 6e 6b 20 #> [1233] 68 72 65 66 3d 22 64 65 70 73 2f 53 6f 75 72 63 65 5f 53 61 6e 73 #> [1255] 5f 50 72 6f 2d 30 2e 34 2e 39 2f 66 6f 6e 74 2e 63 73 73 22 20 72 #> [1277] 65 6c 3d 22 73 74 79 6c 65 73 68 65 65 74 22 3e 0a 3c 6c 69 6e 6b #> [1299] 20 68 72 65 66 3d 22 64 65 70 73 2f 53 6f 75 72 63 65 5f 43 6f 64 #> [1321] 65 5f 50 72 6f 2d 30 2e 34 2e 39 2f 66 6f 6e 74 2e 63 73 73 22 20 #> [1343] 72 65 6c 3d 22 73 74 79 6c 65 73 68 65 65 74 22 3e 0a 3c 6c 69 6e #> [1365] 6b 20 68 72 65 66 3d 22 64 65 70 73 2f 66 6f 6e 74 2d 61 77 65 73 #> [1387] 6f 6d 65 2d 36 2e 34 2e 32 2f 63 73 73 2f 61 6c 6c 2e 6d 69 6e 2e #> [1409] 63 73 73 22 20 72 65 6c 3d 22 73 74 79 6c 65 73 68 65 65 74 22 3e #> [1431] 0a 3c 6c 69 6e 6b 20 68 72 65 66 3d 22 64 65 70 73 2f 66 6f 6e 74 #> [1453] 2d 61 77 65 73 6f 6d 65 2d 36 2e 34 2e 32 2f 63 73 73 2f 76 34 2d #> [1475] 73 68 69 6d 73 2e 6d 69 6e 2e 63 73 73 22 20 72 65 6c 3d 22 73 74 #> [1497] 79 6c 65 73 68 65 65 74 22 3e 0a 3c 73 63 72 69 70 74 20 73 72 63 #> [1519] 3d 22 64 65 70 73 2f 68 65 61 64 72 6f 6f 6d 2d 30 2e 31 31 2e 30 #> [1541] 2f 68 65 61 64 72 6f 6f 6d 2e 6d 69 6e 2e 6a 73 22 3e 3c 2f 73 63 #> [1563] 72 69 70 74 3e 3c 73 63 72 69 70 74 20 73 72 63 3d 22 64 65 70 73 #> [1585] 2f 68 65 61 64 72 6f 6f 6d 2d 30 2e 31 31 2e 30 2f 6a 51 75 65 72 #> [1607] 79 2e 68 65 61 64 72 6f 6f 6d 2e 6d 69 6e 2e 6a 73 22 3e 3c 2f 73 #> [1629] 63 72 69 70 74 3e 3c 73 63 72 69 70 74 20 73 72 63 3d 22 64 65 70 #> [1651] 73 2f 62 6f 6f 74 73 74 72 61 70 2d 74 6f 63 2d 31 2e 30 2e 31 2f #> [1673] 62 6f 6f 74 73 74 72 61 70 2d 74 6f 63 2e 6d 69 6e 2e 6a 73 22 3e #> [1695] 3c 2f 73 63 72 69 70 74 3e 3c 73 63 72 69 70 74 20 73 72 63 3d 22 #> [1717] 64 65 70 73 2f 63 6c 69 70 62 6f 61 72 64 2e 6a 73 2d 32 2e 30 2e #> [1739] 31 31 2f 63 6c 69 70 62 6f 61 72 64 2e 6d 69 6e 2e 6a 73 22 3e 3c #> [1761] 2f 73 63 72 69 70 74 3e 3c 73 63 72 69 70 74 20 73 72 63 3d 22 64 #> [1783] 65 70 73 2f 73 65 61 72 63 68 2d 31 2e 30 2e 30 2f 61 75 74 6f 63 #> [1805] 6f 6d 70 6c 65 74 65 2e 6a 71 75 65 72 79 2e 6d 69 6e 2e 6a 73 22 #> [1827] 3e 3c 2f 73 63 72 69 70 74 3e 3c 73 63 72 69 70 74 20 73 72 63 3d #> [1849] 22 64 65 70 73 2f 73 65 61 72 63 68 2d 31 2e 30 2e 30 2f 66 75 73 #> [1871] 65 2e 6d 69 6e 2e 6a 73 22 3e 3c 2f 73 63 72 69 70 74 3e 3c 73 63 #> [1893] 72 69 70 74 20 73 72 63 3d 22 64 65 70 73 2f 73 65 61 72 63 68 2d #> [1915] 31 2e 30 2e 30 2f 6d 61 72 6b 2e 6d 69 6e 2e 6a 73 22 3e 3c 2f 73 #> [1937] 63 72 69 70 74 3e 3c 21 2d 2d 20 70 6b 67 64 6f 77 6e 20 2d 2d 3e #> [1959] 3c 73 63 72 69 70 74 20 73 72 63 3d 22 70 6b 67 64 6f 77 6e 2e 6a #> [1981] 73 22 3e 3c 2f 73 63 72 69 70 74 3e 3c 6d 65 74 61 20 70 72 6f 70 #> [2003] 65 72 74 79 3d 22 6f 67 3a 74 69 74 6c 65 22 20 63 6f 6e 74 65 6e #> [2025] 74 3d 22 50 65 72 66 6f 72 6d 20 48 54 54 50 20 52 65 71 75 65 73 #> [2047] 74 73 20 61 6e 64 20 50 72 6f 63 65 73 73 20 74 68 65 20 52 65 73 #> [2069] 70 6f 6e 73 65 73 22 3e 0a 3c 6d 65 74 61 20 6e 61 6d 65 3d 22 64 #> [2091] 65 73 63 72 69 70 74 69 6f 6e 22 20 63 6f 6e 74 65 6e 74 3d 22 54 #> [2113] 6f 6f 6c 73 20 66 6f 72 20 63 72 65 61 74 69 6e 67 20 61 6e 64 20 #> [2135] 6d 6f 64 69 66 79 69 6e 67 20 48 54 54 50 20 72 65 71 75 65 73 74 #> [2157] 73 2c 20 74 68 65 6e 20 70 65 72 66 6f 72 6d 69 6e 67 20 74 68 65 #> [2179] 6d 20 61 6e 64 20 70 72 6f 63 65 73 73 69 6e 67 20 74 68 65 20 72 #> [2201] 65 73 75 6c 74 73 2e 20 68 74 74 72 32 20 69 73 20 61 20 6d 6f 64 #> [2223] 65 72 6e 20 72 65 2d 69 6d 61 67 69 6e 69 6e 67 20 6f 66 20 68 74 #> [2245] 74 72 20 74 68 61 74 20 75 73 65 73 20 61 20 70 69 70 65 2d 62 61 #> [2267] 73 65 64 20 69 6e 74 65 72 66 61 63 65 20 61 6e 64 20 73 6f 6c 76 #> [2289] 65 73 20 6d 6f 72 65 20 6f 66 20 74 68 65 20 70 72 6f 62 6c 65 6d #> [2311] 73 20 74 68 61 74 20 41 50 49 20 77 72 61 70 70 69 6e 67 20 70 61 #> [2333] 63 6b 61 67 65 73 20 66 61 63 65 2e 22 3e 0a 3c 6d 65 74 61 20 70 #> [2355] 72 6f 70 65 72 74 79 3d 22 6f 67 3a 64 65 73 63 72 69 70 74 69 6f #> [2377] 6e 22 20 63 6f 6e 74 65 6e 74 3d 22 54 6f 6f 6c 73 20 66 6f 72 20 #> [2399] 63 72 65 61 74 69 6e 67 20 61 6e 64 20 6d 6f 64 69 66 79 69 6e 67 #> [2421] 20 48 54 54 50 20 72 65 71 75 65 73 74 73 2c 20 74 68 65 6e 20 70 #> [2443] 65 72 66 6f 72 6d 69 6e 67 20 74 68 65 6d 20 61 6e 64 20 70 72 6f #> [2465] 63 65 73 73 69 6e 67 20 74 68 65 20 72 65 73 75 6c 74 73 2e 20 68 #> [2487] 74 74 72 32 20 69 73 20 61 20 6d 6f 64 65 72 6e 20 72 65 2d 69 6d #> [2509] 61 67 69 6e 69 6e 67 20 6f 66 20 68 74 74 72 20 74 68 61 74 20 75 #> [2531] 73 65 73 20 61 20 70 69 70 65 2d 62 61 73 65 64 20 69 6e 74 65 72 #> [2553] 66 61 63 65 20 61 6e 64 20 73 6f 6c 76 65 73 20 6d 6f 72 65 20 6f #> [2575] 66 20 74 68 65 20 70 72 6f 62 6c 65 6d 73 20 74 68 61 74 20 41 50 #> [2597] 49 20 77 72 61 70 70 69 6e 67 20 70 61 63 6b 61 67 65 73 20 66 61 #> [2619] 63 65 2e 22 3e 0a 3c 6d 65 74 61 20 70 72 6f 70 65 72 74 79 3d 22 #> [2641] 6f 67 3a 69 6d 61 67 65 22 20 63 6f 6e 74 65 6e 74 3d 22 68 74 74 #> [2663] 70 73 3a 2f 2f 68 74 74 72 32 2e 72 2d 6c 69 62 2e 6f 72 67 2f 6c #> [2685] 6f 67 6f 2e 70 6e 67 22 3e 0a 3c 73 63 72 69 70 74 20 64 65 66 65 #> [2707] 72 20 64 61 74 61 2d 64 6f 6d 61 69 6e 3d 22 68 74 74 72 32 2e 72 #> [2729] 2d 6c 69 62 2e 6f 72 67 2c 61 6c 6c 2e 74 69 64 79 76 65 72 73 65 #> [2751] 2e 6f 72 67 22 20 73 72 63 3d 22 68 74 74 70 73 3a 2f 2f 70 6c 61 #> [2773] 75 73 69 62 6c 65 2e 69 6f 2f 6a 73 2f 70 6c 61 75 73 69 62 6c 65 #> [2795] 2e 6a 73 22 3e 3c 2f 73 63 72 69 70 74 3e 0a 3c 2f 68 65 61 64 3e #> [2817] 0a 3c 62 6f 64 79 3e 0a 20 20 20 20 3c 61 20 68 72 65 66 3d 22 23 #> [2839] 63 6f 6e 74 61 69 6e 65 72 22 20 63 6c 61 73 73 3d 22 76 69 73 75 #> [2861] 61 6c 6c 79 2d 68 69 64 64 65 6e 2d 66 6f 63 75 73 61 62 6c 65 22 #> [2883] 3e 53 6b 69 70 20 74 6f 20 63 6f 6e 74 65 6e 74 3c 2f 61 3e 0a 0a #> [2905] 0a 20 20 20 20 3c 6e 61 76 20 63 6c 61 73 73 3d 22 6e 61 76 62 61 #> [2927] 72 20 6e 61 76 62 61 72 2d 65 78 70 61 6e 64 2d 6c 67 20 66 69 78 #> [2949] 65 64 2d 74 6f 70 20 62 67 2d 6e 6f 6e 65 22 20 64 61 74 61 2d 62 #> [2971] 73 2d 74 68 65 6d 65 3d 22 6c 69 67 68 74 22 20 61 72 69 61 2d 6c #> [2993] 61 62 65 6c 3d 22 53 69 74 65 20 6e 61 76 69 67 61 74 69 6f 6e 22 #> [3015] 3e 3c 64 69 76 20 63 6c 61 73 73 3d 22 63 6f 6e 74 61 69 6e 65 72 #> [3037] 22 3e 0a 0a 20 20 20 20 3c 61 20 63 6c 61 73 73 3d 22 6e 61 76 62 #> [3059] 61 72 2d 62 72 61 6e 64 20 6d 65 2d 32 22 20 68 72 65 66 3d 22 69 #> [3081] 6e 64 65 78 2e 68 74 6d 6c 22 3e 68 74 74 72 32 3c 2f 61 3e 0a 0a #> [3103] 20 20 20 20 3c 73 6d 61 6c 6c 20 63 6c 61 73 73 3d 22 6e 61 76 2d #> [3125] 74 65 78 74 20 74 65 78 74 2d 6d 75 74 65 64 20 6d 65 2d 61 75 74 #> [3147] 6f 22 20 64 61 74 61 2d 62 73 2d 74 6f 67 67 6c 65 3d 22 74 6f 6f #> [3169] 6c 74 69 70 22 20 64 61 74 61 2d 62 73 2d 70 6c 61 63 65 6d 65 6e #> [3191] 74 3d 22 62 6f 74 74 6f 6d 22 20 74 69 74 6c 65 3d 22 52 65 6c 65 #> [3213] 61 73 65 64 20 76 65 72 73 69 6f 6e 22 3e 31 2e 30 2e 35 3c 2f 73 #> [3235] 6d 61 6c 6c 3e 0a 0a 0a 20 20 20 20 3c 62 75 74 74 6f 6e 20 63 6c #> [3257] 61 73 73 3d 22 6e 61 76 62 61 72 2d 74 6f 67 67 6c 65 72 22 20 74 #> [3279] 79 70 65 3d 22 62 75 74 74 6f 6e 22 20 64 61 74 61 2d 62 73 2d 74 #> [3301] 6f 67 67 6c 65 3d 22 63 6f 6c 6c 61 70 73 65 22 20 64 61 74 61 2d #> [3323] 62 73 2d 74 61 72 67 65 74 3d 22 23 6e 61 76 62 61 72 22 20 61 72 #> [3345] 69 61 2d 63 6f 6e 74 72 6f 6c 73 3d 22 6e 61 76 62 61 72 22 20 61 #> [3367] 72 69 61 2d 65 78 70 61 6e 64 65 64 3d 22 66 61 6c 73 65 22 20 61 #> [3389] 72 69 61 2d 6c 61 62 65 6c 3d 22 54 6f 67 67 6c 65 20 6e 61 76 69 #> [3411] 67 61 74 69 6f 6e 22 3e 0a 20 20 20 20 20 20 3c 73 70 61 6e 20 63 #> [3433] 6c 61 73 73 3d 22 6e 61 76 62 61 72 2d 74 6f 67 67 6c 65 72 2d 69 #> [3455] 63 6f 6e 22 3e 3c 2f 73 70 61 6e 3e 0a 20 20 20 20 3c 2f 62 75 74 #> [3477] 74 6f 6e 3e 0a 0a 20 20 20 20 3c 64 69 76 20 69 64 3d 22 6e 61 76 #> [3499] 62 61 72 22 20 63 6c 61 73 73 3d 22 63 6f 6c 6c 61 70 73 65 20 6e #> [3521] 61 76 62 61 72 2d 63 6f 6c 6c 61 70 73 65 20 6d 73 2d 33 22 3e 0a #> [3543] 20 20 20 20 20 20 3c 75 6c 20 63 6c 61 73 73 3d 22 6e 61 76 62 61 #> [3565] 72 2d 6e 61 76 20 6d 65 2d 61 75 74 6f 22 3e 0a 3c 6c 69 20 63 6c #> [3587] 61 73 73 3d 22 6e 61 76 2d 69 74 65 6d 22 3e 3c 61 20 63 6c 61 73 #> [3609] 73 3d 22 6e 61 76 2d 6c 69 6e 6b 22 20 68 72 65 66 3d 22 61 72 74 #> [3631] 69 63 6c 65 73 2f 68 74 74 72 32 2e 68 74 6d 6c 22 3e 47 65 74 20 #> [3653] 73 74 61 72 74 65 64 3c 2f 61 3e 3c 2f 6c 69 3e 0a 3c 6c 69 20 63 #> [3675] 6c 61 73 73 3d 22 6e 61 76 2d 69 74 65 6d 22 3e 3c 61 20 63 6c 61 #> [3697] 73 73 3d 22 6e 61 76 2d 6c 69 6e 6b 22 20 68 72 65 66 3d 22 72 65 #> [3719] 66 65 72 65 6e 63 65 2f 69 6e 64 65 78 2e 68 74 6d 6c 22 3e 52 65 #> [3741] 66 65 72 65 6e 63 65 3c 2f 61 3e 3c 2f 6c 69 3e 0a 3c 6c 69 20 63 #> [3763] 6c 61 73 73 3d 22 6e 61 76 2d 69 74 65 6d 20 64 72 6f 70 64 6f 77 #> [3785] 6e 22 3e 0a 20 20 3c 62 75 74 74 6f 6e 20 63 6c 61 73 73 3d 22 6e #> [3807] 61 76 2d 6c 69 6e 6b 20 64 72 6f 70 64 6f 77 6e 2d 74 6f 67 67 6c #> [3829] 65 22 20 74 79 70 65 3d 22 62 75 74 74 6f 6e 22 20 69 64 3d 22 64 #> [3851] 72 6f 70 64 6f 77 6e 2d 61 72 74 69 63 6c 65 73 22 20 64 61 74 61 #> [3873] 2d 62 73 2d 74 6f 67 67 6c 65 3d 22 64 72 6f 70 64 6f 77 6e 22 20 #> [3895] 61 72 69 61 2d 65 78 70 61 6e 64 65 64 3d 22 66 61 6c 73 65 22 20 #> [3917] 61 72 69 61 2d 68 61 73 70 6f 70 75 70 3d 22 74 72 75 65 22 3e 41 #> [3939] 72 74 69 63 6c 65 73 3c 2f 62 75 74 74 6f 6e 3e 0a 20 20 3c 75 6c #> [3961] 20 63 6c 61 73 73 3d 22 64 72 6f 70 64 6f 77 6e 2d 6d 65 6e 75 22 #> [3983] 20 61 72 69 61 2d 6c 61 62 65 6c 6c 65 64 62 79 3d 22 64 72 6f 70 #> [4005] 64 6f 77 6e 2d 61 72 74 69 63 6c 65 73 22 3e 0a 3c 6c 69 3e 3c 61 #> [4027] 20 63 6c 61 73 73 3d 22 64 72 6f 70 64 6f 77 6e 2d 69 74 65 6d 22 #> [4049] 20 68 72 65 66 3d 22 61 72 74 69 63 6c 65 73 2f 77 72 61 70 70 69 #> [4071] 6e 67 2d 61 70 69 73 2e 68 74 6d 6c 22 3e 57 72 61 70 70 69 6e 67 #> [4093] 20 41 50 49 73 3c 2f 61 3e 3c 2f 6c 69 3e 0a 20 20 20 20 3c 6c 69 #> [4115] 3e 3c 61 20 63 6c 61 73 73 3d 22 64 72 6f 70 64 6f 77 6e 2d 69 74 #> [4137] 65 6d 22 20 68 72 65 66 3d 22 61 72 74 69 63 6c 65 73 2f 6f 61 75 #> [4159] 74 68 2e 68 74 6d 6c 22 3e 4f 41 75 74 68 3c 2f 61 3e 3c 2f 6c 69 #> [4181] 3e 0a 20 20 3c 2f 75 6c 3e 0a 3c 2f 6c 69 3e 0a 3c 6c 69 20 63 6c #> [4203] 61 73 73 3d 22 6e 61 76 2d 69 74 65 6d 20 64 72 6f 70 64 6f 77 6e #> [4225] 22 3e 0a 20 20 3c 62 75 74 74 6f 6e 20 63 6c 61 73 73 3d 22 6e 61 #> [4247] 76 2d 6c 69 6e 6b 20 64 72 6f 70 64 6f 77 6e 2d 74 6f 67 67 6c 65 #> [4269] 22 20 74 79 70 65 3d 22 62 75 74 74 6f 6e 22 20 69 64 3d 22 64 72 #> [4291] 6f 70 64 6f 77 6e 2d 6e 65 77 73 22 20 64 61 74 61 2d 62 73 2d 74 #> [4313] 6f 67 67 6c 65 3d 22 64 72 6f 70 64 6f 77 6e 22 20 61 72 69 61 2d #> [4335] 65 78 70 61 6e 64 65 64 3d 22 66 61 6c 73 65 22 20 61 72 69 61 2d #> [4357] 68 61 73 70 6f 70 75 70 3d 22 74 72 75 65 22 3e 4e 65 77 73 3c 2f #> [4379] 62 75 74 74 6f 6e 3e 0a 20 20 3c 75 6c 20 63 6c 61 73 73 3d 22 64 #> [4401] 72 6f 70 64 6f 77 6e 2d 6d 65 6e 75 22 20 61 72 69 61 2d 6c 61 62 #> [4423] 65 6c 6c 65 64 62 79 3d 22 64 72 6f 70 64 6f 77 6e 2d 6e 65 77 73 #> [4445] 22 3e 0a 3c 6c 69 3e 3c 68 36 20 63 6c 61 73 73 3d 22 64 72 6f 70 #> [4467] 64 6f 77 6e 2d 68 65 61 64 65 72 22 20 64 61 74 61 2d 74 6f 63 2d #> [4489] 73 6b 69 70 3e 52 65 6c 65 61 73 65 73 3c 2f 68 36 3e 3c 2f 6c 69 #> [4511] 3e 0a 20 20 20 20 3c 6c 69 3e 3c 61 20 63 6c 61 73 73 3d 22 65 78 #> [4533] 74 65 72 6e 61 6c 2d 6c 69 6e 6b 20 64 72 6f 70 64 6f 77 6e 2d 69 #> [4555] 74 65 6d 22 20 68 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 77 77 77 #> [4577] 2e 74 69 64 79 76 65 72 73 65 2e 6f 72 67 2f 62 6c 6f 67 2f 32 30 #> [4599] 32 33 2f 31 31 2f 68 74 74 72 32 2d 31 2d 30 2d 30 2f 22 3e 68 74 #> [4621] 74 72 32 20 31 2e 30 2e 30 3c 2f 61 3e 3c 2f 6c 69 3e 0a 20 20 20 #> [4643] 20 3c 6c 69 3e 3c 68 72 20 63 6c 61 73 73 3d 22 64 72 6f 70 64 6f #> [4665] 77 6e 2d 64 69 76 69 64 65 72 22 3e 3c 2f 6c 69 3e 0a 20 20 20 20 #> [4687] 3c 6c 69 3e 3c 61 20 63 6c 61 73 73 3d 22 64 72 6f 70 64 6f 77 6e #> [4709] 2d 69 74 65 6d 22 20 68 72 65 66 3d 22 6e 65 77 73 2f 69 6e 64 65 #> [4731] 78 2e 68 74 6d 6c 22 3e 43 68 61 6e 67 65 6c 6f 67 3c 2f 61 3e 3c #> [4753] 2f 6c 69 3e 0a 20 20 3c 2f 75 6c 3e 0a 3c 2f 6c 69 3e 0a 20 20 20 #> [4775] 20 20 20 3c 2f 75 6c 3e 0a 3c 75 6c 20 63 6c 61 73 73 3d 22 6e 61 #> [4797] 76 62 61 72 2d 6e 61 76 22 3e 0a 3c 6c 69 20 63 6c 61 73 73 3d 22 #> [4819] 6e 61 76 2d 69 74 65 6d 22 3e 3c 66 6f 72 6d 20 63 6c 61 73 73 3d #> [4841] 22 66 6f 72 6d 2d 69 6e 6c 69 6e 65 22 20 72 6f 6c 65 3d 22 73 65 #> [4863] 61 72 63 68 22 3e 0a 20 3c 69 6e 70 75 74 20 63 6c 61 73 73 3d 22 #> [4885] 66 6f 72 6d 2d 63 6f 6e 74 72 6f 6c 22 20 74 79 70 65 3d 22 73 65 #> [4907] 61 72 63 68 22 20 6e 61 6d 65 3d 22 73 65 61 72 63 68 2d 69 6e 70 #> [4929] 75 74 22 20 69 64 3d 22 73 65 61 72 63 68 2d 69 6e 70 75 74 22 20 #> [4951] 61 75 74 6f 63 6f 6d 70 6c 65 74 65 3d 22 6f 66 66 22 20 61 72 69 #> [4973] 61 2d 6c 61 62 65 6c 3d 22 53 65 61 72 63 68 20 73 69 74 65 22 20 #> [4995] 70 6c 61 63 65 68 6f 6c 64 65 72 3d 22 53 65 61 72 63 68 20 66 6f #> [5017] 72 22 20 64 61 74 61 2d 73 65 61 72 63 68 2d 69 6e 64 65 78 3d 22 #> [5039] 73 65 61 72 63 68 2e 6a 73 6f 6e 22 3e 0a 3c 2f 66 6f 72 6d 3e 3c #> [5061] 2f 6c 69 3e 0a 3c 6c 69 20 63 6c 61 73 73 3d 22 6e 61 76 2d 69 74 #> [5083] 65 6d 22 3e 3c 61 20 63 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 6c #> [5105] 2d 6c 69 6e 6b 20 6e 61 76 2d 6c 69 6e 6b 22 20 68 72 65 66 3d 22 #> [5127] 68 74 74 70 73 3a 2f 2f 67 69 74 68 75 62 2e 63 6f 6d 2f 72 2d 6c #> [5149] 69 62 2f 68 74 74 72 32 2f 22 20 61 72 69 61 2d 6c 61 62 65 6c 3d #> [5171] 22 47 69 74 48 75 62 22 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 #> [5193] 66 61 20 66 61 62 20 66 61 2d 67 69 74 68 75 62 20 66 61 2d 6c 67 #> [5215] 22 3e 3c 2f 73 70 61 6e 3e 3c 2f 61 3e 3c 2f 6c 69 3e 0a 20 20 20 #> [5237] 20 20 20 3c 2f 75 6c 3e 0a 3c 2f 64 69 76 3e 0a 0a 0a 20 20 3c 2f #> [5259] 64 69 76 3e 0a 3c 2f 6e 61 76 3e 3c 64 69 76 20 63 6c 61 73 73 3d #> [5281] 22 63 6f 6e 74 61 69 6e 65 72 20 74 65 6d 70 6c 61 74 65 2d 68 6f #> [5303] 6d 65 22 20 69 64 3d 22 63 6f 6e 74 61 69 6e 65 72 22 3e 0a 3c 64 #> [5325] 69 76 20 63 6c 61 73 73 3d 22 72 6f 77 22 3e 0a 20 20 3c 6d 61 69 #> [5347] 6e 20 69 64 3d 22 6d 61 69 6e 22 20 63 6c 61 73 73 3d 22 63 6f 6c #> [5369] 2d 6d 64 2d 39 22 3e 3c 64 69 76 20 63 6c 61 73 73 3d 22 73 65 63 #> [5391] 74 69 6f 6e 20 6c 65 76 65 6c 31 22 3e 0a 3c 64 69 76 20 63 6c 61 #> [5413] 73 73 3d 22 70 61 67 65 2d 68 65 61 64 65 72 22 3e 0a 3c 69 6d 67 #> [5435] 20 73 72 63 3d 22 6c 6f 67 6f 2e 70 6e 67 22 20 63 6c 61 73 73 3d #> [5457] 22 6c 6f 67 6f 22 20 61 6c 74 3d 22 22 3e 3c 68 31 20 69 64 3d 22 #> [5479] 68 74 74 72 32 2d 22 3e 68 74 74 72 32 20 0a 3c 61 20 63 6c 61 73 #> [5501] 73 3d 22 61 6e 63 68 6f 72 22 20 61 72 69 61 2d 6c 61 62 65 6c 3d #> [5523] 22 61 6e 63 68 6f 72 22 20 68 72 65 66 3d 22 23 68 74 74 72 32 2d #> [5545] 22 3e 3c 2f 61 3e 0a 3c 2f 68 31 3e 0a 3c 2f 64 69 76 3e 0a 3c 21 #> [5567] 2d 2d 20 62 61 64 67 65 73 3a 20 73 74 61 72 74 20 2d 2d 3e 0a 0a #> [5589] 3c 70 3e 68 74 74 72 32 20 28 70 72 6f 6e 6f 75 6e 63 65 64 20 68 #> [5611] 69 74 74 65 72 32 29 20 69 73 20 61 20 67 72 6f 75 6e 64 2d 75 70 #> [5633] 20 72 65 77 72 69 74 65 20 6f 66 20 3c 61 20 68 72 65 66 3d 22 68 #> [5655] 74 74 70 73 3a 2f 2f 68 74 74 72 2e 72 2d 6c 69 62 2e 6f 72 67 22 #> [5677] 20 63 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 #> [5699] 3e 68 74 74 72 3c 2f 61 3e 20 74 68 61 74 20 70 72 6f 76 69 64 65 #> [5721] 73 20 61 20 70 69 70 65 61 62 6c 65 20 41 50 49 20 77 69 74 68 20 #> [5743] 61 6e 20 65 78 70 6c 69 63 69 74 20 72 65 71 75 65 73 74 20 6f 62 #> [5765] 6a 65 63 74 20 74 68 61 74 20 73 6f 6c 76 65 73 20 6d 6f 72 65 20 #> [5787] 70 72 6f 62 6c 65 6d 73 20 66 65 6c 74 20 62 79 20 70 61 63 6b 61 #> [5809] 67 65 73 20 74 68 61 74 20 77 72 61 70 20 41 50 49 73 20 28 65 2e #> [5831] 67 2e c2 a0 62 75 69 6c 74 2d 69 6e 20 72 61 74 65 2d 6c 69 6d 69 #> [5853] 74 69 6e 67 2c 20 72 65 74 72 69 65 73 2c 20 4f 41 75 74 68 2c 20 #> [5875] 73 65 63 75 72 65 20 73 65 63 72 65 74 73 2c 20 61 6e 64 20 6d 6f #> [5897] 72 65 29 2e 3c 2f 70 3e 0a 3c 64 69 76 20 63 6c 61 73 73 3d 22 73 #> [5919] 65 63 74 69 6f 6e 20 6c 65 76 65 6c 32 22 3e 0a 3c 68 32 20 69 64 #> [5941] 3d 22 69 6e 73 74 61 6c 6c 61 74 69 6f 6e 22 3e 49 6e 73 74 61 6c #> [5963] 6c 61 74 69 6f 6e 3c 61 20 63 6c 61 73 73 3d 22 61 6e 63 68 6f 72 #> [5985] 22 20 61 72 69 61 2d 6c 61 62 65 6c 3d 22 61 6e 63 68 6f 72 22 20 #> [6007] 68 72 65 66 3d 22 23 69 6e 73 74 61 6c 6c 61 74 69 6f 6e 22 3e 3c #> [6029] 2f 61 3e 0a 3c 2f 68 32 3e 0a 3c 70 3e 59 6f 75 20 63 61 6e 20 69 #> [6051] 6e 73 74 61 6c 6c 20 68 74 74 72 32 20 66 72 6f 6d 20 43 52 41 4e #> [6073] 20 77 69 74 68 3a 3c 2f 70 3e 0a 3c 64 69 76 20 63 6c 61 73 73 3d #> [6095] 22 73 6f 75 72 63 65 43 6f 64 65 22 20 69 64 3d 22 63 62 31 22 3e #> [6117] 3c 70 72 65 20 63 6c 61 73 73 3d 22 64 6f 77 6e 6c 69 74 20 73 6f #> [6139] 75 72 63 65 43 6f 64 65 20 72 22 3e 0a 3c 63 6f 64 65 20 63 6c 61 #> [6161] 73 73 3d 22 73 6f 75 72 63 65 43 6f 64 65 20 52 22 3e 3c 73 70 61 #> [6183] 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 66 75 22 3e 3c 61 20 #> [6205] 68 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 72 64 72 72 2e 69 6f 2f #> [6227] 72 2f 75 74 69 6c 73 2f 69 6e 73 74 61 6c 6c 2e 70 61 63 6b 61 67 #> [6249] 65 73 2e 68 74 6d 6c 22 20 63 6c 61 73 73 3d 22 65 78 74 65 72 6e #> [6271] 61 6c 2d 6c 69 6e 6b 22 3e 69 6e 73 74 61 6c 6c 2e 70 61 63 6b 61 #> [6293] 67 65 73 3c 2f 61 3e 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c #> [6315] 61 73 73 3d 22 6f 70 22 3e 28 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e #> [6337] 20 63 6c 61 73 73 3d 22 73 74 22 3e 22 68 74 74 72 32 22 3c 2f 73 #> [6359] 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 29 #> [6381] 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 3c 2f 63 6f 64 65 3e 3c #> [6403] 2f 70 72 65 3e 3c 2f 64 69 76 3e 0a 3c 2f 64 69 76 3e 0a 3c 64 69 #> [6425] 76 20 63 6c 61 73 73 3d 22 73 65 63 74 69 6f 6e 20 6c 65 76 65 6c #> [6447] 32 22 3e 0a 3c 68 32 20 69 64 3d 22 75 73 61 67 65 22 3e 55 73 61 #> [6469] 67 65 3c 61 20 63 6c 61 73 73 3d 22 61 6e 63 68 6f 72 22 20 61 72 #> [6491] 69 61 2d 6c 61 62 65 6c 3d 22 61 6e 63 68 6f 72 22 20 68 72 65 66 #> [6513] 3d 22 23 75 73 61 67 65 22 3e 3c 2f 61 3e 0a 3c 2f 68 32 3e 0a 3c #> [6535] 70 3e 54 6f 20 75 73 65 20 68 74 74 72 32 2c 20 73 74 61 72 74 20 #> [6557] 62 79 20 63 72 65 61 74 69 6e 67 20 61 20 3c 73 74 72 6f 6e 67 3e #> [6579] 72 65 71 75 65 73 74 3c 2f 73 74 72 6f 6e 67 3e 3a 3c 2f 70 3e 0a #> [6601] 3c 64 69 76 20 63 6c 61 73 73 3d 22 73 6f 75 72 63 65 43 6f 64 65 #> [6623] 22 20 69 64 3d 22 63 62 32 22 3e 3c 70 72 65 20 63 6c 61 73 73 3d #> [6645] 22 64 6f 77 6e 6c 69 74 20 73 6f 75 72 63 65 43 6f 64 65 20 72 22 #> [6667] 3e 0a 3c 63 6f 64 65 20 63 6c 61 73 73 3d 22 73 6f 75 72 63 65 43 #> [6689] 6f 64 65 20 52 22 3e 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 #> [6711] 73 73 3d 22 6b 77 22 3e 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 #> [6733] 3a 2f 2f 72 64 72 72 2e 69 6f 2f 72 2f 62 61 73 65 2f 6c 69 62 72 #> [6755] 61 72 79 2e 68 74 6d 6c 22 20 63 6c 61 73 73 3d 22 65 78 74 65 72 #> [6777] 6e 61 6c 2d 6c 69 6e 6b 22 3e 6c 69 62 72 61 72 79 3c 2f 61 3e 3c #> [6799] 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 #> [6821] 3e 28 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 #> [6843] 76 61 22 3e 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 68 #> [6865] 74 74 72 32 2e 72 2d 6c 69 62 2e 6f 72 67 22 3e 68 74 74 72 32 3c #> [6887] 2f 61 3e 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d #> [6909] 22 6f 70 22 3e 29 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c #> [6931] 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 #> [6953] 61 6e 20 63 6c 61 73 73 3d 22 76 61 22 3e 72 65 71 3c 2f 73 70 61 #> [6975] 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 26 6c #> [6997] 74 3b 2d 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 #> [7019] 3d 22 66 75 22 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e #> [7041] 63 65 2f 72 65 71 75 65 73 74 2e 68 74 6d 6c 22 3e 72 65 71 75 65 #> [7063] 73 74 3c 2f 61 3e 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 #> [7085] 73 73 3d 22 6f 70 22 3e 28 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 #> [7107] 63 6c 61 73 73 3d 22 73 74 22 3e 22 68 74 74 70 73 3a 2f 2f 72 2d #> [7129] 70 72 6f 6a 65 63 74 2e 6f 72 67 22 3c 2f 73 70 61 6e 3e 3c 73 70 #> [7151] 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 29 3c 2f 73 70 61 6e 3e #> [7173] 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c #> [7195] 61 73 73 3d 22 76 61 22 3e 72 65 71 3c 2f 73 70 61 6e 3e 3c 2f 73 #> [7217] 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 #> [7239] 3d 22 63 6f 22 3e 23 26 67 74 3b 20 26 6c 74 3b 68 74 74 72 32 5f #> [7261] 72 65 71 75 65 73 74 26 67 74 3b 3c 2f 73 70 61 6e 3e 3c 2f 73 70 #> [7283] 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d #> [7305] 22 63 6f 22 3e 23 26 67 74 3b 20 47 45 54 20 68 74 74 70 73 3a 2f #> [7327] 2f 72 2d 70 72 6f 6a 65 63 74 2e 6f 72 67 3c 2f 73 70 61 6e 3e 3c #> [7349] 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 #> [7371] 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 42 6f 64 79 3a 20 65 6d #> [7393] 70 74 79 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 3c 2f 63 6f 64 #> [7415] 65 3e 3c 2f 70 72 65 3e 3c 2f 64 69 76 3e 0a 3c 70 3e 59 6f 75 20 #> [7437] 63 61 6e 20 74 61 69 6c 6f 72 20 74 68 69 73 20 72 65 71 75 65 73 #> [7459] 74 20 77 69 74 68 20 74 68 65 20 3c 63 6f 64 65 3e 72 65 71 5f 3c #> [7481] 2f 63 6f 64 65 3e 20 66 61 6d 69 6c 79 20 6f 66 20 66 75 6e 63 74 #> [7503] 69 6f 6e 73 3a 3c 2f 70 3e 0a 3c 64 69 76 20 63 6c 61 73 73 3d 22 #> [7525] 73 6f 75 72 63 65 43 6f 64 65 22 20 69 64 3d 22 63 62 33 22 3e 3c #> [7547] 70 72 65 20 63 6c 61 73 73 3d 22 64 6f 77 6e 6c 69 74 20 73 6f 75 #> [7569] 72 63 65 43 6f 64 65 20 72 22 3e 0a 3c 63 6f 64 65 20 63 6c 61 73 #> [7591] 73 3d 22 73 6f 75 72 63 65 43 6f 64 65 20 52 22 3e 3c 73 70 61 6e #> [7613] 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 20 41 64 #> [7635] 64 20 63 75 73 74 6f 6d 20 68 65 61 64 65 72 73 3c 2f 73 70 61 6e #> [7657] 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 #> [7679] 6c 61 73 73 3d 22 76 61 22 3e 72 65 71 3c 2f 73 70 61 6e 3e 20 3c #> [7701] 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 7c 26 67 74 3b 3c #> [7723] 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 66 75 #> [7745] 22 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 2f 72 #> [7767] 65 71 5f 68 65 61 64 65 72 73 2e 68 74 6d 6c 22 3e 72 65 71 5f 68 #> [7789] 65 61 64 65 72 73 3c 2f 61 3e 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e #> [7811] 20 63 6c 61 73 73 3d 22 6f 70 22 3e 28 3c 2f 73 70 61 6e 3e 3c 73 #> [7833] 70 61 6e 20 63 6c 61 73 73 3d 22 73 74 22 3e 22 41 63 63 65 70 74 #> [7855] 22 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 #> [7877] 6f 70 22 3e 3d 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 #> [7899] 73 73 3d 22 73 74 22 3e 22 61 70 70 6c 69 63 61 74 69 6f 6e 2f 6a #> [7921] 73 6f 6e 22 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 #> [7943] 3d 22 6f 70 22 3e 29 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a #> [7965] 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 #> [7987] 3e 23 26 67 74 3b 20 26 6c 74 3b 68 74 74 72 32 5f 72 65 71 75 65 #> [8009] 73 74 26 67 74 3b 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c #> [8031] 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e #> [8053] 23 26 67 74 3b 20 47 45 54 20 68 74 74 70 73 3a 2f 2f 72 2d 70 72 #> [8075] 6f 6a 65 63 74 2e 6f 72 67 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e #> [8097] 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 #> [8119] 6f 22 3e 23 26 67 74 3b 20 48 65 61 64 65 72 73 3a 3c 2f 73 70 61 #> [8141] 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 #> [8163] 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 e2 80 a2 20 41 #> [8185] 63 63 65 70 74 3a 20 27 61 70 70 6c 69 63 61 74 69 6f 6e 2f 6a 73 #> [8207] 6f 6e 27 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 #> [8229] 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 #> [8251] 74 3b 20 42 6f 64 79 3a 20 65 6d 70 74 79 3c 2f 73 70 61 6e 3e 3c #> [8273] 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c #> [8295] 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e #> [8317] 23 20 41 64 64 20 61 20 62 6f 64 79 2c 20 74 75 72 6e 69 6e 67 20 #> [8339] 69 74 20 69 6e 74 6f 20 61 20 50 4f 53 54 3c 2f 73 70 61 6e 3e 3c #> [8361] 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 #> [8383] 73 73 3d 22 76 61 22 3e 72 65 71 3c 2f 73 70 61 6e 3e 20 3c 73 70 #> [8405] 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 7c 26 67 74 3b 3c 2f 73 #> [8427] 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 66 75 22 3e #> [8449] 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 2f 72 65 71 #> [8471] 5f 62 6f 64 79 2e 68 74 6d 6c 22 3e 72 65 71 5f 62 6f 64 79 5f 6a #> [8493] 73 6f 6e 3c 2f 61 3e 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c #> [8515] 61 73 73 3d 22 6f 70 22 3e 28 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e #> [8537] 20 63 6c 61 73 73 3d 22 66 75 22 3e 3c 61 20 68 72 65 66 3d 22 68 #> [8559] 74 74 70 73 3a 2f 2f 72 64 72 72 2e 69 6f 2f 72 2f 62 61 73 65 2f #> [8581] 6c 69 73 74 2e 68 74 6d 6c 22 20 63 6c 61 73 73 3d 22 65 78 74 65 #> [8603] 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 6c 69 73 74 3c 2f 61 3e 3c 2f 73 #> [8625] 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 28 #> [8647] 3c 2f 73 70 61 6e 3e 78 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 #> [8669] 6f 70 22 3e 3d 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 #> [8691] 73 73 3d 22 66 6c 22 3e 31 3c 2f 73 70 61 6e 3e 2c 20 79 20 3c 73 #> [8713] 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 3d 3c 2f 73 70 61 6e #> [8735] 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 66 6c 22 3e 32 3c 2f #> [8757] 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e #> [8779] 29 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f #> [8801] 70 22 3e 29 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 #> [8823] 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 #> [8845] 67 74 3b 20 26 6c 74 3b 68 74 74 72 32 5f 72 65 71 75 65 73 74 26 #> [8867] 67 74 3b 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 #> [8889] 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 #> [8911] 74 3b 20 50 4f 53 54 20 68 74 74 70 73 3a 2f 2f 72 2d 70 72 6f 6a #> [8933] 65 63 74 2e 6f 72 67 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a #> [8955] 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 #> [8977] 3e 23 26 67 74 3b 20 42 6f 64 79 3a 20 6a 73 6f 6e 20 65 6e 63 6f #> [8999] 64 65 64 20 64 61 74 61 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e #> [9021] 0a 3c 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c #> [9043] 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 20 4d 6f 64 69 #> [9065] 66 79 20 74 68 65 20 70 61 74 68 20 69 6e 20 74 68 65 20 75 72 6c #> [9087] 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c #> [9109] 73 70 61 6e 20 63 6c 61 73 73 3d 22 76 61 22 3e 72 65 71 3c 2f 73 #> [9131] 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e #> [9153] 7c 26 67 74 3b 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 #> [9175] 73 73 3d 22 66 75 22 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 #> [9197] 65 6e 63 65 2f 72 65 71 5f 75 72 6c 2e 68 74 6d 6c 22 3e 72 65 71 #> [9219] 5f 75 72 6c 5f 70 61 74 68 3c 2f 61 3e 3c 2f 73 70 61 6e 3e 3c 73 #> [9241] 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 28 3c 2f 73 70 61 6e #> [9263] 3e 70 61 74 68 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 #> [9285] 3e 3d 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d #> [9307] 22 73 74 22 3e 22 70 61 74 68 2f 74 6f 2f 6d 79 2f 66 69 6c 65 22 #> [9329] 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 #> [9351] 22 3e 29 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 #> [9373] 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 #> [9395] 74 3b 20 26 6c 74 3b 68 74 74 72 32 5f 72 65 71 75 65 73 74 26 67 #> [9417] 74 3b 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e #> [9439] 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 #> [9461] 3b 20 47 45 54 20 68 74 74 70 73 3a 2f 2f 72 2d 70 72 6f 6a 65 63 #> [9483] 74 2e 6f 72 67 2f 70 61 74 68 2f 74 6f 2f 6d 79 2f 66 69 6c 65 3c #> [9505] 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 #> [9527] 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 42 #> [9549] 6f 64 79 3a 20 65 6d 70 74 79 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 #> [9571] 6e 3e 0a 3c 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e #> [9593] 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 20 41 75 #> [9615] 74 6f 6d 61 74 69 63 61 6c 6c 79 20 72 65 74 72 79 20 69 66 20 74 #> [9637] 68 65 20 72 65 71 75 65 73 74 20 66 61 69 6c 73 3c 2f 73 70 61 6e #> [9659] 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 #> [9681] 6c 61 73 73 3d 22 76 61 22 3e 72 65 71 3c 2f 73 70 61 6e 3e 20 3c #> [9703] 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 7c 26 67 74 3b 3c #> [9725] 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 66 75 #> [9747] 22 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 2f 72 #> [9769] 65 71 5f 72 65 74 72 79 2e 68 74 6d 6c 22 3e 72 65 71 5f 72 65 74 #> [9791] 72 79 3c 2f 61 3e 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 #> [9813] 73 73 3d 22 6f 70 22 3e 28 3c 2f 73 70 61 6e 3e 6d 61 78 5f 74 72 #> [9835] 69 65 73 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 3d #> [9857] 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 66 #> [9879] 6c 22 3e 35 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 #> [9901] 3d 22 6f 70 22 3e 29 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a #> [9923] 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 #> [9945] 3e 23 26 67 74 3b 20 26 6c 74 3b 68 74 74 72 32 5f 72 65 71 75 65 #> [9967] 73 74 26 67 74 3b 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c #> [9989] 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e #> [10011] 23 26 67 74 3b 20 47 45 54 20 68 74 74 70 73 3a 2f 2f 72 2d 70 72 #> [10033] 6f 6a 65 63 74 2e 6f 72 67 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e #> [10055] 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 #> [10077] 6f 22 3e 23 26 67 74 3b 20 42 6f 64 79 3a 20 65 6d 70 74 79 3c 2f #> [10099] 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 #> [10121] 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 50 6f #> [10143] 6c 69 63 69 65 73 3a 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a #> [10165] 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 #> [10187] 3e 23 26 67 74 3b 20 e2 80 a2 20 72 65 74 72 79 5f 6d 61 78 5f 74 #> [10209] 72 69 65 73 3a 20 35 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a #> [10231] 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 #> [10253] 3e 23 26 67 74 3b 20 e2 80 a2 20 72 65 74 72 79 5f 6f 6e 5f 66 61 #> [10275] 69 6c 75 72 65 3a 20 46 41 4c 53 45 3c 2f 73 70 61 6e 3e 3c 2f 73 #> [10297] 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 #> [10319] 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 20 #> [10341] 43 68 61 6e 67 65 20 74 68 65 20 48 54 54 50 20 6d 65 74 68 6f 64 #> [10363] 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c #> [10385] 73 70 61 6e 20 63 6c 61 73 73 3d 22 76 61 22 3e 72 65 71 3c 2f 73 #> [10407] 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e #> [10429] 7c 26 67 74 3b 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 #> [10451] 73 73 3d 22 66 75 22 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 #> [10473] 65 6e 63 65 2f 72 65 71 5f 6d 65 74 68 6f 64 2e 68 74 6d 6c 22 3e #> [10495] 72 65 71 5f 6d 65 74 68 6f 64 3c 2f 61 3e 3c 2f 73 70 61 6e 3e 3c #> [10517] 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 28 3c 2f 73 70 61 #> [10539] 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 73 74 22 3e 22 50 41 #> [10561] 54 43 48 22 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 #> [10583] 3d 22 6f 70 22 3e 29 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a #> [10605] 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 #> [10627] 3e 23 26 67 74 3b 20 26 6c 74 3b 68 74 74 72 32 5f 72 65 71 75 65 #> [10649] 73 74 26 67 74 3b 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c #> [10671] 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e #> [10693] 23 26 67 74 3b 20 50 41 54 43 48 20 68 74 74 70 73 3a 2f 2f 72 2d #> [10715] 70 72 6f 6a 65 63 74 2e 6f 72 67 3c 2f 73 70 61 6e 3e 3c 2f 73 70 #> [10737] 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d #> [10759] 22 63 6f 22 3e 23 26 67 74 3b 20 42 6f 64 79 3a 20 65 6d 70 74 79 #> [10781] 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 3c 2f 63 6f 64 65 3e 3c #> [10803] 2f 70 72 65 3e 3c 2f 64 69 76 3e 0a 3c 70 3e 41 6e 64 20 73 65 65 #> [10825] 20 65 78 61 63 74 6c 79 20 77 68 61 74 20 68 74 74 72 32 20 77 69 #> [10847] 6c 6c 20 73 65 6e 64 20 74 6f 20 74 68 65 20 73 65 72 76 65 72 20 #> [10869] 77 69 74 68 20 3c 63 6f 64 65 3e 3c 61 20 68 72 65 66 3d 22 72 65 #> [10891] 66 65 72 65 6e 63 65 2f 72 65 71 5f 64 72 79 5f 72 75 6e 2e 68 74 #> [10913] 6d 6c 22 3e 72 65 71 5f 64 72 79 5f 72 75 6e 28 29 3c 2f 61 3e 3c #> [10935] 2f 63 6f 64 65 3e 3a 3c 2f 70 3e 0a 3c 64 69 76 20 63 6c 61 73 73 #> [10957] 3d 22 73 6f 75 72 63 65 43 6f 64 65 22 20 69 64 3d 22 63 62 34 22 #> [10979] 3e 3c 70 72 65 20 63 6c 61 73 73 3d 22 64 6f 77 6e 6c 69 74 20 73 #> [11001] 6f 75 72 63 65 43 6f 64 65 20 72 22 3e 0a 3c 63 6f 64 65 20 63 6c #> [11023] 61 73 73 3d 22 73 6f 75 72 63 65 43 6f 64 65 20 52 22 3e 3c 73 70 #> [11045] 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 76 61 22 3e 72 65 #> [11067] 71 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 #> [11089] 6f 70 22 3e 7c 26 67 74 3b 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e #> [11111] 20 63 6c 61 73 73 3d 22 66 75 22 3e 3c 61 20 68 72 65 66 3d 22 72 #> [11133] 65 66 65 72 65 6e 63 65 2f 72 65 71 5f 64 72 79 5f 72 75 6e 2e 68 #> [11155] 74 6d 6c 22 3e 72 65 71 5f 64 72 79 5f 72 75 6e 3c 2f 61 3e 3c 2f #> [11177] 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e #> [11199] 28 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f #> [11221] 70 22 3e 29 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 #> [11243] 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 #> [11265] 67 74 3b 20 47 45 54 20 2f 20 48 54 54 50 2f 31 2e 31 3c 2f 73 70 #> [11287] 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e #> [11309] 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 48 6f 73 74 #> [11331] 3a 20 72 2d 70 72 6f 6a 65 63 74 2e 6f 72 67 3c 2f 73 70 61 6e 3e #> [11353] 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c #> [11375] 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 55 73 65 72 2d 41 67 #> [11397] 65 6e 74 3a 20 68 74 74 72 32 2f 31 2e 30 2e 33 2e 39 30 30 30 20 #> [11419] 72 2d 63 75 72 6c 2f 35 2e 32 2e 32 20 6c 69 62 63 75 72 6c 2f 38 #> [11441] 2e 36 2e 30 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 #> [11463] 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 #> [11485] 67 74 3b 20 41 63 63 65 70 74 3a 20 2a 2f 2a 3c 2f 73 70 61 6e 3e #> [11507] 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c #> [11529] 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 41 63 63 65 70 74 2d #> [11551] 45 6e 63 6f 64 69 6e 67 3a 20 64 65 66 6c 61 74 65 2c 20 67 7a 69 #> [11573] 70 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 3c 2f 63 6f 64 65 3e #> [11595] 3c 2f 70 72 65 3e 3c 2f 64 69 76 3e 0a 3c 70 3e 55 73 65 20 3c 63 #> [11617] 6f 64 65 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 #> [11639] 2f 72 65 71 5f 70 65 72 66 6f 72 6d 2e 68 74 6d 6c 22 3e 72 65 71 #> [11661] 5f 70 65 72 66 6f 72 6d 28 29 3c 2f 61 3e 3c 2f 63 6f 64 65 3e 20 #> [11683] 74 6f 20 70 65 72 66 6f 72 6d 20 74 68 65 20 72 65 71 75 65 73 74 #> [11705] 2c 20 72 65 74 72 69 65 76 69 6e 67 20 61 20 3c 73 74 72 6f 6e 67 #> [11727] 3e 72 65 73 70 6f 6e 73 65 3c 2f 73 74 72 6f 6e 67 3e 3a 3c 2f 70 #> [11749] 3e 0a 3c 64 69 76 20 63 6c 61 73 73 3d 22 73 6f 75 72 63 65 43 6f #> [11771] 64 65 22 20 69 64 3d 22 63 62 35 22 3e 3c 70 72 65 20 63 6c 61 73 #> [11793] 73 3d 22 64 6f 77 6e 6c 69 74 20 73 6f 75 72 63 65 43 6f 64 65 20 #> [11815] 72 22 3e 0a 3c 63 6f 64 65 20 63 6c 61 73 73 3d 22 73 6f 75 72 63 #> [11837] 65 43 6f 64 65 20 52 22 3e 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 #> [11859] 6c 61 73 73 3d 22 76 61 22 3e 72 65 73 70 3c 2f 73 70 61 6e 3e 20 #> [11881] 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 26 6c 74 3b 2d #> [11903] 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 66 #> [11925] 75 22 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 2f #> [11947] 72 65 71 5f 70 65 72 66 6f 72 6d 2e 68 74 6d 6c 22 3e 72 65 71 5f #> [11969] 70 65 72 66 6f 72 6d 3c 2f 61 3e 3c 2f 73 70 61 6e 3e 3c 73 70 61 #> [11991] 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 28 3c 2f 73 70 61 6e 3e 3c #> [12013] 73 70 61 6e 20 63 6c 61 73 73 3d 22 76 61 22 3e 72 65 71 3c 2f 73 #> [12035] 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 29 #> [12057] 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c #> [12079] 73 70 61 6e 20 63 6c 61 73 73 3d 22 76 61 22 3e 72 65 73 70 3c 2f #> [12101] 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 #> [12123] 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 26 6c #> [12145] 74 3b 68 74 74 72 32 5f 72 65 73 70 6f 6e 73 65 26 67 74 3b 3c 2f #> [12167] 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 #> [12189] 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 47 45 #> [12211] 54 20 68 74 74 70 73 3a 2f 2f 77 77 77 2e 72 2d 70 72 6f 6a 65 63 #> [12233] 74 2e 6f 72 67 2f 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c #> [12255] 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e #> [12277] 23 26 67 74 3b 20 53 74 61 74 75 73 3a 20 32 30 30 20 4f 4b 3c 2f #> [12299] 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 #> [12321] 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 43 6f #> [12343] 6e 74 65 6e 74 2d 54 79 70 65 3a 20 74 65 78 74 2f 68 74 6d 6c 3c #> [12365] 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 #> [12387] 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 42 #> [12409] 6f 64 79 3a 20 49 6e 20 6d 65 6d 6f 72 79 20 28 36 39 35 31 20 62 #> [12431] 79 74 65 73 29 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 3c 2f 63 #> [12453] 6f 64 65 3e 3c 2f 70 72 65 3e 3c 2f 64 69 76 3e 0a 3c 70 3e 54 68 #> [12475] 65 20 3c 63 6f 64 65 3e 72 65 73 70 5f 3c 2f 63 6f 64 65 3e 20 66 #> [12497] 75 6e 63 74 69 6f 6e 73 20 68 65 6c 70 20 79 6f 75 20 65 78 74 72 #> [12519] 61 63 74 20 76 61 72 69 6f 75 73 20 75 73 65 66 75 6c 20 63 6f 6d #> [12541] 70 6f 6e 65 6e 74 73 20 6f 66 20 74 68 65 20 72 65 73 70 6f 6e 73 #> [12563] 65 3a 3c 2f 70 3e 0a 3c 64 69 76 20 63 6c 61 73 73 3d 22 73 6f 75 #> [12585] 72 63 65 43 6f 64 65 22 20 69 64 3d 22 63 62 36 22 3e 3c 70 72 65 #> [12607] 20 63 6c 61 73 73 3d 22 64 6f 77 6e 6c 69 74 20 73 6f 75 72 63 65 #> [12629] 43 6f 64 65 20 72 22 3e 0a 3c 63 6f 64 65 20 63 6c 61 73 73 3d 22 #> [12651] 73 6f 75 72 63 65 43 6f 64 65 20 52 22 3e 3c 73 70 61 6e 3e 3c 73 #> [12673] 70 61 6e 20 63 6c 61 73 73 3d 22 76 61 22 3e 72 65 73 70 3c 2f 73 #> [12695] 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e #> [12717] 7c 26 67 74 3b 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 #> [12739] 73 73 3d 22 66 75 22 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 #> [12761] 65 6e 63 65 2f 72 65 73 70 5f 63 6f 6e 74 65 6e 74 5f 74 79 70 65 #> [12783] 2e 68 74 6d 6c 22 3e 72 65 73 70 5f 63 6f 6e 74 65 6e 74 5f 74 79 #> [12805] 70 65 3c 2f 61 3e 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 #> [12827] 73 73 3d 22 6f 70 22 3e 28 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 #> [12849] 63 6c 61 73 73 3d 22 6f 70 22 3e 29 3c 2f 73 70 61 6e 3e 3c 2f 73 #> [12871] 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 #> [12893] 3d 22 63 6f 22 3e 23 26 67 74 3b 20 5b 31 5d 20 22 74 65 78 74 2f #> [12915] 68 74 6d 6c 22 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 #> [12937] 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 76 61 22 3e 72 #> [12959] 65 73 70 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 #> [12981] 3d 22 6f 70 22 3e 7c 26 67 74 3b 3c 2f 73 70 61 6e 3e 20 3c 73 70 #> [13003] 61 6e 20 63 6c 61 73 73 3d 22 66 75 22 3e 3c 61 20 68 72 65 66 3d #> [13025] 22 72 65 66 65 72 65 6e 63 65 2f 72 65 73 70 5f 73 74 61 74 75 73 #> [13047] 2e 68 74 6d 6c 22 3e 72 65 73 70 5f 73 74 61 74 75 73 5f 64 65 73 #> [13069] 63 3c 2f 61 3e 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 #> [13091] 73 3d 22 6f 70 22 3e 28 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 #> [13113] 6c 61 73 73 3d 22 6f 70 22 3e 29 3c 2f 73 70 61 6e 3e 3c 2f 73 70 #> [13135] 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d #> [13157] 22 63 6f 22 3e 23 26 67 74 3b 20 5b 31 5d 20 22 4f 4b 22 3c 2f 73 #> [13179] 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 #> [13201] 6e 20 63 6c 61 73 73 3d 22 76 61 22 3e 72 65 73 70 3c 2f 73 70 61 #> [13223] 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 7c 26 #> [13245] 67 74 3b 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 #> [13267] 3d 22 66 75 22 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e #> [13289] 63 65 2f 72 65 73 70 5f 62 6f 64 79 5f 72 61 77 2e 68 74 6d 6c 22 #> [13311] 3e 72 65 73 70 5f 62 6f 64 79 5f 68 74 6d 6c 3c 2f 61 3e 3c 2f 73 #> [13333] 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 28 #> [13355] 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 #> [13377] 22 3e 29 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 #> [13399] 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 #> [13421] 74 3b 20 7b 68 74 6d 6c 5f 64 6f 63 75 6d 65 6e 74 7d 3c 2f 73 70 #> [13443] 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e #> [13465] 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 26 6c 74 3b #> [13487] 68 74 6d 6c 20 6c 61 6e 67 3d 22 65 6e 22 26 67 74 3b 3c 2f 73 70 #> [13509] 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e #> [13531] 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 5b 31 5d 20 #> [13553] 26 6c 74 3b 68 65 61 64 26 67 74 3b 5c 6e 26 6c 74 3b 6d 65 74 61 #> [13575] 20 68 74 74 70 2d 65 71 75 69 76 3d 22 43 6f 6e 74 65 6e 74 2d 54 #> [13597] 79 70 65 22 20 63 6f 6e 74 65 6e 74 3d 22 74 65 78 74 2f 68 74 6d #> [13619] 6c 3b 20 63 68 61 72 73 65 74 3d 55 54 46 2d 38 20 2e 2e 2e 3c 2f #> [13641] 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 #> [13663] 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 5b 32 #> [13685] 5d 20 26 6c 74 3b 62 6f 64 79 26 67 74 3b 5c 6e 20 20 20 20 26 6c #> [13707] 74 3b 64 69 76 20 63 6c 61 73 73 3d 22 63 6f 6e 74 61 69 6e 65 72 #> [13729] 20 70 61 67 65 22 26 67 74 3b 5c 6e 20 20 20 20 20 20 26 6c 74 3b #> [13751] 64 69 76 20 63 6c 61 73 73 3d 22 72 6f 77 22 26 67 74 3b 5c 6e 20 #> [13773] 20 20 20 20 20 20 2e 2e 2e 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e #> [13795] 3e 3c 2f 63 6f 64 65 3e 3c 2f 70 72 65 3e 3c 2f 64 69 76 3e 0a 3c #> [13817] 2f 64 69 76 3e 0a 3c 64 69 76 20 63 6c 61 73 73 3d 22 73 65 63 74 #> [13839] 69 6f 6e 20 6c 65 76 65 6c 32 22 3e 0a 3c 68 32 20 69 64 3d 22 6d #> [13861] 61 6a 6f 72 2d 64 69 66 66 65 72 65 6e 63 65 73 2d 74 6f 2d 68 74 #> [13883] 74 72 22 3e 4d 61 6a 6f 72 20 64 69 66 66 65 72 65 6e 63 65 73 20 #> [13905] 74 6f 20 68 74 74 72 3c 61 20 63 6c 61 73 73 3d 22 61 6e 63 68 6f #> [13927] 72 22 20 61 72 69 61 2d 6c 61 62 65 6c 3d 22 61 6e 63 68 6f 72 22 #> [13949] 20 68 72 65 66 3d 22 23 6d 61 6a 6f 72 2d 64 69 66 66 65 72 65 6e #> [13971] 63 65 73 2d 74 6f 2d 68 74 74 72 22 3e 3c 2f 61 3e 0a 3c 2f 68 32 #> [13993] 3e 0a 3c 75 6c 3e 0a 3c 6c 69 3e 3c 70 3e 59 6f 75 20 63 61 6e 20 #> [14015] 6e 6f 77 20 63 72 65 61 74 65 20 61 6e 64 20 6d 6f 64 69 66 79 20 #> [14037] 61 20 72 65 71 75 65 73 74 20 77 69 74 68 6f 75 74 20 70 65 72 66 #> [14059] 6f 72 6d 69 6e 67 20 69 74 2e 20 54 68 69 73 20 6d 65 61 6e 73 20 #> [14081] 74 68 61 74 20 74 68 65 72 65 e2 80 99 73 20 6e 6f 77 20 61 20 73 #> [14103] 69 6e 67 6c 65 20 66 75 6e 63 74 69 6f 6e 20 74 6f 20 70 65 72 66 #> [14125] 6f 72 6d 20 74 68 65 20 72 65 71 75 65 73 74 20 61 6e 64 20 66 65 #> [14147] 74 63 68 20 74 68 65 20 72 65 73 75 6c 74 3a 20 3c 63 6f 64 65 3e #> [14169] 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 2f 72 65 71 #> [14191] 5f 70 65 72 66 6f 72 6d 2e 68 74 6d 6c 22 3e 72 65 71 5f 70 65 72 #> [14213] 66 6f 72 6d 28 29 3c 2f 61 3e 3c 2f 63 6f 64 65 3e 2e 20 3c 63 6f #> [14235] 64 65 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 2f #> [14257] 72 65 71 5f 70 65 72 66 6f 72 6d 2e 68 74 6d 6c 22 3e 72 65 71 5f #> [14279] 70 65 72 66 6f 72 6d 28 29 3c 2f 61 3e 3c 2f 63 6f 64 65 3e 20 72 #> [14301] 65 70 6c 61 63 65 73 20 3c 63 6f 64 65 3e 3c 61 20 68 72 65 66 3d #> [14323] 22 68 74 74 70 73 3a 2f 2f 68 74 74 72 2e 72 2d 6c 69 62 2e 6f 72 #> [14345] 67 2f 72 65 66 65 72 65 6e 63 65 2f 47 45 54 2e 68 74 6d 6c 22 20 #> [14367] 63 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e #> [14389] 68 74 74 72 3a 3a 47 45 54 28 29 3c 2f 61 3e 3c 2f 63 6f 64 65 3e #> [14411] 2c 20 3c 63 6f 64 65 3e 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 #> [14433] 3a 2f 2f 68 74 74 72 2e 72 2d 6c 69 62 2e 6f 72 67 2f 72 65 66 65 #> [14455] 72 65 6e 63 65 2f 50 4f 53 54 2e 68 74 6d 6c 22 20 63 6c 61 73 73 #> [14477] 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 68 74 74 72 3a #> [14499] 3a 50 4f 53 54 28 29 3c 2f 61 3e 3c 2f 63 6f 64 65 3e 2c 20 3c 63 #> [14521] 6f 64 65 3e 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 68 #> [14543] 74 74 72 2e 72 2d 6c 69 62 2e 6f 72 67 2f 72 65 66 65 72 65 6e 63 #> [14565] 65 2f 44 45 4c 45 54 45 2e 68 74 6d 6c 22 20 63 6c 61 73 73 3d 22 #> [14587] 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 68 74 74 72 3a 3a 44 #> [14609] 45 4c 45 54 45 28 29 3c 2f 61 3e 3c 2f 63 6f 64 65 3e 2c 20 61 6e #> [14631] 64 20 6d 6f 72 65 2e 3c 2f 70 3e 3c 2f 6c 69 3e 0a 3c 6c 69 3e 3c #> [14653] 70 3e 48 54 54 50 20 65 72 72 6f 72 73 20 61 72 65 20 61 75 74 6f #> [14675] 6d 61 74 69 63 61 6c 6c 79 20 63 6f 6e 76 65 72 74 65 64 20 69 6e #> [14697] 74 6f 20 52 20 65 72 72 6f 72 73 2e 20 55 73 65 20 3c 63 6f 64 65 #> [14719] 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 2f 72 65 #> [14741] 71 5f 65 72 72 6f 72 2e 68 74 6d 6c 22 3e 72 65 71 5f 65 72 72 6f #> [14763] 72 28 29 3c 2f 61 3e 3c 2f 63 6f 64 65 3e 20 74 6f 20 6f 76 65 72 #> [14785] 72 69 64 65 20 74 68 65 20 64 65 66 61 75 6c 74 73 20 28 77 68 69 #> [14807] 63 68 20 74 75 72 6e 20 61 6c 6c 20 34 78 78 20 61 6e 64 20 35 78 #> [14829] 78 20 72 65 73 70 6f 6e 73 65 73 20 69 6e 74 6f 20 65 72 72 6f 72 #> [14851] 73 29 20 6f 72 20 74 6f 20 61 64 64 20 61 64 64 69 74 69 6f 6e 61 #> [14873] 6c 20 64 65 74 61 69 6c 73 20 74 6f 20 74 68 65 20 65 72 72 6f 72 #> [14895] 20 6d 65 73 73 61 67 65 2e 3c 2f 70 3e 3c 2f 6c 69 3e 0a 3c 6c 69 #> [14917] 3e 3c 70 3e 59 6f 75 20 63 61 6e 20 61 75 74 6f 6d 61 74 69 63 61 #> [14939] 6c 6c 79 20 72 65 74 72 79 20 69 66 20 74 68 65 20 72 65 71 75 65 #> [14961] 73 74 20 66 61 69 6c 73 20 6f 72 20 65 6e 63 6f 75 6e 74 65 72 73 #> [14983] 20 61 20 74 72 61 6e 73 69 65 6e 74 20 48 54 54 50 20 65 72 72 6f #> [15005] 72 20 28 65 2e 67 2e c2 a0 61 20 34 32 39 20 72 61 74 65 20 6c 69 #> [15027] 6d 69 74 20 72 65 71 75 65 73 74 29 2e 20 3c 63 6f 64 65 3e 3c 61 #> [15049] 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 2f 72 65 71 5f 72 #> [15071] 65 74 72 79 2e 68 74 6d 6c 22 3e 72 65 71 5f 72 65 74 72 79 28 29 #> [15093] 3c 2f 61 3e 3c 2f 63 6f 64 65 3e 20 64 65 66 69 6e 65 73 20 74 68 #> [15115] 65 20 6d 61 78 69 6d 75 6d 20 6e 75 6d 62 65 72 20 6f 66 20 72 65 #> [15137] 74 72 69 65 73 2c 20 77 68 69 63 68 20 65 72 72 6f 72 73 20 61 72 #> [15159] 65 20 74 72 61 6e 73 69 65 6e 74 2c 20 61 6e 64 20 68 6f 77 20 6c #> [15181] 6f 6e 67 20 74 6f 20 77 61 69 74 20 62 65 74 77 65 65 6e 20 74 72 #> [15203] 69 65 73 2e 3c 2f 70 3e 3c 2f 6c 69 3e 0a 3c 6c 69 3e 3c 70 3e 4f #> [15225] 41 75 74 68 20 73 75 70 70 6f 72 74 20 68 61 73 20 62 65 65 6e 20 #> [15247] 74 6f 74 61 6c 6c 79 20 6f 76 65 72 68 61 75 6c 65 64 20 74 6f 20 #> [15269] 64 69 72 65 63 74 6c 79 20 73 75 70 70 6f 72 74 20 6d 61 6e 79 20 #> [15291] 6d 6f 72 65 20 66 6c 6f 77 73 20 61 6e 64 20 74 6f 20 6d 61 6b 65 #> [15313] 20 69 74 20 6d 75 63 68 20 65 61 73 69 65 72 20 74 6f 20 62 6f 74 #> [15335] 68 20 63 75 73 74 6f 6d 69 73 65 20 74 68 65 20 62 75 69 6c 74 2d #> [15357] 69 6e 20 66 6c 6f 77 73 20 61 6e 64 20 74 6f 20 63 72 65 61 74 65 #> [15379] 20 79 6f 75 72 20 6f 77 6e 2e 3c 2f 70 3e 3c 2f 6c 69 3e 0a 3c 6c #> [15401] 69 3e 3c 70 3e 59 6f 75 20 63 61 6e 20 6d 61 6e 61 67 65 20 73 65 #> [15423] 63 72 65 74 73 20 28 6f 66 74 65 6e 20 6e 65 65 64 65 64 20 66 6f #> [15445] 72 20 74 65 73 74 69 6e 67 29 20 77 69 74 68 20 3c 63 6f 64 65 3e #> [15467] 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 2f 73 65 63 #> [15489] 72 65 74 73 2e 68 74 6d 6c 22 3e 73 65 63 72 65 74 5f 65 6e 63 72 #> [15511] 79 70 74 28 29 3c 2f 61 3e 3c 2f 63 6f 64 65 3e 20 61 6e 64 20 66 #> [15533] 72 69 65 6e 64 73 2e 20 59 6f 75 20 63 61 6e 20 6f 62 66 75 73 63 #> [15555] 61 74 65 20 6d 69 6c 64 6c 79 20 63 6f 6e 66 69 64 65 6e 74 69 61 #> [15577] 6c 20 64 61 74 61 20 77 69 74 68 20 3c 63 6f 64 65 3e 3c 61 20 68 #> [15599] 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 2f 6f 62 66 75 73 63 61 #> [15621] 74 65 2e 68 74 6d 6c 22 3e 6f 62 66 75 73 63 61 74 65 28 29 3c 2f #> [15643] 61 3e 3c 2f 63 6f 64 65 3e 2c 20 70 72 65 76 65 6e 74 69 6e 67 20 #> [15665] 69 74 20 66 72 6f 6d 20 62 65 69 6e 67 20 73 63 72 61 70 65 64 20 #> [15687] 66 72 6f 6d 20 70 75 62 6c 69 73 68 65 64 20 63 6f 64 65 2e 3c 2f #> [15709] 70 3e 3c 2f 6c 69 3e 0a 3c 6c 69 3e 3c 70 3e 59 6f 75 20 63 61 6e #> [15731] 20 61 75 74 6f 6d 61 74 69 63 61 6c 6c 79 20 63 61 63 68 65 20 61 #> [15753] 6c 6c 20 63 61 63 68 65 61 62 6c 65 20 72 65 73 75 6c 74 73 20 77 #> [15775] 69 74 68 20 3c 63 6f 64 65 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 #> [15797] 65 72 65 6e 63 65 2f 72 65 71 5f 63 61 63 68 65 2e 68 74 6d 6c 22 #> [15819] 3e 72 65 71 5f 63 61 63 68 65 28 29 3c 2f 61 3e 3c 2f 63 6f 64 65 #> [15841] 3e 2e 20 52 65 6c 61 74 69 76 65 6c 79 20 66 65 77 20 41 50 49 20 #> [15863] 72 65 73 70 6f 6e 73 65 73 20 61 72 65 20 63 61 63 68 65 61 62 6c #> [15885] 65 2c 20 62 75 74 20 77 68 65 6e 20 74 68 65 79 20 61 72 65 20 69 #> [15907] 74 20 74 79 70 69 63 61 6c 6c 79 20 6d 61 6b 65 73 20 61 20 62 69 #> [15929] 67 20 64 69 66 66 65 72 65 6e 63 65 2e 3c 2f 70 3e 3c 2f 6c 69 3e #> [15951] 0a 3c 2f 75 6c 3e 0a 3c 2f 64 69 76 3e 0a 3c 64 69 76 20 63 6c 61 #> [15973] 73 73 3d 22 73 65 63 74 69 6f 6e 20 6c 65 76 65 6c 32 22 3e 0a 3c #> [15995] 68 32 20 69 64 3d 22 61 63 6b 6e 6f 77 6c 65 64 67 65 6d 65 6e 74 #> [16017] 73 22 3e 41 63 6b 6e 6f 77 6c 65 64 67 65 6d 65 6e 74 73 3c 61 20 #> [16039] 63 6c 61 73 73 3d 22 61 6e 63 68 6f 72 22 20 61 72 69 61 2d 6c 61 #> [16061] 62 65 6c 3d 22 61 6e 63 68 6f 72 22 20 68 72 65 66 3d 22 23 61 63 #> [16083] 6b 6e 6f 77 6c 65 64 67 65 6d 65 6e 74 73 22 3e 3c 2f 61 3e 0a 3c #> [16105] 2f 68 32 3e 0a 3c 70 3e 68 74 74 72 32 20 77 6f 75 6c 64 6e e2 80 #> [16127] 99 74 20 62 65 20 70 6f 73 73 69 62 6c 65 20 77 69 74 68 6f 75 74 #> [16149] 20 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 6a 65 72 6f #> [16171] 65 6e 2e 63 72 61 6e 2e 64 65 76 2f 63 75 72 6c 2f 22 20 63 6c 61 #> [16193] 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 63 75 72 #> [16215] 6c 3c 2f 61 3e 2c 20 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 3a #> [16237] 2f 2f 67 69 74 68 75 62 2e 63 6f 6d 2f 6a 65 72 6f 65 6e 2f 6f 70 #> [16259] 65 6e 73 73 6c 2f 22 20 63 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 #> [16281] 6c 2d 6c 69 6e 6b 22 3e 6f 70 65 6e 73 73 6c 3c 2f 61 3e 2c 20 3c #> [16303] 61 20 68 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 6a 65 72 6f 65 6e #> [16325] 2e 63 72 61 6e 2e 64 65 76 2f 6a 73 6f 6e 6c 69 74 65 2f 22 20 63 #> [16347] 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 6a #> [16369] 73 6f 6e 6c 69 74 65 3c 2f 61 3e 2c 20 61 6e 64 20 3c 61 20 68 72 #> [16391] 65 66 3d 22 68 74 74 70 73 3a 2f 2f 67 69 74 68 75 62 2e 63 6f 6d #> [16413] 2f 72 2d 6c 69 62 2f 6a 6f 73 65 2f 22 20 63 6c 61 73 73 3d 22 65 #> [16435] 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 6a 6f 73 65 3c 2f 61 3e #> [16457] 2c 20 77 68 69 63 68 20 61 72 65 20 61 6c 6c 20 6d 61 69 6e 74 61 #> [16479] 69 6e 65 64 20 62 79 20 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 #> [16501] 3a 2f 2f 67 69 74 68 75 62 2e 63 6f 6d 2f 6a 65 72 6f 65 6e 22 20 #> [16523] 63 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e #> [16545] 4a 65 72 6f 65 6e 20 4f 6f 6d 73 3c 2f 61 3e 2e 20 41 20 62 69 67 #> [16567] 20 74 68 61 6e 6b 73 20 61 6c 73 6f 20 67 6f 20 74 6f 20 3c 61 20 #> [16589] 68 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 6a 65 6e 6e 79 62 72 79 #> [16611] 61 6e 2e 6f 72 67 22 20 63 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 #> [16633] 6c 2d 6c 69 6e 6b 22 3e 4a 65 6e 6e 79 20 42 72 79 61 6e 3c 2f 61 #> [16655] 3e 20 61 6e 64 20 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 3a 2f #> [16677] 2f 77 77 77 2e 63 72 61 69 67 63 69 74 72 6f 2e 6f 72 67 22 20 63 #> [16699] 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 43 #> [16721] 72 61 69 67 20 43 69 74 72 6f 3c 2f 61 3e 20 77 68 6f 20 68 61 76 #> [16743] 65 20 67 69 76 65 6e 20 6d 65 20 6d 75 63 68 20 75 73 65 66 75 6c #> [16765] 20 66 65 65 64 62 61 63 6b 20 6f 6e 20 62 6f 74 68 20 74 68 65 20 #> [16787] 64 65 73 69 67 6e 20 6f 66 20 74 68 65 20 69 6e 74 65 72 6e 61 6c #> [16809] 73 20 61 6e 64 20 74 68 65 20 75 73 65 72 20 66 61 63 69 6e 67 20 #> [16831] 41 50 49 2e 3c 2f 70 3e 0a 3c 2f 64 69 76 3e 0a 3c 2f 64 69 76 3e #> [16853] 0a 20 20 3c 2f 6d 61 69 6e 3e 3c 61 73 69 64 65 20 63 6c 61 73 73 #> [16875] 3d 22 63 6f 6c 2d 6d 64 2d 33 22 3e 3c 64 69 76 20 63 6c 61 73 73 #> [16897] 3d 22 6c 69 6e 6b 73 22 3e 0a 3c 68 32 20 64 61 74 61 2d 74 6f 63 #> [16919] 2d 73 6b 69 70 3e 4c 69 6e 6b 73 3c 2f 68 32 3e 0a 3c 75 6c 20 63 #> [16941] 6c 61 73 73 3d 22 6c 69 73 74 2d 75 6e 73 74 79 6c 65 64 22 3e 0a #> [16963] 3c 6c 69 3e 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 63 #> [16985] 6c 6f 75 64 2e 72 2d 70 72 6f 6a 65 63 74 2e 6f 72 67 2f 70 61 63 #> [17007] 6b 61 67 65 3d 68 74 74 72 32 22 20 63 6c 61 73 73 3d 22 65 78 74 #> [17029] 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 56 69 65 77 20 6f 6e 20 43 52 #> [17051] 41 4e 3c 2f 61 3e 3c 2f 6c 69 3e 0a 3c 6c 69 3e 3c 61 20 68 72 65 #> [17073] 66 3d 22 68 74 74 70 73 3a 2f 2f 67 69 74 68 75 62 2e 63 6f 6d 2f #> [17095] 72 2d 6c 69 62 2f 68 74 74 72 32 2f 22 20 63 6c 61 73 73 3d 22 65 #> [17117] 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 42 72 6f 77 73 65 20 73 #> [17139] 6f 75 72 63 65 20 63 6f 64 65 3c 2f 61 3e 3c 2f 6c 69 3e 0a 3c 6c #> [17161] 69 3e 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 67 69 74 #> [17183] 68 75 62 2e 63 6f 6d 2f 72 2d 6c 69 62 2f 68 74 74 72 32 2f 69 73 #> [17205] 73 75 65 73 22 20 63 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d #> [17227] 6c 69 6e 6b 22 3e 52 65 70 6f 72 74 20 61 20 62 75 67 3c 2f 61 3e #> [17249] 3c 2f 6c 69 3e 0a 3c 2f 75 6c 3e 0a 3c 2f 64 69 76 3e 0a 0a 3c 64 #> [17271] 69 76 20 63 6c 61 73 73 3d 22 6c 69 63 65 6e 73 65 22 3e 0a 3c 68 #> [17293] 32 20 64 61 74 61 2d 74 6f 63 2d 73 6b 69 70 3e 4c 69 63 65 6e 73 #> [17315] 65 3c 2f 68 32 3e 0a 3c 75 6c 20 63 6c 61 73 73 3d 22 6c 69 73 74 #> [17337] 2d 75 6e 73 74 79 6c 65 64 22 3e 0a 3c 6c 69 3e 3c 61 20 68 72 65 #> [17359] 66 3d 22 4c 49 43 45 4e 53 45 2e 68 74 6d 6c 22 3e 46 75 6c 6c 20 #> [17381] 6c 69 63 65 6e 73 65 3c 2f 61 3e 3c 2f 6c 69 3e 0a 3c 6c 69 3e 3c #> [17403] 73 6d 61 6c 6c 3e 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 3a 2f #> [17425] 2f 6f 70 65 6e 73 6f 75 72 63 65 2e 6f 72 67 2f 6c 69 63 65 6e 73 #> [17447] 65 73 2f 6d 69 74 2d 6c 69 63 65 6e 73 65 2e 70 68 70 22 20 63 6c #> [17469] 61 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 4d 49 #> [17491] 54 3c 2f 61 3e 20 2b 20 66 69 6c 65 20 3c 61 20 68 72 65 66 3d 22 #> [17513] 4c 49 43 45 4e 53 45 2d 74 65 78 74 2e 68 74 6d 6c 22 3e 4c 49 43 #> [17535] 45 4e 53 45 3c 2f 61 3e 3c 2f 73 6d 61 6c 6c 3e 3c 2f 6c 69 3e 0a #> [17557] 3c 2f 75 6c 3e 0a 3c 2f 64 69 76 3e 0a 0a 0a 3c 64 69 76 20 63 6c #> [17579] 61 73 73 3d 22 63 69 74 61 74 69 6f 6e 22 3e 0a 3c 68 32 20 64 61 #> [17601] 74 61 2d 74 6f 63 2d 73 6b 69 70 3e 43 69 74 61 74 69 6f 6e 3c 2f #> [17623] 68 32 3e 0a 3c 75 6c 20 63 6c 61 73 73 3d 22 6c 69 73 74 2d 75 6e #> [17645] 73 74 79 6c 65 64 22 3e 0a 3c 6c 69 3e 3c 61 20 68 72 65 66 3d 22 #> [17667] 61 75 74 68 6f 72 73 2e 68 74 6d 6c 23 63 69 74 61 74 69 6f 6e 22 #> [17689] 3e 43 69 74 69 6e 67 20 68 74 74 72 32 3c 2f 61 3e 3c 2f 6c 69 3e #> [17711] 0a 3c 2f 75 6c 3e 0a 3c 2f 64 69 76 3e 0a 0a 3c 64 69 76 20 63 6c #> [17733] 61 73 73 3d 22 64 65 76 65 6c 6f 70 65 72 73 22 3e 0a 3c 68 32 20 #> [17755] 64 61 74 61 2d 74 6f 63 2d 73 6b 69 70 3e 44 65 76 65 6c 6f 70 65 #> [17777] 72 73 3c 2f 68 32 3e 0a 3c 75 6c 20 63 6c 61 73 73 3d 22 6c 69 73 #> [17799] 74 2d 75 6e 73 74 79 6c 65 64 22 3e 0a 3c 6c 69 3e 0a 3c 61 20 68 #> [17821] 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 68 61 64 6c 65 79 2e 6e 7a #> [17843] 22 20 63 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b #> [17865] 22 3e 48 61 64 6c 65 79 20 57 69 63 6b 68 61 6d 3c 2f 61 3e 20 3c #> [17887] 62 72 3e 3c 73 6d 61 6c 6c 20 63 6c 61 73 73 3d 22 72 6f 6c 65 73 #> [17909] 22 3e 20 41 75 74 68 6f 72 2c 20 6d 61 69 6e 74 61 69 6e 65 72 20 #> [17931] 3c 2f 73 6d 61 6c 6c 3e 20 20 3c 2f 6c 69 3e 0a 3c 6c 69 3e 0a 3c #> [17953] 61 20 68 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 77 77 77 2e 70 6f #> [17975] 73 69 74 2e 63 6f 22 20 63 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 #> [17997] 6c 2d 6c 69 6e 6b 22 3e 3c 69 6d 67 20 73 72 63 3d 22 68 74 74 70 #> [18019] 73 3a 2f 2f 77 77 77 2e 74 69 64 79 76 65 72 73 65 2e 6f 72 67 2f #> [18041] 70 6f 73 69 74 2d 6c 6f 67 6f 2e 73 76 67 22 20 61 6c 74 3d 22 50 #> [18063] 6f 73 69 74 22 20 68 65 69 67 68 74 3d 22 31 36 22 20 77 69 64 74 #> [18085] 68 3d 22 36 32 22 20 73 74 79 6c 65 3d 22 6d 61 72 67 69 6e 2d 62 #> [18107] 6f 74 74 6f 6d 3a 20 33 70 78 3b 22 3e 3c 2f 61 3e 20 3c 62 72 3e #> [18129] 3c 73 6d 61 6c 6c 20 63 6c 61 73 73 3d 22 72 6f 6c 65 73 22 3e 20 #> [18151] 43 6f 70 79 72 69 67 68 74 20 68 6f 6c 64 65 72 2c 20 66 75 6e 64 #> [18173] 65 72 20 3c 2f 73 6d 61 6c 6c 3e 20 20 3c 2f 6c 69 3e 0a 3c 6c 69 #> [18195] 3e 3c 61 20 68 72 65 66 3d 22 61 75 74 68 6f 72 73 2e 68 74 6d 6c #> [18217] 22 3e 4d 6f 72 65 20 61 62 6f 75 74 20 61 75 74 68 6f 72 73 2e 2e #> [18239] 2e 3c 2f 61 3e 3c 2f 6c 69 3e 0a 3c 2f 75 6c 3e 0a 3c 2f 64 69 76 #> [18261] 3e 0a 0a 0a 0a 20 20 3c 2f 61 73 69 64 65 3e 0a 3c 2f 64 69 76 3e #> [18283] 0a 0a 0a 20 20 20 3c 2f 64 69 76 3e 0a 20 20 3c 66 6f 6f 74 65 72 #> [18305] 3e 3c 64 69 76 20 63 6c 61 73 73 3d 22 63 6f 6e 74 61 69 6e 65 72 #> [18327] 22 3e 0a 20 20 3c 64 69 76 20 63 6c 61 73 73 3d 22 70 6b 67 64 6f #> [18349] 77 6e 2d 66 6f 6f 74 65 72 2d 6c 65 66 74 22 3e 0a 20 20 3c 70 3e #> [18371] 44 65 76 65 6c 6f 70 65 64 20 62 79 20 3c 61 20 68 72 65 66 3d 22 #> [18393] 68 74 74 70 73 3a 2f 2f 68 61 64 6c 65 79 2e 6e 7a 22 20 63 6c 61 #> [18415] 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 48 61 64 #> [18437] 6c 65 79 20 57 69 63 6b 68 61 6d 3c 2f 61 3e 2c 20 3c 61 20 68 72 #> [18459] 65 66 3d 22 68 74 74 70 73 3a 2f 2f 77 77 77 2e 70 6f 73 69 74 2e #> [18481] 63 6f 22 20 63 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 #> [18503] 6e 6b 22 3e 3c 69 6d 67 20 73 72 63 3d 22 68 74 74 70 73 3a 2f 2f #> [18525] 77 77 77 2e 74 69 64 79 76 65 72 73 65 2e 6f 72 67 2f 70 6f 73 69 #> [18547] 74 2d 6c 6f 67 6f 2e 73 76 67 22 20 61 6c 74 3d 22 50 6f 73 69 74 #> [18569] 22 20 68 65 69 67 68 74 3d 22 31 36 22 20 77 69 64 74 68 3d 22 36 #> [18591] 32 22 20 73 74 79 6c 65 3d 22 6d 61 72 67 69 6e 2d 62 6f 74 74 6f #> [18613] 6d 3a 20 33 70 78 3b 22 3e 3c 2f 61 3e 2e 3c 2f 70 3e 0a 3c 2f 64 #> [18635] 69 76 3e 0a 0a 3c 64 69 76 20 63 6c 61 73 73 3d 22 70 6b 67 64 6f #> [18657] 77 6e 2d 66 6f 6f 74 65 72 2d 72 69 67 68 74 22 3e 0a 20 20 3c 70 #> [18679] 3e 53 69 74 65 20 62 75 69 6c 74 20 77 69 74 68 20 3c 61 20 68 72 #> [18701] 65 66 3d 22 68 74 74 70 73 3a 2f 2f 70 6b 67 64 6f 77 6e 2e 72 2d #> [18723] 6c 69 62 2e 6f 72 67 2f 22 20 63 6c 61 73 73 3d 22 65 78 74 65 72 #> [18745] 6e 61 6c 2d 6c 69 6e 6b 22 3e 70 6b 67 64 6f 77 6e 3c 2f 61 3e 20 #> [18767] 32 2e 31 2e 31 2e 3c 2f 70 3e 0a 3c 2f 64 69 76 3e 0a 0a 20 20 3c #> [18789] 2f 64 69 76 3e 3c 2f 66 6f 6f 74 65 72 3e 0a 3c 2f 62 6f 64 79 3e #> [18811] 0a 3c 2f 68 74 6d 6c 3e 0a resp |> resp_body_string() #> [1] \"\\n\\n\\n\\n\\n\\n\\nPerform HTTP Requests and Process the Responses • httr2<\/title>\\n<!-- favicons --><link rel=\\\"icon\\\" type=\\\"image/png\\\" sizes=\\\"16x16\\\" href=\\\"favicon-16x16.png\\\">\\n<link rel=\\\"icon\\\" type=\\\"image/png\\\" sizes=\\\"32x32\\\" href=\\\"favicon-32x32.png\\\">\\n<link rel=\\\"apple-touch-icon\\\" type=\\\"image/png\\\" sizes=\\\"180x180\\\" href=\\\"apple-touch-icon.png\\\">\\n<link rel=\\\"apple-touch-icon\\\" type=\\\"image/png\\\" sizes=\\\"120x120\\\" href=\\\"apple-touch-icon-120x120.png\\\">\\n<link rel=\\\"apple-touch-icon\\\" type=\\\"image/png\\\" sizes=\\\"76x76\\\" href=\\\"apple-touch-icon-76x76.png\\\">\\n<link rel=\\\"apple-touch-icon\\\" type=\\\"image/png\\\" sizes=\\\"60x60\\\" href=\\\"apple-touch-icon-60x60.png\\\">\\n<script src=\\\"deps/jquery-3.6.0/jquery-3.6.0.min.js\\\"><\/script><meta name=\\\"viewport\\\" content=\\\"width=device-width, initial-scale=1, shrink-to-fit=no\\\">\\n<link href=\\\"deps/bootstrap-5.3.1/bootstrap.min.css\\\" rel=\\\"stylesheet\\\">\\n<script src=\\\"deps/bootstrap-5.3.1/bootstrap.bundle.min.js\\\"><\/script><link href=\\\"deps/Source_Sans_Pro-0.4.9/font.css\\\" rel=\\\"stylesheet\\\">\\n<link href=\\\"deps/Source_Code_Pro-0.4.9/font.css\\\" rel=\\\"stylesheet\\\">\\n<link href=\\\"deps/font-awesome-6.4.2/css/all.min.css\\\" rel=\\\"stylesheet\\\">\\n<link href=\\\"deps/font-awesome-6.4.2/css/v4-shims.min.css\\\" rel=\\\"stylesheet\\\">\\n<script src=\\\"deps/headroom-0.11.0/headroom.min.js\\\"><\/script><script src=\\\"deps/headroom-0.11.0/jQuery.headroom.min.js\\\"><\/script><script src=\\\"deps/bootstrap-toc-1.0.1/bootstrap-toc.min.js\\\"><\/script><script src=\\\"deps/clipboard.js-2.0.11/clipboard.min.js\\\"><\/script><script src=\\\"deps/search-1.0.0/autocomplete.jquery.min.js\\\"><\/script><script src=\\\"deps/search-1.0.0/fuse.min.js\\\"><\/script><script src=\\\"deps/search-1.0.0/mark.min.js\\\"><\/script><!-- pkgdown --><script src=\\\"pkgdown.js\\\"><\/script><meta property=\\\"og:title\\\" content=\\\"Perform HTTP Requests and Process the Responses\\\">\\n<meta name=\\\"description\\\" content=\\\"Tools for creating and modifying HTTP requests, then performing them and processing the results. httr2 is a modern re-imagining of httr that uses a pipe-based interface and solves more of the problems that API wrapping packages face.\\\">\\n<meta property=\\\"og:description\\\" content=\\\"Tools for creating and modifying HTTP requests, then performing them and processing the results. httr2 is a modern re-imagining of httr that uses a pipe-based interface and solves more of the problems that API wrapping packages face.\\\">\\n<meta property=\\\"og:image\\\" content=\\\"https://httr2.r-lib.org/logo.png\\\">\\n<script defer data-domain=\\\"httr2.r-lib.org,all.tidyverse.org\\\" src=\\\"https://plausible.io/js/plausible.js\\\"><\/script>\\n<\/head>\\n<body>\\n <a href=\\\"#container\\\" class=\\\"visually-hidden-focusable\\\">Skip to content<\/a>\\n\\n\\n <nav class=\\\"navbar navbar-expand-lg fixed-top bg-none\\\" data-bs-theme=\\\"light\\\" aria-label=\\\"Site navigation\\\"><div class=\\\"container\\\">\\n\\n <a class=\\\"navbar-brand me-2\\\" href=\\\"index.html\\\">httr2<\/a>\\n\\n <small class=\\\"nav-text text-muted me-auto\\\" data-bs-toggle=\\\"tooltip\\\" data-bs-placement=\\\"bottom\\\" title=\\\"Released version\\\">1.0.5<\/small>\\n\\n\\n <button class=\\\"navbar-toggler\\\" type=\\\"button\\\" data-bs-toggle=\\\"collapse\\\" data-bs-target=\\\"#navbar\\\" aria-controls=\\\"navbar\\\" aria-expanded=\\\"false\\\" aria-label=\\\"Toggle navigation\\\">\\n <span class=\\\"navbar-toggler-icon\\\"><\/span>\\n <\/button>\\n\\n <div id=\\\"navbar\\\" class=\\\"collapse navbar-collapse ms-3\\\">\\n <ul class=\\\"navbar-nav me-auto\\\">\\n<li class=\\\"nav-item\\\"><a class=\\\"nav-link\\\" href=\\\"articles/httr2.html\\\">Get started<\/a><\/li>\\n<li class=\\\"nav-item\\\"><a class=\\\"nav-link\\\" href=\\\"reference/index.html\\\">Reference<\/a><\/li>\\n<li class=\\\"nav-item dropdown\\\">\\n <button class=\\\"nav-link dropdown-toggle\\\" type=\\\"button\\\" id=\\\"dropdown-articles\\\" data-bs-toggle=\\\"dropdown\\\" aria-expanded=\\\"false\\\" aria-haspopup=\\\"true\\\">Articles<\/button>\\n <ul class=\\\"dropdown-menu\\\" aria-labelledby=\\\"dropdown-articles\\\">\\n<li><a class=\\\"dropdown-item\\\" href=\\\"articles/wrapping-apis.html\\\">Wrapping APIs<\/a><\/li>\\n <li><a class=\\\"dropdown-item\\\" href=\\\"articles/oauth.html\\\">OAuth<\/a><\/li>\\n <\/ul>\\n<\/li>\\n<li class=\\\"nav-item dropdown\\\">\\n <button class=\\\"nav-link dropdown-toggle\\\" type=\\\"button\\\" id=\\\"dropdown-news\\\" data-bs-toggle=\\\"dropdown\\\" aria-expanded=\\\"false\\\" aria-haspopup=\\\"true\\\">News<\/button>\\n <ul class=\\\"dropdown-menu\\\" aria-labelledby=\\\"dropdown-news\\\">\\n<li><h6 class=\\\"dropdown-header\\\" data-toc-skip>Releases<\/h6><\/li>\\n <li><a class=\\\"external-link dropdown-item\\\" href=\\\"https://www.tidyverse.org/blog/2023/11/httr2-1-0-0/\\\">httr2 1.0.0<\/a><\/li>\\n <li><hr class=\\\"dropdown-divider\\\"><\/li>\\n <li><a class=\\\"dropdown-item\\\" href=\\\"news/index.html\\\">Changelog<\/a><\/li>\\n <\/ul>\\n<\/li>\\n <\/ul>\\n<ul class=\\\"navbar-nav\\\">\\n<li class=\\\"nav-item\\\"><form class=\\\"form-inline\\\" role=\\\"search\\\">\\n <input class=\\\"form-control\\\" type=\\\"search\\\" name=\\\"search-input\\\" id=\\\"search-input\\\" autocomplete=\\\"off\\\" aria-label=\\\"Search site\\\" placeholder=\\\"Search for\\\" data-search-index=\\\"search.json\\\">\\n<\/form><\/li>\\n<li class=\\\"nav-item\\\"><a class=\\\"external-link nav-link\\\" href=\\\"https://github.com/r-lib/httr2/\\\" aria-label=\\\"GitHub\\\"><span class=\\\"fa fab fa-github fa-lg\\\"><\/span><\/a><\/li>\\n <\/ul>\\n<\/div>\\n\\n\\n <\/div>\\n<\/nav><div class=\\\"container template-home\\\" id=\\\"container\\\">\\n<div class=\\\"row\\\">\\n <main id=\\\"main\\\" class=\\\"col-md-9\\\"><div class=\\\"section level1\\\">\\n<div class=\\\"page-header\\\">\\n<img src=\\\"logo.png\\\" class=\\\"logo\\\" alt=\\\"\\\"><h1 id=\\\"httr2-\\\">httr2 \\n<a class=\\\"anchor\\\" aria-label=\\\"anchor\\\" href=\\\"#httr2-\\\"><\/a>\\n<\/h1>\\n<\/div>\\n<!-- badges: start -->\\n\\n<p>httr2 (pronounced hitter2) is a ground-up rewrite of <a href=\\\"https://httr.r-lib.org\\\" class=\\\"external-link\\\">httr<\/a> that provides a pipeable API with an explicit request object that solves more problems felt by packages that wrap APIs (e.g. built-in rate-limiting, retries, OAuth, secure secrets, and more).<\/p>\\n<div class=\\\"section level2\\\">\\n<h2 id=\\\"installation\\\">Installation<a class=\\\"anchor\\\" aria-label=\\\"anchor\\\" href=\\\"#installation\\\"><\/a>\\n<\/h2>\\n<p>You can install httr2 from CRAN with:<\/p>\\n<div class=\\\"sourceCode\\\" id=\\\"cb1\\\"><pre class=\\\"downlit sourceCode r\\\">\\n<code class=\\\"sourceCode R\\\"><span><span class=\\\"fu\\\"><a href=\\\"https://rdrr.io/r/utils/install.packages.html\\\" class=\\\"external-link\\\">install.packages<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"st\\\">\\\"httr2\\\"<\/span><span class=\\\"op\\\">)<\/span><\/span><\/code><\/pre><\/div>\\n<\/div>\\n<div class=\\\"section level2\\\">\\n<h2 id=\\\"usage\\\">Usage<a class=\\\"anchor\\\" aria-label=\\\"anchor\\\" href=\\\"#usage\\\"><\/a>\\n<\/h2>\\n<p>To use httr2, start by creating a <strong>request<\/strong>:<\/p>\\n<div class=\\\"sourceCode\\\" id=\\\"cb2\\\"><pre class=\\\"downlit sourceCode r\\\">\\n<code class=\\\"sourceCode R\\\"><span><span class=\\\"kw\\\"><a href=\\\"https://rdrr.io/r/base/library.html\\\" class=\\\"external-link\\\">library<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"va\\\"><a href=\\\"https://httr2.r-lib.org\\\">httr2<\/a><\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><\/span>\\n<span><span class=\\\"va\\\">req<\/span> <span class=\\\"op\\\"><-<\/span> <span class=\\\"fu\\\"><a href=\\\"reference/request.html\\\">request<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"st\\\">\\\"https://r-project.org\\\"<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"va\\\">req<\/span><\/span>\\n<span><span class=\\\"co\\\">#> <httr2_request><\/span><\/span>\\n<span><span class=\\\"co\\\">#> GET https://r-project.org<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Body: empty<\/span><\/span><\/code><\/pre><\/div>\\n<p>You can tailor this request with the <code>req_<\/code> family of functions:<\/p>\\n<div class=\\\"sourceCode\\\" id=\\\"cb3\\\"><pre class=\\\"downlit sourceCode r\\\">\\n<code class=\\\"sourceCode R\\\"><span><span class=\\\"co\\\"># Add custom headers<\/span><\/span>\\n<span><span class=\\\"va\\\">req<\/span> <span class=\\\"op\\\">|><\/span> <span class=\\\"fu\\\"><a href=\\\"reference/req_headers.html\\\">req_headers<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"st\\\">\\\"Accept\\\"<\/span> <span class=\\\"op\\\">=<\/span> <span class=\\\"st\\\">\\\"application/json\\\"<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"co\\\">#> <httr2_request><\/span><\/span>\\n<span><span class=\\\"co\\\">#> GET https://r-project.org<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Headers:<\/span><\/span>\\n<span><span class=\\\"co\\\">#> • Accept: 'application/json'<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Body: empty<\/span><\/span>\\n<span><\/span>\\n<span><span class=\\\"co\\\"># Add a body, turning it into a POST<\/span><\/span>\\n<span><span class=\\\"va\\\">req<\/span> <span class=\\\"op\\\">|><\/span> <span class=\\\"fu\\\"><a href=\\\"reference/req_body.html\\\">req_body_json<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"fu\\\"><a href=\\\"https://rdrr.io/r/base/list.html\\\" class=\\\"external-link\\\">list<\/a><\/span><span class=\\\"op\\\">(<\/span>x <span class=\\\"op\\\">=<\/span> <span class=\\\"fl\\\">1<\/span>, y <span class=\\\"op\\\">=<\/span> <span class=\\\"fl\\\">2<\/span><span class=\\\"op\\\">)<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"co\\\">#> <httr2_request><\/span><\/span>\\n<span><span class=\\\"co\\\">#> POST https://r-project.org<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Body: json encoded data<\/span><\/span>\\n<span><\/span>\\n<span><span class=\\\"co\\\"># Modify the path in the url<\/span><\/span>\\n<span><span class=\\\"va\\\">req<\/span> <span class=\\\"op\\\">|><\/span> <span class=\\\"fu\\\"><a href=\\\"reference/req_url.html\\\">req_url_path<\/a><\/span><span class=\\\"op\\\">(<\/span>path <span class=\\\"op\\\">=<\/span> <span class=\\\"st\\\">\\\"path/to/my/file\\\"<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"co\\\">#> <httr2_request><\/span><\/span>\\n<span><span class=\\\"co\\\">#> GET https://r-project.org/path/to/my/file<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Body: empty<\/span><\/span>\\n<span><\/span>\\n<span><span class=\\\"co\\\"># Automatically retry if the request fails<\/span><\/span>\\n<span><span class=\\\"va\\\">req<\/span> <span class=\\\"op\\\">|><\/span> <span class=\\\"fu\\\"><a href=\\\"reference/req_retry.html\\\">req_retry<\/a><\/span><span class=\\\"op\\\">(<\/span>max_tries <span class=\\\"op\\\">=<\/span> <span class=\\\"fl\\\">5<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"co\\\">#> <httr2_request><\/span><\/span>\\n<span><span class=\\\"co\\\">#> GET https://r-project.org<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Body: empty<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Policies:<\/span><\/span>\\n<span><span class=\\\"co\\\">#> • retry_max_tries: 5<\/span><\/span>\\n<span><span class=\\\"co\\\">#> • retry_on_failure: FALSE<\/span><\/span>\\n<span><\/span>\\n<span><span class=\\\"co\\\"># Change the HTTP method<\/span><\/span>\\n<span><span class=\\\"va\\\">req<\/span> <span class=\\\"op\\\">|><\/span> <span class=\\\"fu\\\"><a href=\\\"reference/req_method.html\\\">req_method<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"st\\\">\\\"PATCH\\\"<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"co\\\">#> <httr2_request><\/span><\/span>\\n<span><span class=\\\"co\\\">#> PATCH https://r-project.org<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Body: empty<\/span><\/span><\/code><\/pre><\/div>\\n<p>And see exactly what httr2 will send to the server with <code><a href=\\\"reference/req_dry_run.html\\\">req_dry_run()<\/a><\/code>:<\/p>\\n<div class=\\\"sourceCode\\\" id=\\\"cb4\\\"><pre class=\\\"downlit sourceCode r\\\">\\n<code class=\\\"sourceCode R\\\"><span><span class=\\\"va\\\">req<\/span> <span class=\\\"op\\\">|><\/span> <span class=\\\"fu\\\"><a href=\\\"reference/req_dry_run.html\\\">req_dry_run<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"co\\\">#> GET / HTTP/1.1<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Host: r-project.org<\/span><\/span>\\n<span><span class=\\\"co\\\">#> User-Agent: httr2/1.0.3.9000 r-curl/5.2.2 libcurl/8.6.0<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Accept: */*<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Accept-Encoding: deflate, gzip<\/span><\/span><\/code><\/pre><\/div>\\n<p>Use <code><a href=\\\"reference/req_perform.html\\\">req_perform()<\/a><\/code> to perform the request, retrieving a <strong>response<\/strong>:<\/p>\\n<div class=\\\"sourceCode\\\" id=\\\"cb5\\\"><pre class=\\\"downlit sourceCode r\\\">\\n<code class=\\\"sourceCode R\\\"><span><span class=\\\"va\\\">resp<\/span> <span class=\\\"op\\\"><-<\/span> <span class=\\\"fu\\\"><a href=\\\"reference/req_perform.html\\\">req_perform<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"va\\\">req<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"va\\\">resp<\/span><\/span>\\n<span><span class=\\\"co\\\">#> <httr2_response><\/span><\/span>\\n<span><span class=\\\"co\\\">#> GET https://www.r-project.org/<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Status: 200 OK<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Content-Type: text/html<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Body: In memory (6951 bytes)<\/span><\/span><\/code><\/pre><\/div>\\n<p>The <code>resp_<\/code> functions help you extract various useful components of the response:<\/p>\\n<div class=\\\"sourceCode\\\" id=\\\"cb6\\\"><pre class=\\\"downlit sourceCode r\\\">\\n<code class=\\\"sourceCode R\\\"><span><span class=\\\"va\\\">resp<\/span> <span class=\\\"op\\\">|><\/span> <span class=\\\"fu\\\"><a href=\\\"reference/resp_content_type.html\\\">resp_content_type<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"co\\\">#> [1] \\\"text/html\\\"<\/span><\/span>\\n<span><span class=\\\"va\\\">resp<\/span> <span class=\\\"op\\\">|><\/span> <span class=\\\"fu\\\"><a href=\\\"reference/resp_status.html\\\">resp_status_desc<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"co\\\">#> [1] \\\"OK\\\"<\/span><\/span>\\n<span><span class=\\\"va\\\">resp<\/span> <span class=\\\"op\\\">|><\/span> <span class=\\\"fu\\\"><a href=\\\"reference/resp_body_raw.html\\\">resp_body_html<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"co\\\">#> {html_document}<\/span><\/span>\\n<span><span class=\\\"co\\\">#> <html lang=\\\"en\\\"><\/span><\/span>\\n<span><span class=\\\"co\\\">#> [1] <head>\\\\n<meta http-equiv=\\\"Content-Type\\\" content=\\\"text/html; charset=UTF-8 ...<\/span><\/span>\\n<span><span class=\\\"co\\\">#> [2] <body>\\\\n <div class=\\\"container page\\\">\\\\n <div class=\\\"row\\\">\\\\n ...<\/span><\/span><\/code><\/pre><\/div>\\n<\/div>\\n<div class=\\\"section level2\\\">\\n<h2 id=\\\"major-differences-to-httr\\\">Major differences to httr<a class=\\\"anchor\\\" aria-label=\\\"anchor\\\" href=\\\"#major-differences-to-httr\\\"><\/a>\\n<\/h2>\\n<ul>\\n<li><p>You can now create and modify a request without performing it. This means that there’s now a single function to perform the request and fetch the result: <code><a href=\\\"reference/req_perform.html\\\">req_perform()<\/a><\/code>. <code><a href=\\\"reference/req_perform.html\\\">req_perform()<\/a><\/code> replaces <code><a href=\\\"https://httr.r-lib.org/reference/GET.html\\\" class=\\\"external-link\\\">httr::GET()<\/a><\/code>, <code><a href=\\\"https://httr.r-lib.org/reference/POST.html\\\" class=\\\"external-link\\\">httr::POST()<\/a><\/code>, <code><a href=\\\"https://httr.r-lib.org/reference/DELETE.html\\\" class=\\\"external-link\\\">httr::DELETE()<\/a><\/code>, and more.<\/p><\/li>\\n<li><p>HTTP errors are automatically converted into R errors. Use <code><a href=\\\"reference/req_error.html\\\">req_error()<\/a><\/code> to override the defaults (which turn all 4xx and 5xx responses into errors) or to add additional details to the error message.<\/p><\/li>\\n<li><p>You can automatically retry if the request fails or encounters a transient HTTP error (e.g. a 429 rate limit request). <code><a href=\\\"reference/req_retry.html\\\">req_retry()<\/a><\/code> defines the maximum number of retries, which errors are transient, and how long to wait between tries.<\/p><\/li>\\n<li><p>OAuth support has been totally overhauled to directly support many more flows and to make it much easier to both customise the built-in flows and to create your own.<\/p><\/li>\\n<li><p>You can manage secrets (often needed for testing) with <code><a href=\\\"reference/secrets.html\\\">secret_encrypt()<\/a><\/code> and friends. You can obfuscate mildly confidential data with <code><a href=\\\"reference/obfuscate.html\\\">obfuscate()<\/a><\/code>, preventing it from being scraped from published code.<\/p><\/li>\\n<li><p>You can automatically cache all cacheable results with <code><a href=\\\"reference/req_cache.html\\\">req_cache()<\/a><\/code>. Relatively few API responses are cacheable, but when they are it typically makes a big difference.<\/p><\/li>\\n<\/ul>\\n<\/div>\\n<div class=\\\"section level2\\\">\\n<h2 id=\\\"acknowledgements\\\">Acknowledgements<a class=\\\"anchor\\\" aria-label=\\\"anchor\\\" href=\\\"#acknowledgements\\\"><\/a>\\n<\/h2>\\n<p>httr2 wouldn’t be possible without <a href=\\\"https://jeroen.cran.dev/curl/\\\" class=\\\"external-link\\\">curl<\/a>, <a href=\\\"https://github.com/jeroen/openssl/\\\" class=\\\"external-link\\\">openssl<\/a>, <a href=\\\"https://jeroen.cran.dev/jsonlite/\\\" class=\\\"external-link\\\">jsonlite<\/a>, and <a href=\\\"https://github.com/r-lib/jose/\\\" class=\\\"external-link\\\">jose<\/a>, which are all maintained by <a href=\\\"https://github.com/jeroen\\\" class=\\\"external-link\\\">Jeroen Ooms<\/a>. A big thanks also go to <a href=\\\"https://jennybryan.org\\\" class=\\\"external-link\\\">Jenny Bryan<\/a> and <a href=\\\"https://www.craigcitro.org\\\" class=\\\"external-link\\\">Craig Citro<\/a> who have given me much useful feedback on both the design of the internals and the user facing API.<\/p>\\n<\/div>\\n<\/div>\\n <\/main><aside class=\\\"col-md-3\\\"><div class=\\\"links\\\">\\n<h2 data-toc-skip>Links<\/h2>\\n<ul class=\\\"list-unstyled\\\">\\n<li><a href=\\\"https://cloud.r-project.org/package=httr2\\\" class=\\\"external-link\\\">View on CRAN<\/a><\/li>\\n<li><a href=\\\"https://github.com/r-lib/httr2/\\\" class=\\\"external-link\\\">Browse source code<\/a><\/li>\\n<li><a href=\\\"https://github.com/r-lib/httr2/issues\\\" class=\\\"external-link\\\">Report a bug<\/a><\/li>\\n<\/ul>\\n<\/div>\\n\\n<div class=\\\"license\\\">\\n<h2 data-toc-skip>License<\/h2>\\n<ul class=\\\"list-unstyled\\\">\\n<li><a href=\\\"LICENSE.html\\\">Full license<\/a><\/li>\\n<li><small><a href=\\\"https://opensource.org/licenses/mit-license.php\\\" class=\\\"external-link\\\">MIT<\/a> + file <a href=\\\"LICENSE-text.html\\\">LICENSE<\/a><\/small><\/li>\\n<\/ul>\\n<\/div>\\n\\n\\n<div class=\\\"citation\\\">\\n<h2 data-toc-skip>Citation<\/h2>\\n<ul class=\\\"list-unstyled\\\">\\n<li><a href=\\\"authors.html#citation\\\">Citing httr2<\/a><\/li>\\n<\/ul>\\n<\/div>\\n\\n<div class=\\\"developers\\\">\\n<h2 data-toc-skip>Developers<\/h2>\\n<ul class=\\\"list-unstyled\\\">\\n<li>\\n<a href=\\\"https://hadley.nz\\\" class=\\\"external-link\\\">Hadley Wickham<\/a> <br><small class=\\\"roles\\\"> Author, maintainer <\/small> <\/li>\\n<li>\\n<a href=\\\"https://www.posit.co\\\" class=\\\"external-link\\\"><img src=\\\"https://www.tidyverse.org/posit-logo.svg\\\" alt=\\\"Posit\\\" height=\\\"16\\\" width=\\\"62\\\" style=\\\"margin-bottom: 3px;\\\"><\/a> <br><small class=\\\"roles\\\"> Copyright holder, funder <\/small> <\/li>\\n<li><a href=\\\"authors.html\\\">More about authors...<\/a><\/li>\\n<\/ul>\\n<\/div>\\n\\n\\n\\n <\/aside>\\n<\/div>\\n\\n\\n <\/div>\\n <footer><div class=\\\"container\\\">\\n <div class=\\\"pkgdown-footer-left\\\">\\n <p>Developed by <a href=\\\"https://hadley.nz\\\" class=\\\"external-link\\\">Hadley Wickham<\/a>, <a href=\\\"https://www.posit.co\\\" class=\\\"external-link\\\"><img src=\\\"https://www.tidyverse.org/posit-logo.svg\\\" alt=\\\"Posit\\\" height=\\\"16\\\" width=\\\"62\\\" style=\\\"margin-bottom: 3px;\\\"><\/a>.<\/p>\\n<\/div>\\n\\n<div class=\\\"pkgdown-footer-right\\\">\\n <p>Site built with <a href=\\\"https://pkgdown.r-lib.org/\\\" class=\\\"external-link\\\">pkgdown<\/a> 2.1.1.<\/p>\\n<\/div>\\n\\n <\/div><\/footer>\\n<\/body>\\n<\/html>\\n\" if (requireNamespace(\"xml2\", quietly = TRUE)) { resp |> resp_body_html() } #> {html_document} #> <html lang=\"en\"> #> [1] <head>\\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset ... #> [2] <body>\\n <a href=\"#container\" class=\"visually-hidden-focusable\"> ..."},{"path":"https://httr2.r-lib.org/dev/reference/resp_check_content_type.html","id":null,"dir":"Reference","previous_headings":"","what":"Check the content type of a response — resp_check_content_type","title":"Check the content type of a response — resp_check_content_type","text":"different content type expected often leads error parsing response body. function checks content type response expected fails otherwise.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_check_content_type.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Check the content type of a response — resp_check_content_type","text":"","code":"resp_check_content_type( resp, valid_types = NULL, valid_suffix = NULL, check_type = TRUE, call = caller_env() )"},{"path":"https://httr2.r-lib.org/dev/reference/resp_check_content_type.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Check the content type of a response — resp_check_content_type","text":"resp httr2 response object, created req_perform(). valid_types character vector valid MIME types. specified type/subtype. valid_suffix string given \"structured media type\" suffix. check_type type actually checked? Provided convenience using function inside resp_body_* helpers. call execution environment currently running function, e.g. caller_env(). function mentioned error messages source error. See call argument abort() information.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_check_content_type.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Check the content type of a response — resp_check_content_type","text":"Called side-effect; erroring response expected content type.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_check_content_type.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Check the content type of a response — resp_check_content_type","text":"","code":"resp <- response(headers = list(`content-type` = \"application/json\")) resp_check_content_type(resp, \"application/json\") try(resp_check_content_type(resp, \"application/xml\")) #> Error in eval(expr, envir) : #> Unexpected content type \"application/json\". #> • Expecting type \"application/xml\" # `types` can also specify multiple valid types resp_check_content_type(resp, c(\"application/xml\", \"application/json\"))"},{"path":"https://httr2.r-lib.org/dev/reference/resp_content_type.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract response content type and encoding — resp_content_type","title":"Extract response content type and encoding — resp_content_type","text":"resp_content_type() returns just type subtype Content-Type header. Content-Type provided; returns NA. Used resp_body_json(), resp_body_html(), resp_body_xml(). resp_encoding() returns likely character encoding text types, parsed charset parameter Content-Type header. header found, valid, charset parameter found, returns UTF-8. Used resp_body_string().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_content_type.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract response content type and encoding — resp_content_type","text":"","code":"resp_content_type(resp) resp_encoding(resp)"},{"path":"https://httr2.r-lib.org/dev/reference/resp_content_type.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract response content type and encoding — resp_content_type","text":"resp httr2 response object, created req_perform().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_content_type.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract response content type and encoding — resp_content_type","text":"string. content type specified resp_content_type() return character NA; encoding specified, resp_encoding() return \"UTF-8\".","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_content_type.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract response content type and encoding — resp_content_type","text":"","code":"resp <- response(headers = \"Content-type: text/html; charset=utf-8\") resp |> resp_content_type() #> [1] \"text/html\" resp |> resp_encoding() #> [1] \"utf-8\" # No Content-Type header resp <- response() resp |> resp_content_type() #> [1] NA resp |> resp_encoding() #> [1] \"UTF-8\""},{"path":"https://httr2.r-lib.org/dev/reference/resp_date.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract request date from response — resp_date","title":"Extract request date from response — resp_date","text":"responses contain request date Date header; provided server automatically added httr2.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_date.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract request date from response — resp_date","text":"","code":"resp_date(resp)"},{"path":"https://httr2.r-lib.org/dev/reference/resp_date.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract request date from response — resp_date","text":"resp httr2 response object, created req_perform().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_date.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract request date from response — resp_date","text":"POSIXct date-time.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_date.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract request date from response — resp_date","text":"","code":"resp <- response(headers = \"Date: Wed, 01 Jan 2020 09:23:15 UTC\") resp |> resp_date() #> [1] \"2020-01-01 09:23:15 UTC\" # If server doesn't add header (unusual), you get the time the request # was created: resp <- response() resp |> resp_date() #> [1] \"2020-01-01 UTC\""},{"path":"https://httr2.r-lib.org/dev/reference/resp_headers.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract headers from a response — resp_headers","title":"Extract headers from a response — resp_headers","text":"resp_headers() retrieves list headers. resp_header() retrieves single header. resp_header_exists() checks header present.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_headers.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract headers from a response — resp_headers","text":"","code":"resp_headers(resp, filter = NULL) resp_header(resp, header, default = NULL) resp_header_exists(resp, header)"},{"path":"https://httr2.r-lib.org/dev/reference/resp_headers.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract headers from a response — resp_headers","text":"resp httr2 response object, created req_perform(). filter regular expression used filter header names. NULL, default, returns headers. header Header name (case insensitive) default Default value use header exist.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_headers.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract headers from a response — resp_headers","text":"resp_headers() returns list. resp_header() returns string header exists NULL otherwise. resp_header_exists() returns TRUE FALSE.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_headers.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract headers from a response — resp_headers","text":"","code":"resp <- request(\"https://httr2.r-lib.org\") |> req_perform() resp |> resp_headers() #> <httr2_headers> #> server: GitHub.com #> content-type: text/html; charset=utf-8 #> last-modified: Wed, 23 Oct 2024 14:55:26 GMT #> access-control-allow-origin: * #> etag: W/\"67190e5e-4983\" #> expires: Wed, 23 Oct 2024 18:22:09 GMT #> cache-control: max-age=600 #> content-encoding: gzip #> x-proxy-cache: MISS #> x-github-request-id: D2CE:1451B9:19BD01:1A2D21:67193C77 #> accept-ranges: bytes #> date: Wed, 23 Oct 2024 18:13:45 GMT #> via: 1.1 varnish #> age: 19 #> x-served-by: cache-pao-kpao1770054-PAO #> x-cache: HIT #> x-cache-hits: 4 #> x-timer: S1729707225.441271,VS0,VE0 #> vary: Accept-Encoding #> x-fastly-request-id: 2c87968531fb2ec39e249069fddf6afa5edaadd8 #> content-length: 4636 resp |> resp_headers(\"x-\") #> <httr2_headers> #> x-proxy-cache: MISS #> x-github-request-id: D2CE:1451B9:19BD01:1A2D21:67193C77 #> x-served-by: cache-pao-kpao1770054-PAO #> x-cache: HIT #> x-cache-hits: 4 #> x-timer: S1729707225.441271,VS0,VE0 #> x-fastly-request-id: 2c87968531fb2ec39e249069fddf6afa5edaadd8 resp |> resp_header_exists(\"server\") #> [1] TRUE resp |> resp_header(\"server\") #> [1] \"GitHub.com\" # Headers are case insensitive resp |> resp_header(\"SERVER\") #> [1] \"GitHub.com\" # Returns NULL if header doesn't exist resp |> resp_header(\"this-header-doesnt-exist\") #> NULL"},{"path":"https://httr2.r-lib.org/dev/reference/resp_link_url.html","id":null,"dir":"Reference","previous_headings":"","what":"Parse link URL from a response — resp_link_url","title":"Parse link URL from a response — resp_link_url","text":"Parses URLs Link header defined RFC 8288.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_link_url.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Parse link URL from a response — resp_link_url","text":"","code":"resp_link_url(resp, rel)"},{"path":"https://httr2.r-lib.org/dev/reference/resp_link_url.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Parse link URL from a response — resp_link_url","text":"resp httr2 response object, created req_perform(). rel \"link relation type\" value retrieve URL.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_link_url.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Parse link URL from a response — resp_link_url","text":"Either string providing URL, specified rel exists, NULL .","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_link_url.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Parse link URL from a response — resp_link_url","text":"","code":"# Simulate response from GitHub code search resp <- response(headers = paste0(\"Link: \", '<https://api.github.com/search/code?q=addClass+user%3Amozilla&page=2>; rel=\"next\",', '<https://api.github.com/search/code?q=addClass+user%3Amozilla&page=34>; rel=\"last\"' )) resp_link_url(resp, \"next\") #> [1] \"https://api.github.com/search/code?q=addClass+user%3Amozilla&page=2\" resp_link_url(resp, \"last\") #> [1] \"https://api.github.com/search/code?q=addClass+user%3Amozilla&page=34\" resp_link_url(resp, \"prev\") #> NULL"},{"path":"https://httr2.r-lib.org/dev/reference/resp_raw.html","id":null,"dir":"Reference","previous_headings":"","what":"Show the raw response — resp_raw","title":"Show the raw response — resp_raw","text":"function reconstructs HTTP message httr2 received server. unlikely exactly byte--byte identical (servers compress least body, HTTP/2 can also compress headers), conveys information.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_raw.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Show the raw response — resp_raw","text":"","code":"resp_raw(resp)"},{"path":"https://httr2.r-lib.org/dev/reference/resp_raw.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Show the raw response — resp_raw","text":"resp httr2 response object, created req_perform().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_raw.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Show the raw response — resp_raw","text":"resp (invisibly).","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_raw.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Show the raw response — resp_raw","text":"","code":"resp <- request(example_url()) |> req_url_path(\"/json\") |> req_perform() resp |> resp_raw() #> HTTP/1.1 200 OK #> Connection: close #> Date: Wed, 23 Oct 2024 18:13:45 GMT #> Content-Type: application/json #> Content-Length: 407 #> ETag: \"de760e6d\" #> #> { #> \"firstName\": \"John\", #> \"lastName\": \"Smith\", #> \"isAlive\": true, #> \"age\": 27, #> \"address\": { #> \"streetAddress\": \"21 2nd Street\", #> \"city\": \"New York\", #> \"state\": \"NY\", #> \"postalCode\": \"10021-3100\" #> }, #> \"phoneNumbers\": [ #> { #> \"type\": \"home\", #> \"number\": \"212 555-1234\" #> }, #> { #> \"type\": \"office\", #> \"number\": \"646 555-4567\" #> } #> ], #> \"children\": [], #> \"spouse\": null #> } #>"},{"path":"https://httr2.r-lib.org/dev/reference/resp_retry_after.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract wait time from a response — resp_retry_after","title":"Extract wait time from a response — resp_retry_after","text":"Computes many seconds wait retrying request inspecting Retry-header. parses forms (absolute relative) returns number seconds wait. heading found, return NA.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_retry_after.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract wait time from a response — resp_retry_after","text":"","code":"resp_retry_after(resp)"},{"path":"https://httr2.r-lib.org/dev/reference/resp_retry_after.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract wait time from a response — resp_retry_after","text":"resp httr2 response object, created req_perform().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_retry_after.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract wait time from a response — resp_retry_after","text":"Scalar double giving number seconds wait retrying request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_retry_after.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract wait time from a response — resp_retry_after","text":"","code":"resp <- response(headers = \"Retry-After: 30\") resp |> resp_retry_after() #> [1] 30 resp <- response(headers = \"Retry-After: Mon, 20 Sep 2025 21:44:05 UTC\") resp |> resp_retry_after() #> [1] 180567845"},{"path":"https://httr2.r-lib.org/dev/reference/resp_status.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract HTTP status from response — resp_status","title":"Extract HTTP status from response — resp_status","text":"resp_status() retrieves numeric HTTP status code resp_status_desc() retrieves brief textual description. resp_is_error() returns TRUE status code represents error (.e. 4xx 5xx status). resp_check_status() turns HTTPs errors R errors. functions mostly internal use cases ever see 200 response: 1xx handled internally curl. 3xx redirects automatically followed. see deliberately suppressed redirects req |> req_options(followlocation = FALSE). 4xx client 5xx server errors automatically turned R errors. can stop turned R errors req_error(), e.g. req |> req_error(is_error = ~ FALSE).","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_status.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract HTTP status from response — resp_status","text":"","code":"resp_status(resp) resp_status_desc(resp) resp_is_error(resp) resp_check_status(resp, info = NULL, error_call = caller_env())"},{"path":"https://httr2.r-lib.org/dev/reference/resp_status.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract HTTP status from response — resp_status","text":"resp httr2 response object, created req_perform(). info character vector additional information include error message. Passed rlang::abort(). error_call execution environment currently running function, e.g. caller_env(). function mentioned error messages source error. See call argument abort() information.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_status.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract HTTP status from response — resp_status","text":"resp_status() returns scalar integer resp_status_desc() returns string resp_is_error() returns TRUE FALSE resp_check_status() invisibly returns response ok; otherwise throws error class httr2_http_{status}.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_status.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract HTTP status from response — resp_status","text":"","code":"# An HTTP status code you're unlikely to see in the wild: resp <- response(418) resp |> resp_is_error() #> [1] TRUE resp |> resp_status() #> [1] 418 resp |> resp_status_desc() #> [1] \"I'm a teapot\""},{"path":"https://httr2.r-lib.org/dev/reference/resp_stream_raw.html","id":null,"dir":"Reference","previous_headings":"","what":"Read a streaming body a chunk at a time — resp_stream_raw","title":"Read a streaming body a chunk at a time — resp_stream_raw","text":"resp_stream_raw() retrieves bytes (raw vectors). resp_stream_lines() retrieves lines text (character vectors). resp_stream_sse() retrieves server-sent events stream. currently works text mode connections calling req_perform_connection() must use mode = \"text\".","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_stream_raw.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Read a streaming body a chunk at a time — resp_stream_raw","text":"","code":"resp_stream_raw(resp, kb = 32) resp_stream_lines(resp, lines = 1, max_size = Inf, warn = TRUE) resp_stream_sse(resp, max_size = Inf) # S3 method for class 'httr2_response' close(con, ...)"},{"path":"https://httr2.r-lib.org/dev/reference/resp_stream_raw.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Read a streaming body a chunk at a time — resp_stream_raw","text":"resp, con streaming response created req_perform_connection(). kb many kilobytes (1024 bytes) data read. lines maximum number lines return . max_size maximum number bytes buffer; number bytes exceeded without line/event boundary, error thrown. warn Like readLines(): warn connection ends without final EOL. ... used; included compatibility generic.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_stream_raw.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Read a streaming body a chunk at a time — resp_stream_raw","text":"resp_stream_raw(): raw vector. resp_stream_lines(): character vector. resp_stream_sse(): list components type, data, id; NULL, signifying end stream reached –nonblocking mode–event currently available.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_url.html","id":null,"dir":"Reference","previous_headings":"","what":"Get URL/components from the response — resp_url","title":"Get URL/components from the response — resp_url","text":"resp_url() returns complete url. resp_url_path() returns path component. resp_url_query() returns single query component. resp_url_queries() returns query component named list.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_url.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Get URL/components from the response — resp_url","text":"","code":"resp_url(resp) resp_url_path(resp) resp_url_query(resp, name, default = NULL) resp_url_queries(resp)"},{"path":"https://httr2.r-lib.org/dev/reference/resp_url.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Get URL/components from the response — resp_url","text":"resp httr2 response object, created req_perform(). name Query parameter name. default Default value use query parameter exist.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_url.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Get URL/components from the response — resp_url","text":"","code":"resp <- request(example_url()) |> req_url_path(\"/get?hello=world\") |> req_perform() resp |> resp_url() #> [1] \"http://127.0.0.1:34151/get?hello=world\" resp |> resp_url_path() #> [1] \"/get\" resp |> resp_url_queries() #> $hello #> [1] \"world\" #> resp |> resp_url_query(\"hello\") #> [1] \"world\""},{"path":"https://httr2.r-lib.org/dev/reference/response.html","id":null,"dir":"Reference","previous_headings":"","what":"Create a new HTTP response — response","title":"Create a new HTTP response — response","text":"Generally, need call function directly; get real HTTP response calling req_perform() friends. function provided primarily testing, place describe key components response. response() creates generic response; response_json() creates response JSON body, automatically adding correct Content-Type header.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/response.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Create a new HTTP response — response","text":"","code":"response( status_code = 200, url = \"https://example.com\", method = \"GET\", headers = list(), body = raw() ) response_json( status_code = 200, url = \"https://example.com\", method = \"GET\", headers = list(), body = list() )"},{"path":"https://httr2.r-lib.org/dev/reference/response.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Create a new HTTP response — response","text":"status_code HTTP status code. Must single integer. url URL response came ; might URL request redirects. method HTTP method used retrieve response. headers HTTP headers. Can supplied raw character vector parsed using standard rules, named list. body Response, , contained response body. response_json(), R data structure serialize JSON.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/response.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Create a new HTTP response — response","text":"HTTP response: S3 list class httr2_response.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/response.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Create a new HTTP response — response","text":"","code":"response() #> <httr2_response> #> GET https://example.com #> Status: 200 OK #> Body: None response(404, method = \"POST\") #> <httr2_response> #> POST https://example.com #> Status: 404 Not Found #> Body: None response(headers = c(\"Content-Type: text/html\", \"Content-Length: 300\")) #> <httr2_response> #> GET https://example.com #> Status: 200 OK #> Content-Type: text/html #> Body: None"},{"path":"https://httr2.r-lib.org/dev/reference/resps_successes.html","id":null,"dir":"Reference","previous_headings":"","what":"Tools for working with lists of responses — resps_successes","title":"Tools for working with lists of responses — resps_successes","text":"function provide basic toolkit operating lists responses possibly errors, returned req_perform_parallel(), req_perform_sequential() req_perform_iterative(). resps_successes() returns list successful responses. resps_failures() returns list failed responses (.e. errors). resps_requests() returns list requests corresponds request. resps_data() returns data single vector data frame. requires vctrs package installed.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resps_successes.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Tools for working with lists of responses — resps_successes","text":"","code":"resps_successes(resps) resps_failures(resps) resps_requests(resps) resps_data(resps, resp_data)"},{"path":"https://httr2.r-lib.org/dev/reference/resps_successes.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Tools for working with lists of responses — resps_successes","text":"resps list responses (possibly including errors). resp_data function takes response (resp) returns data found inside response vector data frame.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resps_successes.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Tools for working with lists of responses — resps_successes","text":"","code":"reqs <- list( request(example_url()) |> req_url_path(\"/ip\"), request(example_url()) |> req_url_path(\"/user-agent\"), request(example_url()) |> req_template(\"/status/:status\", status = 404), request(\"INVALID\") ) resps <- req_perform_parallel(reqs, on_error = \"continue\") # find successful responses resps |> resps_successes() #> [[1]] #> <httr2_response> #> GET http://127.0.0.1:34151/ip #> Status: 200 OK #> Content-Type: application/json #> Body: In memory (27 bytes) #> #> [[2]] #> <httr2_response> #> GET http://127.0.0.1:34151/user-agent #> Status: 200 OK #> Content-Type: application/json #> Body: In memory (66 bytes) #> # collect all their data resps |> resps_successes() |> resps_data(\\(resp) resp_body_json(resp)) #> $origin #> [1] \"127.0.0.1\" #> #> $`user-agent` #> [1] \"httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0\" #> # find requests corresponding to failure responses resps |> resps_failures() |> resps_requests() #> [[1]] #> <httr2_request> #> GET http://127.0.0.1:34151/status/404 #> Body: empty #> #> [[2]] #> <httr2_request> #> GET INVALID #> Body: empty #>"},{"path":"https://httr2.r-lib.org/dev/reference/secrets.html","id":null,"dir":"Reference","previous_headings":"","what":"Secret management — secrets","title":"Secret management — secrets","text":"httr2 provides handful functions designed working confidential data. useful testing packages use httr2 often requires confidential data needs available testing, available package users. secret_encrypt() secret_decrypt() work individual strings secret_encrypt_file() encrypts file place secret_decrypt_file() decrypts file temporary location. secret_write_rds() secret_read_rds() work .rds files secret_make_key() generates random string use key. secret_has_key() returns TRUE key available; can use examples vignettes want evaluate CI, CRAN/package users. look key environment variable. used inside testthat, automatically testthat::skip() test env var found. (Outside testthat, error env var found.)","code":""},{"path":"https://httr2.r-lib.org/dev/reference/secrets.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Secret management — secrets","text":"","code":"secret_make_key() secret_encrypt(x, key) secret_decrypt(encrypted, key) secret_write_rds(x, path, key) secret_read_rds(path, key) secret_decrypt_file(path, key, envir = parent.frame()) secret_encrypt_file(path, key) secret_has_key(key)"},{"path":"https://httr2.r-lib.org/dev/reference/secrets.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Secret management — secrets","text":"x Object encrypt. Must string secret_encrypt(). key Encryption key; password allows \"lock\" \"unlock\" secret. easiest way specify name environment variable. Alternatively, already base64url encoded string, can wrap (), can pass raw vector directly. encrypted String decrypt path Path file encrypted file read write. secret_write_rds() secret_read_rds() .rds file. envir decrypted file automatically deleted environment exits. need set argument want pass unencrypted file another function.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/secrets.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Secret management — secrets","text":"secret_decrypt() secret_encrypt() return strings. secret_decrypt_file() returns path temporary file; secret_encrypt_file() encrypts file place. secret_write_rds() returns x invisibly; secret_read_rds() returns saved object. secret_make_key() returns string class AsIs. secret_has_key() returns TRUE FALSE.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/secrets.html","id":"basic-workflow","dir":"Reference","previous_headings":"","what":"Basic workflow","title":"Secret management — secrets","text":"Use secret_make_key() generate password. Make available env var (e.g. {MYPACKAGE}_KEY) adding line .Renviron. Encrypt strings secret_encrypt(), files secret_encrypt_file(), data secret_write_rds(), setting key = \"{MYPACKAGE}_KEY\". tests, decrypt data secret_decrypt(), secret_decrypt_file(), secret_read_rds() match encrypt . push code CI server, already \"work\" functions automatically skip tests {MYPACKAGE}_KEY env var set. make tests actually run, need set env var using whatever tool CI system provides setting env vars. Make sure carefully inspect test output check skips actually gone away.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/secrets.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Secret management — secrets","text":"","code":"key <- secret_make_key() path <- tempfile() secret_write_rds(mtcars, path, key = key) secret_read_rds(path, key) #> mpg cyl disp hp drat wt qsec vs am gear carb #> Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 #> Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 #> Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 #> Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 #> Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 #> Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 #> Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 #> Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 #> Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 #> Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4 #> Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4 #> Merc 450SE 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3 #> Merc 450SL 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3 #> Merc 450SLC 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3 #> Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4 #> Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4 #> Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4 #> Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1 #> Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2 #> Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1 #> Toyota Corona 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1 #> Dodge Challenger 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2 #> AMC Javelin 15.2 8 304.0 150 3.15 3.435 17.30 0 0 3 2 #> Camaro Z28 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4 #> Pontiac Firebird 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2 #> Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1 #> Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2 #> Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2 #> Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4 #> Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6 #> Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8 #> Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2 # While you can manage the key explicitly in a variable, it's much # easier to store in an environment variable. In real life, you should # NEVER use `Sys.setenv()` to create this env var because you will # also store the secret in your `.Rhistory`. Instead add it to your # .Renviron using `usethis::edit_r_environ()` or similar. Sys.setenv(\"MY_KEY\" = key) x <- secret_encrypt(\"This is a secret\", \"MY_KEY\") x #> [1] \"skw86WojAwJCvQY4wNnXJYCbj-fGpVsDhJg3ia2tbJ0\" secret_decrypt(x, \"MY_KEY\") #> [1] \"This is a secret\""},{"path":"https://httr2.r-lib.org/dev/reference/signal_total_pages.html","id":null,"dir":"Reference","previous_headings":"","what":"Signal total number pages — signal_total_pages","title":"Signal total number pages — signal_total_pages","text":"called within next_req callback function used req_perform_iterative()","code":""},{"path":"https://httr2.r-lib.org/dev/reference/signal_total_pages.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Signal total number pages — signal_total_pages","text":"","code":"signal_total_pages(n)"},{"path":"https://httr2.r-lib.org/dev/reference/signal_total_pages.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Signal total number pages — signal_total_pages","text":"n Total number pages.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/throttle_status.html","id":null,"dir":"Reference","previous_headings":"","what":"Display internal throttle status — throttle_status","title":"Display internal throttle status — throttle_status","text":"Sometimes useful debugging.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/throttle_status.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Display internal throttle status — throttle_status","text":"","code":"throttle_status()"},{"path":"https://httr2.r-lib.org/dev/reference/throttle_status.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Display internal throttle status — throttle_status","text":"data frame two columns: realm time last_request made.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/url_parse.html","id":null,"dir":"Reference","previous_headings":"","what":"Parse and build URLs — url_parse","title":"Parse and build URLs — url_parse","text":"url_parse() parses URL component pieces; url_build() reverse, converting list pieces string URL. See RFC 3986 details parsing algorithm.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/url_parse.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Parse and build URLs — url_parse","text":"","code":"url_parse(url) url_build(url)"},{"path":"https://httr2.r-lib.org/dev/reference/url_parse.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Parse and build URLs — url_parse","text":"url url_parse() string parse URL; url_build() URL turn back string.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/url_parse.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Parse and build URLs — url_parse","text":"url_build() returns string. url_parse() returns URL: S3 list class httr2_url elements scheme, hostname, port, path, fragment, query, username, password.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/url_parse.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Parse and build URLs — url_parse","text":"","code":"url_parse(\"http://google.com/\") #> <httr2_url> http://google.com/ #> • scheme: http #> • hostname: google.com #> • path: / url_parse(\"http://google.com:80/\") #> <httr2_url> http://google.com:80/ #> • scheme: http #> • hostname: google.com #> • port: 80 #> • path: / url_parse(\"http://google.com:80/?a=1&b=2\") #> <httr2_url> http://google.com:80/?a=1&b=2 #> • scheme: http #> • hostname: google.com #> • port: 80 #> • path: / #> • query: #> • a: 1 #> • b: 2 url_parse(\"http://username@google.com:80/path;test?a=1&b=2#40\") #> <httr2_url> http://username@google.com:80/path;test?a=1&b=2#40 #> • scheme: http #> • hostname: google.com #> • username: username #> • port: 80 #> • path: /path;test #> • query: #> • a: 1 #> • b: 2 #> • fragment: 40 url <- url_parse(\"http://google.com/\") url$port <- 80 url$hostname <- \"example.com\" url$query <- list(a = 1, b = 2, c = 3) url_build(url) #> [1] \"http://example.com:80/?a=1&b=2&c=3\""},{"path":"https://httr2.r-lib.org/dev/reference/with_mocked_responses.html","id":null,"dir":"Reference","previous_headings":"","what":"Temporarily mock requests — with_mocked_responses","title":"Temporarily mock requests — with_mocked_responses","text":"Mocking allows selectively temporarily replace response typically receive request code. primarily used testing.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/with_mocked_responses.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Temporarily mock requests — with_mocked_responses","text":"","code":"with_mocked_responses(mock, code) local_mocked_responses(mock, env = caller_env())"},{"path":"https://httr2.r-lib.org/dev/reference/with_mocked_responses.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Temporarily mock requests — with_mocked_responses","text":"mock function, list, NULL. NULL disables mocking returns httr2 regular operation. list responses returned sequence. responses used , return 503 server errors. maximum flexibility, can supply function takes single argument, req, returns either NULL (want handle request) response (). code Code execute temporary environment. env Environment use scoping changes.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/with_mocked_responses.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Temporarily mock requests — with_mocked_responses","text":"with_mock() returns result evaluating code.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/with_mocked_responses.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Temporarily mock requests — with_mocked_responses","text":"","code":"# This function should perform a response against google.com: google <- function() { request(\"http://google.com\") |> req_perform() } # But I can use a mock to instead return my own made up response: my_mock <- function(req) { response(status_code = 403) } try(with_mock(my_mock, google())) #> Warning: `with_mock()` was deprecated in httr2 1.0.0. #> ℹ Please use `with_mocked_responses()` instead. #> Error in req_perform(request(\"http://google.com\")) : HTTP 403 Forbidden."},{"path":"https://httr2.r-lib.org/dev/reference/with_verbosity.html","id":null,"dir":"Reference","previous_headings":"","what":"Temporarily set verbosity for all requests — with_verbosity","title":"Temporarily set verbosity for all requests — with_verbosity","text":"with_verbosity() useful debugging httr2 code buried deep inside another package allows see exactly sent requested.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/with_verbosity.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Temporarily set verbosity for all requests — with_verbosity","text":"","code":"with_verbosity(code, verbosity = 1)"},{"path":"https://httr2.r-lib.org/dev/reference/with_verbosity.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Temporarily set verbosity for all requests — with_verbosity","text":"code Code execture verbosity much information print? wrapper around req_verbose() uses integer control verbosity: 0: output 1: show headers 2: show headers bodies 3: show headers, bodies, curl status messages. Use with_verbosity() control verbosity requests affect directly.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/with_verbosity.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Temporarily set verbosity for all requests — with_verbosity","text":"result evaluating code.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/with_verbosity.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Temporarily set verbosity for all requests — with_verbosity","text":"","code":"fun <- function() { request(\"https://httr2.r-lib.org\") |> req_perform() } with_verbosity(fun()) #> -> GET / HTTP/2 #> -> Host: httr2.r-lib.org #> -> user-agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> -> accept: */* #> -> accept-encoding: deflate, gzip, br, zstd #> -> #> <- HTTP/2 200 #> <- server: GitHub.com #> <- content-type: text/html; charset=utf-8 #> <- last-modified: Wed, 23 Oct 2024 14:55:26 GMT #> <- access-control-allow-origin: * #> <- etag: W/\"67190e5e-4983\" #> <- expires: Wed, 23 Oct 2024 18:22:09 GMT #> <- cache-control: max-age=600 #> <- content-encoding: gzip #> <- x-proxy-cache: MISS #> <- x-github-request-id: D2CE:1451B9:19BD01:1A2D21:67193C77 #> <- accept-ranges: bytes #> <- date: Wed, 23 Oct 2024 18:13:48 GMT #> <- via: 1.1 varnish #> <- age: 23 #> <- x-served-by: cache-pao-kpao1770054-PAO #> <- x-cache: HIT #> <- x-cache-hits: 5 #> <- x-timer: S1729707229.662431,VS0,VE0 #> <- vary: Accept-Encoding #> <- x-fastly-request-id: 910c2a82cac2fc81ccae9741896220af58026967 #> <- content-length: 4636 #> <- #> <httr2_response> #> GET https://httr2.r-lib.org/ #> Status: 200 OK #> Content-Type: text/html #> Body: In memory (18819 bytes)"},{"path":[]},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-105","dir":"Changelog","previous_headings":"","what":"httr2 1.0.5","title":"httr2 1.0.5","text":"CRAN release: 2024-09-26 New req_auth_aws_v4() signs request using AWS’s special format (#562, #566). req_perform_parallel() req_perform_promise() now correctly set method body (#549).","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-104","dir":"Changelog","previous_headings":"","what":"httr2 1.0.4","title":"httr2 1.0.4","text":"CRAN release: 2024-09-13 req_body_file() now works files >64kb (#524) longer leaks connection response doesn’t complete succesfully (#534). req_body_*() now give informative error attempt change body type (#451). req_cache() now re-caches response body hasn’t modified headers changed (#442). also works better req_perform() sets path (#442). New req_cookie_set() allows set client side cookies (#369). req_perform() longer displays progress bar sleeping tests. can override behaviour setting option httr2_progress. req_perform_iterative() longer experimental. New req_perform_connection() working streaming data. Unlike req_perform_stream() uses callbacks, req_perform_connection() returns regular response object connection body. Unlike req_perform_stream() supports req_retry() (@jcheng5, #519). req_retry() longer treates low-level HTTP failures way transient errors default. can return previous behaviour retry_on_error = TRUE. resp_body_html() resp_body_xml() now work req_perform() given path (#448). New resp_stream_bytes(), resp_stream_lines(), resp_stream_sse() streaming chunk connection response (#519).","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-103","dir":"Changelog","previous_headings":"","what":"httr2 1.0.3","title":"httr2 1.0.3","text":"CRAN release: 2024-08-22 jwt_encode_hmac() now calls correct underlying function jose::jwt_encode_hmac() correct default size parameter value (@denskh, #508). req_cache() now prunes cache checking given key exists, eliminating occassional error reading invalid RDS file. also longer tests existence later reads cache, avoiding potential race conditions. New req_perform_promise() creates promises::promise request can run background (#501, @gergness). req_perform_parallel() now respects error handling req_error().","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-102","dir":"Changelog","previous_headings":"","what":"httr2 1.0.2","title":"httr2 1.0.2","text":"CRAN release: 2024-07-16 req_body_file() now opens connection request actually needs data. particular, makes work better req_perform_parallel() (#487). req_cache() longer fails rds files somehow corrupted now defaults debug argument httr2_cache_debug option make easier debug caching buried people’s code (#486). req_oauth_password() now asks password (#498). req_perform_parallel() now works correctly req_cache() (#447) now works downloading 0 byte files (#478) req_perform_stream() longer applies callback unsuccessful responses, instead creating regular response. also now sets last_request() last_response() (#479). req_url_query() now allows opt escaping multi-value parameters (#404).","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-101","dir":"Changelog","previous_headings":"","what":"httr2 1.0.1","title":"httr2 1.0.1","text":"CRAN release: 2024-04-01 req_perform_stream() gains round = c(\"byte\", \"line\") argument control stream rounded (#437). req_retry() gives clearer error returns wrong type value (#385). req_template() now works bare : template uses “uri” style (#389). req_timeout() now resets value connecttimeout set curl. ensures can use req_timeout() increase connection timeout past 10s (#395). url_parse() considerably faster thanks performance optimisations discussion @DyfanJones (#429).","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-100","dir":"Changelog","previous_headings":"","what":"httr2 1.0.0","title":"httr2 1.0.0","text":"CRAN release: 2023-11-14","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"function-lifecycle-1-0-0","dir":"Changelog","previous_headings":"","what":"Function lifecycle","title":"httr2 1.0.0","text":"local_mock() with_mock() deprecated favour local_mocked_responses() with_mocked_responses() (#301). multi_req_perform() deprecated favour req_perform_parallel(). req_stream() deprecated favour req_perform_stream() (#314). oauth_flow_auth_code() deprecates host_name port arguments favour using redirect_uri. also deprecates host_ip since seems unlikely changing ever useful. oauth_flow_auth_code_listen() now takes single redirect_uri argument instead separate host_ip port arguments. breaking change don’t expect anyone call function directly (confirmed GitHub search) made change without deprecation. req_body_form() req_body_multipart() now require data ...; longer accept single list compatibility 0.1.0 API.","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"multiple-requests-1-0-0","dir":"Changelog","previous_headings":"","what":"Multiple requests","title":"httr2 1.0.0","text":"New req_perform_sequential() performs known set requests sequentially. interface similar req_perform_parallel() limitations, cost slower (#361). New req_perform_iterative() performs multiple requests, request derived previous response (@mgirlich, #8). req_perform_parallel() replaces multi_req_perform() match new naming scheme (#314). gains progress argument. req_perform_iterative(), req_perform_parallel(), req_perform_sequential() share new error handling strategy. default, errors bubbled , can choose alternative strategy on_error argument (#372). new family functions resps_successes(), resps_failures(), resps_requests() resps_data() make easier work lists responses (#357). Behind scenes, work request now stored response (error) object (#357). resp_body_json() resp_body_xml() now cache parsed values can use repeatedly without worrying performance cost. supports design req_perform_iterative() avoiding need carefully pass around parsed object.","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"oauth-features-1-0-0","dir":"Changelog","previous_headings":"","what":"OAuth features","title":"httr2 1.0.0","text":"new vignette(\"oauth\") gives many details OAuth works use httr2 (#234), OAuth docs overhauled make clear use req_oauth_*(), oauth_*() (#330). using OAuth token refresh token, refresh token expired, httr2 now re-run entire flow get new token (#349). New oauth_cache_path() returns path httr2 uses caching OAuth tokens. Additionally, can now change cache location setting HTTR2_OAUTH_CACHE env var. now obvious user, httr2 now informs user whenever token cached. oauth_flow_auth_code() gains redirect_uri argument rather deriving URL automatically host_name port (#248). uses argument automatically choose strategy use get auth code, either launching temporary web server , new, allowing manually enter details help custom JS/HTML page hosted elsewhere, copying pasting URL ’re redirected (@fh-mthomson, #326). temporary web server now also respects path component redirect_uri, API needs specific path (#149). New oauth_token_cached() allows get OAuth token still taking advantage httr2’s caching auto-renewal features. expert use (#328).","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"other-new-features-1-0-0","dir":"Changelog","previous_headings":"","what":"Other new features","title":"httr2 1.0.0","text":"@mgirlich now httr2 contributor recognition many contributions. req_cache() gains max_n, max_size, max_age arguments automatically prune cache. default, cache stay 1 GB (#207). New req_body_json_modify() allows iteratively modify JSON body request. New req_cookie_preserve() lets use file share cookies across requests (#223). New req_progress() adds progress bar long downloads uploads (#20). New resp_check_content_type() check response content types (#190). resp_body_json() friends give better errors Content-Type header present response (#284). New resp_has_body() returns TRUE FALSE depending whether response body (#205). New resp_url(), resp_url_path(), resp_url_queries() resp_url_query() extract various part response url (#57). req_url_query() gains .multi parameter controls happens supply multiple values vector. default continue error can use .multi = \"comma\" separate commas, \"pipe\" separate |, \"explode\" generate one parameter value (e.g. ?=1&=2) (#350). New secret_encrypt_file() secret_decrypt_file() encrypting decrypting files (#237).","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"minor-improvements-and-bug-fixes-1-0-0","dir":"Changelog","previous_headings":"","what":"Minor improvements and bug fixes","title":"httr2 1.0.0","text":"httr2 examples now run R 4.2 later can use base pipe lambda syntax (#345). OAuth errors containing url now correctly display URL (instead string “uri”). curl_translate() now uses base pipe, produces escapes single quotes raw strings case double quotes can’t used (@mgirlich, #264). gains argument simplify_headers removes common unimportant headers, like Sec-Fetch-Dest sec-ch-ua-mobile (@mgirlich, #256). also parses query components url (@mgirlich, #259) works multiline commands clipboard (@mgirlich, #254). local_mocked_responses() with_mocked_responses() now accept list responses returned sequence. also now correctly trigger errors mocked response represents HTTP failure (#252). oauth_flow_refresh() now warns, errors, refresh_token changes, making little easier use manual workflows (#186). obfuscated() values now display original call printed. req_body_json() gains custom content type argument respects custom content-type set header (@mgirlich, #189). req_cache() now combine headers new response headers cached response. particular, fixes resp_body_json/xml/html() cached responses (@mgirlich, #277). req_perform() now throws error class httr2_failure/httr2_error request fails, error now captures curl error parent. request succeeds, response HTTP error, error now also super class httr2_error. means errors thrown httr2 now inherit httr2_error class. See new docs ?req_error() details. req_perform()’s progress bar can suppressed setting options(httr2_progress = FALSE) (#251). Progress bars displayed waiting time pass now tell ’re waiting (#206). req_oauth_bearer_jwt() now includes claim cache key (#192). req_oauth_device() now takes auth_url parameter making usable (#331, @taerwin). req_url_query() gains .multi parameter controls happens supply multiple values vector. default continue error can use .multi = \"comma\" separate commas, \"pipe\" separate |, \"explode\" generate one parameter value (e.g. ?=1&=2) (#350).","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-023","dir":"Changelog","previous_headings":"","what":"httr2 0.2.3","title":"httr2 0.2.3","text":"CRAN release: 2023-05-08 New example_url() launch local server, making tests examples robust. New throttle_status() make little easier verify ’s happening throttling. req_oauth_refresh() now respects refresh_token caching (@mgirlich, #178). req_perform() now always sleeps request, rather . also gains error_call argument communicates clearly error occurred (@mgirlich, #187). req_url_path() req_url_path_append() can now handle NULL empty ... elements ... can also length > 1 (@mgirlich, #177). sys_sleep() (used req_retry() req_throttle()) gains progress bar (#202).","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-022","dir":"Changelog","previous_headings":"","what":"httr2 0.2.2","title":"httr2 0.2.2","text":"CRAN release: 2022-09-25 curl_translate() can now handle curl copied Chrome developer tools (@mgirlich, #161). req_oauth_*() can now refresh OAuth tokens. One, two, even times! (@jennybc, #166) req_oauth_device() can now work non-interactive environments, intendend (@flahn, #170) req_oauth_refresh() oauth_flow_refresh() now use envvar HTTR2_REFRESH_TOKEN, HTTR_REFRESH_TOKEN (@jennybc, #169). req_proxy() now uses appropriate authentication option (@jl5000). req_url_query() can now opt escaping () (@boshek, #152). Can now print responses content type empty string (@mgirlich, #163).","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-021","dir":"Changelog","previous_headings":"","what":"httr2 0.2.1","title":"httr2 0.2.1","text":"CRAN release: 2022-05-10 “Wrapping APIs” now article, vignette. req_template() now appends path instead replacing (@jchrom, #133)","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-020","dir":"Changelog","previous_headings":"","what":"httr2 0.2.0","title":"httr2 0.2.0","text":"CRAN release: 2022-04-28","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"new-features-0-2-0","dir":"Changelog","previous_headings":"","what":"New features","title":"httr2 0.2.0","text":"req_body_form(), req_body_multipart(), req_url_query() now support multiple arguments name (#97, #107). req_body_form(), req_body_multipart(), now match interface req_url_query(), taking name-value pairs .... Supplying single list() now deprecated removed future version. req_body_json() now overrides existing JSON body, rather attempting merge previous value (#95, #115). Implement req_proxy() (owenjonesuob, #77).","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"minor-improvements-and-bug-fixes-0-2-0","dir":"Changelog","previous_headings":"","what":"Minor improvements and bug fixes","title":"httr2 0.2.0","text":"httr_path class renamed httr2_path correctly match package name (#99). oauth_flow_device() gains PKCE support (@flahn, #92), interactive flow little user friendly. req_error() can now correct force successful HTTP statuses fail (#98). req_headers() now override Content-Type set req_body_*() (#116). req_throttle() correctly sets throttle rate (@jchrom, #101). req_url_query() never uses scientific notation queries (#93). req_perform() now respects httr::with_verbose() (#85). response() now defaults body raw(0) consistency real responses (#100). req_stream() longer throws error non 200 http status codes (@DMerch, #137)","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-011","dir":"Changelog","previous_headings":"","what":"httr2 0.1.1","title":"httr2 0.1.1","text":"CRAN release: 2021-09-28 Fix R CMD check failures CRAN Added NEWS.md file track changes package.","code":""}] +[{"path":"https://httr2.r-lib.org/dev/LICENSE.html","id":null,"dir":"","previous_headings":"","what":"MIT License","title":"MIT License","text":"Copyright (c) 2021 httr2 authors Permission hereby granted, free charge, person obtaining copy software associated documentation files (“Software”), deal Software without restriction, including without limitation rights use, copy, modify, merge, publish, distribute, sublicense, /sell copies Software, permit persons Software furnished , subject following conditions: copyright notice permission notice shall included copies substantial portions Software. SOFTWARE PROVIDED “”, WITHOUT WARRANTY KIND, EXPRESS IMPLIED, INCLUDING LIMITED WARRANTIES MERCHANTABILITY, FITNESS PARTICULAR PURPOSE NONINFRINGEMENT. EVENT SHALL AUTHORS COPYRIGHT HOLDERS LIABLE CLAIM, DAMAGES LIABILITY, WHETHER ACTION CONTRACT, TORT OTHERWISE, ARISING , CONNECTION SOFTWARE USE DEALINGS SOFTWARE.","code":""},{"path":"https://httr2.r-lib.org/dev/articles/httr2.html","id":"create-a-request","dir":"Articles","previous_headings":"","what":"Create a request","title":"httr2","text":"httr2, start creating request. ’re familiar httr, big change: httr submit request, immediately receiving response. explicit request object makes easier build complex request piece piece works well pipe. Every request starts URL: , instead external website, use test server ’s built-httr2 . ensures vignette work regardless run . can see exactly request send server dry run: first line request contains three important pieces information: HTTP method, verb tells server want . ’s GET, common verb, indicating want get resource. verbs include POST, create new resource, PUT, replace existing resource, DELETE, delete resource. path, URL stripped details server already knows, .e. protocol (http https), host (localhost), port (46815). version HTTP protocol. unimportant purposes ’s handled lower level. following lines specify HTTP headers, series name-value pairs separated :. headers request automatically added httr2, can override add req_headers(): Header names case-insensitive, servers ignore headers don’t understand. headers finish blank line followed body. requests (like GET requests) don’t body, let’s add one see happens. req_body_*() functions provide variety ways add data body. ’ll use req_body_json() add data encoded JSON: ’s changed? method changed GET POST. POST standard method sending data website, automatically used whenever add body. Use req_method() different method. two new headers: Content-Type Content-Length. tell server interpret body — ’s encoded JSON 15 bytes long. body, consisting JSON. Different servers want data encoded differently httr2 provides selection common formats. example, req_body_form() uses encoding used submit form web browser: req_body_multipart() uses multipart encoding particularly important need send larger amounts data complete files: need send data encoded different form, can use req_body_raw() add data body set Content-Type header.","code":"req <- request(example_url()) req #> <httr2_request> #> GET http://127.0.0.1:46815/ #> Body: empty req |> req_dry_run() #> GET / HTTP/1.1 #> Host: 127.0.0.1:46815 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd req |> req_headers( Name = \"Hadley\", `Shoe-Size` = \"11\", Accept = \"application/json\" ) |> req_dry_run() #> GET / HTTP/1.1 #> Host: 127.0.0.1:46815 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept-Encoding: deflate, gzip, br, zstd #> Name: Hadley #> Shoe-Size: 11 #> Accept: application/json req |> req_body_json(list(x = 1, y = \"a\")) |> req_dry_run() #> POST / HTTP/1.1 #> Host: 127.0.0.1:46815 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Content-Type: application/json #> Content-Length: 15 #> #> {\"x\":1,\"y\":\"a\"} req |> req_body_form(x = \"1\", y = \"a\") |> req_dry_run() #> POST / HTTP/1.1 #> Host: 127.0.0.1:46815 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Content-Type: application/x-www-form-urlencoded #> Content-Length: 7 #> #> x=1&y=a req |> req_body_multipart(x = \"1\", y = \"a\") |> req_dry_run() #> POST / HTTP/1.1 #> Host: 127.0.0.1:46815 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Content-Length: 228 #> Content-Type: multipart/form-data; boundary=------------------------daec775293434987 #> #> --------------------------daec775293434987 #> Content-Disposition: form-data; name=\"x\" #> #> 1 #> --------------------------daec775293434987 #> Content-Disposition: form-data; name=\"y\" #> #> a #> --------------------------daec775293434987--"},{"path":"https://httr2.r-lib.org/dev/articles/httr2.html","id":"perform-a-request-and-fetch-the-response","dir":"Articles","previous_headings":"","what":"Perform a request and fetch the response","title":"httr2","text":"actually perform request fetch response back server, call req_perform(): can see simulation httr2 actually received resp_raw(): HTTP response similar structure HTTP request. first line gives version HTTP used, status code ’s optionally followed short description. headers, followed blank line, followed body. majority responses body, unlike requests. can extract data response using resp_() functions: resp_status() returns status code resp_status_desc() returns description: can extract headers resp_headers() specific header resp_header(): Headers case insensitive: can extract body various forms using resp_body_*() family functions. Since response returns JSON can use resp_body_json(): Responses status codes 4xx 5xx HTTP errors. httr2 automatically turns R errors: another important difference httr, required explicitly call httr::stop_for_status() turn HTTP errors R errors. can revert httr behaviour req_error(req, is_error = ~ FALSE).","code":"req <- request(example_url()) |> req_url_path(\"/json\") resp <- req |> req_perform() resp #> <httr2_response> #> GET http://127.0.0.1:46815/json #> Status: 200 OK #> Content-Type: application/json #> Body: In memory (407 bytes) resp |> resp_raw() #> HTTP/1.1 200 OK #> Connection: close #> Date: Wed, 23 Oct 2024 22:11:02 GMT #> Content-Type: application/json #> Content-Length: 407 #> ETag: \"de760e6d\" #> #> { #> \"firstName\": \"John\", #> \"lastName\": \"Smith\", #> \"isAlive\": true, #> \"age\": 27, #> \"address\": { #> \"streetAddress\": \"21 2nd Street\", #> \"city\": \"New York\", #> \"state\": \"NY\", #> \"postalCode\": \"10021-3100\" #> }, #> \"phoneNumbers\": [ #> { #> \"type\": \"home\", #> \"number\": \"212 555-1234\" #> }, #> { #> \"type\": \"office\", #> \"number\": \"646 555-4567\" #> } #> ], #> \"children\": [], #> \"spouse\": null #> } resp |> resp_status() #> [1] 200 resp |> resp_status_desc() #> [1] \"OK\" resp |> resp_headers() #> <httr2_headers> #> Connection: close #> Date: Wed, 23 Oct 2024 22:11:02 GMT #> Content-Type: application/json #> Content-Length: 407 #> ETag: \"de760e6d\" resp |> resp_header(\"Content-Length\") #> [1] \"407\" resp |> resp_header(\"ConTEnT-LeNgTH\") #> [1] \"407\" resp |> resp_body_json() |> str() #> List of 8 #> $ firstName : chr \"John\" #> $ lastName : chr \"Smith\" #> $ isAlive : logi TRUE #> $ age : int 27 #> $ address :List of 4 #> ..$ streetAddress: chr \"21 2nd Street\" #> ..$ city : chr \"New York\" #> ..$ state : chr \"NY\" #> ..$ postalCode : chr \"10021-3100\" #> $ phoneNumbers:List of 2 #> ..$ :List of 2 #> .. ..$ type : chr \"home\" #> .. ..$ number: chr \"212 555-1234\" #> ..$ :List of 2 #> .. ..$ type : chr \"office\" #> .. ..$ number: chr \"646 555-4567\" #> $ children : list() #> $ spouse : NULL request(example_url()) |> req_url_path(\"/status/404\") |> req_perform() #> Error in `req_perform()`: #> ! HTTP 404 Not Found. request(example_url()) |> req_url_path(\"/status/500\") |> req_perform() #> Error in `req_perform()`: #> ! HTTP 500 Internal Server Error."},{"path":"https://httr2.r-lib.org/dev/articles/httr2.html","id":"control-the-request-process","dir":"Articles","previous_headings":"","what":"Control the request process","title":"httr2","text":"number req_ functions don’t directly affect HTTP request instead control overall process submitting request handling response. include: req_cache() sets cache repeated requests return results, can avoid trip server. req_throttle() automatically add small delay request can avoid hammering server many requests. req_retry() sets retry strategy request either fails get transient HTTP error, ’ll automatically retry short delay. details see documentation, well examples usage real APIs vignette(\"wrapping-apis\").","code":""},{"path":"https://httr2.r-lib.org/dev/articles/oauth.html","id":"oauth-basics","dir":"Articles","previous_headings":"","what":"OAuth basics","title":"OAuth","text":"OAuth broad framework many different variants, called flows, makes hard provide sweeping generalisations, basic idea OAuth create hierarchy increasingly specific shorter-lived credentials, impact credential lost small possible. longest lived powerful credential typically user name password. people don’t change passwords regularly, often (advice) reuse password multiple websites. user name password, total control account; can even use change password actual user can’t log . means programmer never want touch user name-password pairs ’re lost stolen, give wide access. Avoiding problem lead creation OAuth. basic idea instead package asking user give user name password, instead ask log give package permission use API behalf. API gives permission form access token essentially random string numbers letters, e.g. UfNlXaEog03hdRPTUPpEInEiIW01jI1WcjOB. access token short lived, lasting maybe days, bound specified scope access. access token big advantages user name password: ’s short-lived ’s lost stolen, ’s limited amount time can abused. limited scope, even stolen, can’t used something particularly nefarious like changing password contact details. ’s bound specific application, can invalidated (cancelled) without affecting uses. access token can use authenticate API passing bearer token Authorization header, can req_auth_bearer_token(). However, cases want let httr2 manage calling one req_oauth_ functions ’ll talk shortly. One reasons want httr2 manage tokens access tokens short lived, ’re often accompanied refresh token. refresh token lasts longer amount time one job: allows get new access token previous one expires. need look refresh token little carefully access token. particular, never include refresh token HTTP request ’s job access token. Overall leads hierarchy credentials weakest strongest: access token usually lasts couple hours needs submitted every request. refresh token lasts days weeks ’s designed stored locally can regenerate access tokens. (’ll talk Caching, .) user name + password gives access everything code never touch ! Now ’ve got basic idea OAuth, lets talk details.","code":""},{"path":"https://httr2.r-lib.org/dev/articles/oauth.html","id":"clients","dir":"Articles","previous_headings":"","what":"Clients","title":"OAuth","text":"first step working OAuth API create application client. ’s called application client wider world OAuth usually used web, phone, tv app, “app” going R package. reason, httr2 calls application client client, many APIs call OAuth application. create client, ’ll need first register developer account API’s website. cases easy, totally automated, takes couple minutes. give access sort developer portal can use register new OAuth app (aka client). process varies API API (’s normal spend time hunting docs settings), end ’ll get client id (another random string numbers letters). Sometimes client id need, can create httr2 client oauth_client(), e.g.: call oauth_client() also includes name token_url. name human-facing, typically package (thing prompted create client). bunch apps ’ve used testing, ’ve used name hadley-oauth-test-2 remind app client corresponds . token_url points URL ’s used obtain access token. ’ll need find documentation API ’re wrapping; typically found section describes OAuth process endpoint returns access token. Don’t surprised endpoint feels different rest API; auth often implemented third-party package slightly different conventions rest API.","code":"client <- oauth_client( id = \"28acfec0674bb3da9f38\", token_url = \"https://github.com/login/oauth/access_token\", name = \"hadley-oauth-test-2\" )"},{"path":"https://httr2.r-lib.org/dev/articles/oauth.html","id":"client-secret","dir":"Articles","previous_headings":"Clients","what":"Client secret","title":"OAuth","text":"cases, however, API also require client secret. called secret, ’s typically important keep secret two reasons: ’s typically easy create new app developer website stealing wouldn’t save much time. ’s unusual OAuth client able anything right, stealing secret doesn’t much benefit. means unless paid app given private information creating , ’s ok embed client package. said, httr2 provides tooling obfuscate client secret client secret isn’t directly embedded source code, hence vulnerable scraping. obfuscate string, call obfuscate(), copy paste result package. example, client secret “secret”, ’d call obfuscate() ’d copy paste obfuscated(\"B4Evdd5x4wl0XTWvtTpuGaw7nM7GEg\") client specification. ’s complete client specification GitHub looks like, using real app created specifically vignette: can certainly uncover client secret experienced R programmer willing spend bit time experimenting, ’m pretty sure ’d easy just create app GitHub.","code":"obfuscate(\"secret\") #> obfuscated(\"f5LXTegwNUQuMsVtP4Y6gSR-tBNENQ\") client <- oauth_client( id = \"28acfec0674bb3da9f38\", secret = obfuscated(\"J9iiGmyelHltyxqrHXW41ZZPZamyUNxSX1_uKnvPeinhhxET_7FfUs2X0LLKotXY2bpgOMoHRCo\"), token_url = \"https://github.com/login/oauth/access_token\", name = \"hadley-oauth-test\" )"},{"path":"https://httr2.r-lib.org/dev/articles/oauth.html","id":"packaging","dir":"Articles","previous_headings":"Clients","what":"Packaging","title":"OAuth","text":"recommend wrapping client creation function package, e.g.: ’ll need order run tests package, ’ll probably also want use default client users. cases, necessary user create app matching client (e.g. rate limits applied app, user), much less user friendly avoid possible. said, always provide way user supply client bundle default. can see example googledrive package.","code":"github_client <- function() { oauth_client( id = \"28acfec0674bb3da9f38\", secret = obfuscated(\"J9iiGmyelHltyxqrHXW41ZZPZamyUNxSX1_uKnvPeinhhxET_7FfUs2X0LLKotXY2bpgOMoHRCo\"), token_url = \"https://github.com/login/oauth/access_token\", name = \"hadley-oauth-test\" ) }"},{"path":"https://httr2.r-lib.org/dev/articles/oauth.html","id":"authorization-code-flow","dir":"Articles","previous_headings":"","what":"Authorization code flow","title":"OAuth","text":"client need use flow order get token. ’ll need read docs API figure flows supports, common authorization code2 flow, works something like : httr2 opens browser using authorization URL provided API. URL includes parameters identify app scope access ’re looking (e.g. tweet.read, userinfo.write). user logs using user name password (hopefully using password manager) approves request. API sends authorization code back httr2 using callback URL supplied initial request. httr2 sends authorization code token URL get access token. httr2 flow implemented pair functions: oauth_flow_auth_code() req_oauth_auth_code(). Start oauth_flow_auth_code() check parameters correctly specified, use req_oauth_auth_code() authenticate requests. two steps described following sections.","code":""},{"path":"https://httr2.r-lib.org/dev/articles/oauth.html","id":"creating-a-token","dir":"Articles","previous_headings":"Authorization code flow","what":"Creating a token","title":"OAuth","text":"oauth_flow_auth_code() best way verify ’ve correctly specified parameters client auth_url, without depending correctly understanding part API. example, get token access GitHub API (using client defined ) code: flow can’t used inside vignette ’s designed specifically interactive use, run print token, ’ll see something like : ’s much see httr2 automatically redacts access token (used perform actions behalf user). call oauth_flow_auth_code() succeeds ’ve got everything set correctly can proceed next step. Otherwise, ’ll get HTTP error. ’re lucky, error informative help figure want went wrong. However, cases, ’ll need carefully double check ’ve correctly copied pasted client id secret, check ’ve supplied correct authorization token urls (auth_url token_url). docs multiple candidates ’re unclear , ’ll need systematic experimentation.","code":"token <- oauth_flow_auth_code( client = client, auth_url = \"https://github.com/login/oauth/authorize\" ) token #> <httr2_token> #> token_type: bearer #> access_token: <REDACTED> #> scope: ''"},{"path":"https://httr2.r-lib.org/dev/articles/oauth.html","id":"authenticating-a-request","dir":"Articles","previous_headings":"Authorization code flow","what":"Authenticating a request","title":"OAuth","text":"Initial configuration time ’ll see httr2_token object ’ll generally want rely httr2 manage tokens . ’ll req_oauth_auth_code(). check ’s working correctly, recommend finding simplest possible API endpoint test . good place start endpoint provides information “current” user, API provides one. example, GitHub API provides GET endpoint /user returns information current user. make request endpoint without authentication, ’ll get error: can authenticate request req_oauth_auth_code(), using arguments previous call oauth_flow_auth_code(): run code, ’ll see something like , obviously contain information , .","code":"req <- request(\"https://api.github.com/user\") req |> req_perform() #> Error in `req_perform()`: #> ! HTTP 401 Unauthorized. req |> req_oauth_auth_code( client = github_client(), auth_url = \"https://github.com/login/oauth/authorize\" ) |> req_perform() |> resp_body_json() |> str() #> List of 32 #> $ login : chr \"hadley\" #> $ id : int 4196 #> $ node_id : chr \"MDQ6VXNlcjQxOTY=\" #> $ avatar_url : chr \"https://avatars.githubusercontent.com/u/4196?v=4\" #> $ gravatar_id : chr \"\" #> $ url : chr \"https://api.github.com/users/hadley\" #> $ html_url : chr \"https://github.com/hadley\" #> ... #> $ type : chr \"User\" #> $ site_admin : logi FALSE #> $ name : chr \"Hadley Wickham\" #> $ company : chr \"@posit-pbc\" #> $ blog : chr \"http://hadley.nz\" #> $ location : chr \"Houston, TX\""},{"path":"https://httr2.r-lib.org/dev/articles/oauth.html","id":"caching","dir":"Articles","previous_headings":"Authorization code flow","what":"Caching","title":"OAuth","text":"two big reasons allow httr2 manage tokens . first httr2 automatically refresh token ’s expired. second cross-session caching, described . default, OAuth token cached memory. means need authenticate current session, ’ll need re-authenticate restart R. cases, may want save tokens (refresh access) can used across sessions. easy (just set cache_disk = TRUE) need think consequences saving refresh token disk. httr2 best can save credentials securely. stored local cache directory (oauth_cache_path()) accessible current user, encrypted hard package httr2 read. However, ’s way prevent R code using httr2 access , choose cache tokens, inform user give ability opt-. httr2 automatically deletes cached tokens older 30 days whenever ’s loaded. means ’ll need re-auth least month, prevents tokens hanging around disk long ’ve forgotten created . can see clients cached tokens looking cache directory used httr2: client gets subdirectory named using client name, turn caching , ’s particularly important give client good name user can easily tell package tokens belong .","code":"dir(oauth_cache_path(), recursive = TRUE)"},{"path":"https://httr2.r-lib.org/dev/articles/oauth.html","id":"other-flows","dir":"Articles","previous_headings":"","what":"Other flows","title":"OAuth","text":"wrapping API, ’ll need carefully read documentation figure flows provides. possible ’ll want use authorization code flow since generally provides best experience, ’s available ’ll need carefully consider others. Currently, httr2 supports following flows: req_oauth_device() uses “device” flow designed devices like TVs don’t easy way enter data. also works well console. req_oauth_client_credentials() req_oauth_bearer_jwt() often needed service accounts, accounts represent automated services, people, often used non-interactive environments. req_oauth_password() exchanges user name password access token. req_oauth_refresh() works directly refresh token already . ’s useful testing automation. httr2 doesn’t support implicit grant flow. historically important now mostly deprecated never particularly good fit R relies technique returning access token reliably works inside web browser. Regardless flow use, ’ll need follow process example : first figure get token using oauth_flow_ function, actually use oauth request, calling matching req_oauth_ function. One additional wrinkle many APIs don’t implement flow exactly way spec httr2’s built-flows might work . initial attempt doesn’t work, ’re going need sleuthing. going painful, unfortunately ’s way around . recommend wrapping httr2 code with_verbosity() can see exactly httr2 sending server. ’ll need carefully compare API documentation play “spot difference”. ’re welcome file issue ’ll best help .","code":""},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"faker-api","dir":"Articles","previous_headings":"","what":"Faker API","title":"Wrapping APIs","text":"’ll start simple API, faker API, provides collection techniques generating fake data. start writing sort functions might put package, ’ll perform request just see basics work:","code":"# We start by creating a request that uses the base API url req <- request(\"https://fakerapi.it/api/v1\") resp <- req |> # Then we add on the images path req_url_path_append(\"images\") |> # Add query parameters _width and _quantity req_url_query(`_width` = 380, `_quantity` = 1) |> req_perform() # The result comes back as JSON resp |> resp_body_json() |> str() #> List of 6 #> $ status: chr \"OK\" #> $ code : int 200 #> $ locale: chr \"en_US\" #> $ seed : NULL #> $ total : int 1 #> $ data :List of 1 #> ..$ :List of 3 #> .. ..$ title : chr \"Aut porro aut et possimus.\" #> .. ..$ description: chr \"Et voluptatem provident libero sequi ea rerum. Omnis reiciendis quia et. Non veniam repellat odit facilis ut ut\"| __truncated__ #> .. ..$ url : chr \"https://picsum.photos/380/480\""},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"errors","dir":"Articles","previous_headings":"Faker API","what":"Errors","title":"Wrapping APIs","text":"’s always worth little early experimentation see get useful information errors. httr2 defaults get way , retrieve unsuccessful HTTP response, automatically get error prevents inspecting body: However, can access last response (successful ) last_response(): doesn’t look like ’s anything useful . Sometimes useful info returned headers, let’s check: doesn’t look like ’re getting useful information, can leave req_error() default . ’ll another go later API provide details.","code":"req |> req_url_path_append(\"invalid\") |> req_perform() #> Error in `req_perform()`: #> ! HTTP 400 Bad Request. resp <- last_response() resp |> resp_body_json() #> $message #> [1] \"Resource invalid not supported in version v1\" resp |> resp_headers() #> <httr2_headers> #> Server: nginx #> Content-Type: application/json #> Transfer-Encoding: chunked #> Connection: keep-alive #> X-Powered-By: PHP/8.3.8 #> Cache-Control: no-cache, private #> Date: Wed, 23 Oct 2024 22:11:09 GMT #> X-RateLimit-Limit: 60 #> X-RateLimit-Remaining: 56 #> Access-Control-Allow-Origin: *"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"user-agent","dir":"Articles","previous_headings":"Faker API","what":"User agent","title":"Wrapping APIs","text":"’re wrapping code package, ’s considered polite set user agent, , package accidentally something horribly wrong, developers website can figure reach . can req_user_agent() function:","code":"req |> req_user_agent(\"my_package_name (http://my.package.web.site)\") |> req_dry_run() #> GET /api/v1 HTTP/1.1 #> Host: fakerapi.it #> User-Agent: my_package_name (http://my.package.web.site) #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"core-request-function","dir":"Articles","previous_headings":"Faker API","what":"Core request function","title":"Wrapping APIs","text":"’ve made successful requests, ’s worth seeing can figure general pattern can wrap function become core package. faker, spent little time documentation noting commonalities: Every URL form https://fakerapi./api/v1/{resource}, data passed resource query parameters. parameters start _. Every resource three common query parameters: _locale, _quantity, _seed. endpoints return JSON data. led construct following function: ’ve made important choices : ’ve decided supply default values quantity locale parameters. makes function easier demo vignette. ’ve used default NULL seed argument. req_url_query() automatically drop NULL arguments means default value sent API, read function definition can still see seed accepted. automatically prefix query parameters _ argument names starting _ hard type R. function generates request, performs , extracts body response. works well simple cases, complex APIs might want return request object can modified performed. also used one cool trick: req_url_query() uses dynamic dots, can use !!! convert (e.g.) req_url_query(req, !!!list(`_quantity` = 1, `_locale` = \"en_US\")) req_url_query(req, `_quantity` = 1, `_locale` = \"en_US\").","code":"faker <- function(resource, ..., quantity = 1, locale = \"en_US\", seed = NULL) { params <- list( ..., quantity = quantity, locale = locale, seed = seed ) names(params) <- paste0(\"_\", names(params)) request(\"https://fakerapi.it/api/v1\") |> req_url_path_append(resource) |> req_url_query(!!!params) |> req_user_agent(\"my_package_name (http://my.package.web.site)\") |> req_perform() |> resp_body_json() } str(faker(\"images\", width = 300)) #> List of 6 #> $ status: chr \"OK\" #> $ code : int 200 #> $ locale: chr \"en_US\" #> $ seed : NULL #> $ total : int 1 #> $ data :List of 1 #> ..$ :List of 3 #> .. ..$ title : chr \"Neque est sit itaque.\" #> .. ..$ description: chr \"Provident deleniti dolor officiis. Amet saepe cumque eos id expedita sint. Eius odio maiores qui debitis ut cul\"| __truncated__ #> .. ..$ url : chr \"https://picsum.photos/300/480\""},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"wrapping-individual-endpoints","dir":"Articles","previous_headings":"Faker API","what":"Wrapping individual endpoints","title":"Wrapping APIs","text":"faker() quite general — ’s good tool package developer can read faker documentation translate function call. ’s friendly package user might know anything web APIs. typically next step process wrap individual endpoints functions. example, let’s take persons endpoint three additional parameters: gender (male female), birthday_start, birthday_end. simple wrapper start something like : make user friendly checking input types, returning result tibble. quick dirty conversion using purrr; depending needs use base R code tidyr::hoist(). next steps export document function; ’ll leave .","code":"faker_person <- function(gender = NULL, birthday_start = NULL, birthday_end = NULL, quantity = 1, locale = \"en_US\", seed = NULL) { faker( \"persons\", gender = gender, birthday_start = birthday_start, birthday_end = birthday_end, quantity = quantity, locale = locale, seed = seed ) } str(faker_person(\"male\")) #> List of 6 #> $ status: chr \"OK\" #> $ code : int 200 #> $ locale: chr \"en_US\" #> $ seed : NULL #> $ total : int 1 #> $ data :List of 1 #> ..$ :List of 10 #> .. ..$ id : int 1 #> .. ..$ firstname: chr \"Ari\" #> .. ..$ lastname : chr \"Donnelly\" #> .. ..$ email : chr \"xhudson@rutherford.org\" #> .. ..$ phone : chr \"+13802154733\" #> .. ..$ birthday : chr \"1990-08-02\" #> .. ..$ gender : chr \"male\" #> .. ..$ address :List of 10 #> .. .. ..$ id : int 1 #> .. .. ..$ street : chr \"6180 Bosco Court Apt. 363\" #> .. .. ..$ streetName : chr \"Anabel Parkway\" #> .. .. ..$ buildingNumber: chr \"19405\" #> .. .. ..$ city : chr \"Quinnville\" #> .. .. ..$ zipcode : chr \"65194-6912\" #> .. .. ..$ country : chr \"Rwanda\" #> .. .. ..$ country_code : chr \"RW\" #> .. .. ..$ latitude : num 52.8 #> .. .. ..$ longitude : num 68.6 #> .. ..$ website : chr \"http://marks.info\" #> .. ..$ image : chr \"http://placeimg.com/640/480/people\" library(purrr) faker_person <- function(gender = NULL, birthday_start = NULL, birthday_end = NULL, quantity = 1, locale = \"en_US\", seed = NULL) { if (!is.null(gender)) { gender <- match.arg(gender, c(\"male\", \"female\")) } if (!is.null(birthday_start)) { if (!inherits(birthday_start, \"Date\")) { stop(\"`birthday_start` must be a date\") } birthday_start <- format(birthday_start, \"%Y-%m-%d\") } if (!is.null(birthday_end)) { if (!inherits(birthday_end, \"Date\")) { stop(\"`birthday_end` must be a date\") } birthday_end <- format(birthday_end, \"%Y-%m-%d\") } json <- faker( \"persons\", gender = gender, birthday_start = birthday_start, birthday_end = birthday_end, quantity = quantity, locale = locale, seed = seed ) tibble::tibble( firstname = map_chr(json$data, \"firstname\"), lastname = map_chr(json$data, \"lastname\"), email = map_chr(json$data, \"email\"), gender = map_chr(json$data, \"gender\") ) } faker_person(\"male\", quantity = 5) #> # A tibble: 5 × 4 #> firstname lastname email gender #> <chr> <chr> <chr> <chr> #> 1 Orrin Batz walsh.francisco@beier.com male #> 2 Dexter Powlowski harris.angie@ondricka.net male #> 3 Randal Schimmel langosh.modesta@harris.com male #> 4 Tyrell Schultz pablo.batz@gmail.com male #> 5 Beau Ankunding konopelski.river@hotmail.com male"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"secret-management","dir":"Articles","previous_headings":"","what":"Secret management","title":"Wrapping APIs","text":"need take quick break APIs talk secrets. Secrets important, every API (except simple APIs like faker) going require identify way, typically API key token. even plan require users supply information, ’ll still need record credentials order test package. system described likely overkill one secret needs shared couple places: can just put .Renviron access Sys.getenv(). probably accumulate secrets time, ’ll need figure share people computers, think spending little time understand system set package pay long term.","code":""},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"basics","dir":"Articles","previous_headings":"Secret management","what":"Basics","title":"Wrapping APIs","text":"httr2 provides secret_encrypt() secret_decrypt() scramble secrets can include public source code without worrying others can read . three basic steps process: create encryption key secret_make_key() used scramble descramble secrets using symmetric cryptography: (Note secret_make_key() uses cryptographically secure random number generator provided OpenSSL; affected R’s RNG settings, ’s way make reproducible.) scramble secrets secret_encrypt() store resulting text directly source code package: needed, descramble secret using secret_decrypt():","code":"key <- secret_make_key() key #> [1] \"w0KujW4GaNMlS4RYNxYrOQ\" secret_scrambled <- secret_encrypt(\"secret I need to work with an API\", key) secret_scrambled #> [1] \"8YRzIpKrl3qAfM6Sr4NReyMtoO_TbCzBhKXtxGpzlCcjzxWc8nQz_g5GlXMdNhdaYg\" secret_decrypt(secret_scrambled, key) #> [1] \"secret I need to work with an API\""},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"package-keys-and-secrets","dir":"Articles","previous_headings":"Secret management","what":"Package keys and secrets","title":"Wrapping APIs","text":"can create number encryption keys, highly recommend create one key per package, ’ll call package key. section, ’ll show store key (automated tests) can use , one else can. httr2 built around notion key live environment variable. first step make package key available local development machine adding line user-level .Renviron (can easily open usethis::edit_r_environ()): Now (restart R), ’ll able take advantage special secret_encrypt() secret_decrypt() feature: key argument can name environment variable, instead encryption key . fact, natural usage. ’ll also need make key available GitHub Actions (check pkgdown) automated tests can use . requires two steps: Add key repository secrets. Share key workflows need adding line appropriate workflow: can see httr2 GitHub workflow. continuous integration platforms offer similar ways make key available secure environment variable.","code":"YOURPACKAGE_KEY=key_you_generated_with_secret_make_key secret_scrambled <- secret_encrypt(\"secret I need to work with an API\", \"YOURPACKAGE_KEY\") secret_scrambled #> [1] \"8CjGTE7kbnDPSFihrrjKcj39J3ddD9_bP6-MsPWXyBdG4vrUp7uahDnx3MpvqXNKLQ\" secret_decrypt(secret_scrambled, \"YOURPACKAGE_KEY\") #> [1] \"secret I need to work with an API\" env: YOURPACKAGE_KEY: ${{ secrets.YOURPACKAGE_KEY }}"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"when-the-package-key-isnt-available","dir":"Articles","previous_headings":"Secret management","what":"When the package key isn’t available","title":"Wrapping APIs","text":"important cases code won’t access package key: CRAN, personal machines external contributors, automated checks PRs. want share package CRAN make easy others contribute, need make sure examples, vignettes, tests work without error: vignettes, can run knitr::opts_chunk(eval = secret_has_key(\"YOURPACKAGE_KEY\")) chunks evaluated key available. examples, can surround code blocks require key (httr2::secret_has_key(\"YOURPACKAGE_KEY\")) {} don’t need anything tests secret_decrypt() run testthat, automatically skip() test key isn’t available.","code":""},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"nytimes-books-api","dir":"Articles","previous_headings":"","what":"NYTimes Books API","title":"Wrapping APIs","text":"Next ’ll take look NYTimes Books API. requires simple authentication API key ’s included every request. ’re wrapping API key ’re going face two struggles: test package without sharing key whole world? allow users supply key, without pass every function? now can understand following code works get NYTimes Book API key: ’ll start tackling first problem otherwise ’s way show API works vignette 😃. ’ll come back second end section, ’s easiest tackle function place.","code":"my_key <- secret_decrypt(\"4Nx84VPa83dMt3X6bv0fNBlLbv3U4D1kHM76YisKEfpCarBm1UHJHARwJHCFXQSV\", \"HTTR2_KEY\")"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"security-considerations","dir":"Articles","previous_headings":"NYTimes Books API","what":"Security considerations","title":"Wrapping APIs","text":"Note including API key query parameter relatively insecure; API uses method auth, ’s typically key relatively easy create gives relatively privileges. takes couple minutes generate NYTimes API key, ’s little incentive someone try steal . main problem conveying credentials via url ’s easily exposed, httr2 makes efforts redact confidential information stored query parameters. means ’s relatively easy leak key use req_perform(verbosity = 1), req_dry_run(), even just print request object. indeed, ’ll see examples — bad practice real package, think ’s ok key doesn’t allow anything valuable makes teaching APIs much easier.","code":""},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"basic-request","dir":"Articles","previous_headings":"NYTimes Books API","what":"Basic request","title":"Wrapping APIs","text":"Now let’s perform test request look response: Like modern APIs, one returns results JSON: start wrapping function, let’s consider happens errors.","code":"resp <- request(\"https://api.nytimes.com/svc/books/v3\") |> req_url_path_append(\"/reviews.json\") |> req_url_query(`api-key` = my_key, isbn = 9780307476463) |> req_perform() resp resp |> resp_body_json() |> str()"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"error-handling","dir":"Articles","previous_headings":"NYTimes Books API","what":"Error handling","title":"Wrapping APIs","text":"happens ’s error? example, deliberately supply invalid key: see ’s extra useful information can look last_response(): looks like ’s useful additional info faultstring: add information future errors can use body argument req_error(). function takes response returns character vector additional information include error. re-fetch request, see additional information displayed R error:","code":"resp <- request(\"https://api.nytimes.com/svc/books/v3\") |> req_url_path_append(\"/reviews.json\") |> req_url_query(`api-key` = \"invalid\", isbn = 9780307476463) |> req_perform() resp <- last_response() resp resp |> resp_body_json() resp |> resp_body_json() |> _$fault |> _$faultstring nytimes_error_body <- function(resp) { resp |> resp_body_json() |> _$fault |> _$faultstring } resp <- request(\"https://api.nytimes.com/svc/books/v3\") |> req_url_path_append(\"/reviews.json\") |> req_url_query(`api-key` = \"invalid\", isbn = 9780307476463) |> req_error(body = nytimes_error_body) |> req_perform()"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"rate-limits","dir":"Articles","previous_headings":"NYTimes Books API","what":"Rate limits","title":"Wrapping APIs","text":"Another common source errors rate-limiting — used many servers prevent one unruly client consuming many resources. frequently asked questions page describes rate limits NYT APIs: Yes, two rate limits per API: 4,000 requests per day 10 requests per minute. sleep 6 seconds calls avoid hitting per minute rate limit. need higher rate limit, please contact us code@nytimes.com. Many APIs return additional information long wait rate limit exceeded (often using Retry-header). deliberately violated rate limit quickly making 11 requests; unfortunately response standard 429 (many requests), include information long wait either response body headers. means can’t use req_retry(), automatically waits amount time server requests. Instead, ’ll use req_throttle() ensure don’t make 10 requests every 60 seconds: default, req_throttle() shares limit across requests made host (.e. api.nytimes.com). Since docs suggest rate limit applies per API, might want use realm argument bit specific:","code":"req <- request(\"https://api.nytimes.com/svc/books/v3\") |> req_url_path_append(\"/reviews.json\") |> req_url_query(`api-key` = \"invalid\", isbn = 9780307476463) |> req_throttle(10 / 60) req <- request(\"https://api.nytimes.com/svc/books/v3\") |> req_url_path_append(\"/reviews.json\") |> req_url_query(`api-key` = \"invalid\", isbn = 9780307476463) |> req_throttle(10 / 60, realm = \"https://api.nytimes.com/svc/books\")"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"wrapping-it-up","dir":"Articles","previous_headings":"NYTimes Books API","what":"Wrapping it up","title":"Wrapping APIs","text":"Putting together pieces yields function something like : finish real package, ’d want : Add explicit arguments check correct type. Export document function. Convert nested list user-friendly data structure (probably data frame one row per review). ’d also want provide convenient way user supply API key.","code":"nytimes_books <- function(api_key, path, ...) { request(\"https://api.nytimes.com/svc/books/v3\") |> req_url_path_append(path) |> req_url_query(..., `api-key` = api_key) |> req_error(body = nytimes_error_body) |> req_throttle(10 / 60, realm = \"https://api.nytimes.com/svc/books\") |> req_perform() |> resp_body_json() } drunk <- nytimes_books(my_key, \"/reviews.json\", isbn = \"0316453382\") drunk$results[[1]]$summary"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"user-supplied-key","dir":"Articles","previous_headings":"NYTimes Books API","what":"User-supplied key","title":"Wrapping APIs","text":"good place start environment variable, environment variables easy set without typing anything console (can get accidentally shared via .Rhistory) easily set automated processes. ’d write function retrieve API key, returning helpful message ’s found: modify nytimes_books() use get_api_key() default value api_key. Since argument now optional, can move end argument list, since ’ll needed exceptional circumstances. can make approach little user friendly providing helper sets environment variable: Using askpass (similar) good practice since don’t want encourage user type secret key console, mentioned . ’s good idea extend get_api_key() automatically use encrypted key make easier write tests:","code":"get_api_key <- function() { key <- Sys.getenv(\"NYTIMES_KEY\") if (identical(key, \"\")) { stop(\"No API key found, please supply with `api_key` argument or with NYTIMES_KEY env var\") } key } nytimes_books <- function(path, ..., api_key = get_api_key()) { ... } set_api_key <- function(key = NULL) { if (is.null(key)) { key <- askpass::askpass(\"Please enter your API key\") } Sys.setenv(\"NYTIMES_KEY\" = key) } get_api_key <- function() { key <- Sys.getenv(\"NYTIMES_KEY\") if (!identical(key, \"\")) { return(key) } if (is_testing()) { return(testing_key()) } else { stop(\"No API key found, please supply with `api_key` argument or with NYTIMES_KEY env var\") } } is_testing <- function() { identical(Sys.getenv(\"TESTTHAT\"), \"true\") } testing_key <- function() { secret_decrypt(\"4Nx84VPa83dMt3X6bv0fNBlLbv3U4D1kHM76YisKEfpCarBm1UHJHARwJHCFXQSV\", \"HTTR2_KEY\") }"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"github-gists-api","dir":"Articles","previous_headings":"","what":"Github Gists API","title":"Wrapping APIs","text":"Next ’ll take look API can make changes behalf user, just retrieve data: GitHub’s gist API. uses different HTTP methods perform different actions, like creating, updating, deleting gists. can get , let’s handle authentication, rate-limiting, errors.","code":""},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"authentication","dir":"Articles","previous_headings":"Github Gists API","what":"Authentication","title":"Wrapping APIs","text":"easiest way authenticate GitHub API use personal access token. token alternative username password. one username + password per site; can one token per use case. lets use case minimal set permissions, can easily revoke one token without affecting use case. created personal access token specifically vignette can access gists, , last example, stored encrypted version vignette: want run vignette , ’ll need create new token GitHub settings; just make sure includes “gist” scope. ’s also good idea give every token descriptive name, reminds motivating use case, update re-generate expired. authenticate request token, need put Authorization header “token” prefix: authorization header usually contains secret information, httr2 automatically redacts it1:","code":"token <- secret_decrypt(\"Guz59woxKoIO_JVtp2IzU3mFIU3ULtaUEa8xvvpYUBdVthR8jhxzc3bMZFhA9HL-ZK6YZudOI6g\", \"HTTR2_KEY\") req <- request(\"https://api.github.com/gists\") |> req_headers(Authorization = paste(\"token\", token)) req |> req_perform() req req |> req_dry_run()"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"errors-1","dir":"Articles","previous_headings":"Github Gists API","what":"Errors","title":"Wrapping APIs","text":"’ve got authentication working, ’s always good idea work errors next, since help debug failed requests. experience APIs rarely good job documenting errors, ’ll often little experimentation. add pain, large APIs different endpoints often return different amounts information different forms. ’ll typically need tackle error handling iteratively, improving code time encounter new problem. GitHub document errors, ’m sufficiently distrustful still want construct deliberately malformed query see happens: documented get 422 “Unprocessable Entity” error. response rather different documentation suggests string message list errors: ’ll proceed anyway, writing function extracts data formats presentation user: Now can pass function body argument req_error() automatically included error request fails: Notice element character vector produced gh_error_body() becomes bullet resulting error.","code":"resp <- request(\"https://api.github.com/gists\") |> req_url_query(since = \"abcdef\") |> req_headers(Authorization = paste(\"token\", token)) |> req_perform() resp <- last_response() resp resp |> resp_body_json() gist_error_body <- function(resp) { body <- resp_body_json(resp) message <- body$message if (!is.null(body$documentation_url)) { message <- c(message, paste0(\"See docs at <\", body$documentation_url, \">\")) } message } gist_error_body(resp) request(\"https://api.github.com/gists\") |> req_url_query(since = \"yesterday\") |> req_headers(Authorization = paste(\"token\", token)) |> req_error(body = gist_error_body) |> req_perform()"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"rate-limiting","dir":"Articles","previous_headings":"Github Gists API","what":"Rate-limiting","title":"Wrapping APIs","text":"’re thinking errors, ’s useful look happens requests rate limited. Luckily, GitHub consistently uses response headers provide information remaining rate limits. can teach httr2 can automatically wait reset rate limit hit. need define two functions. first tells us whether response transient error, .e. ’s worth waiting trying . GitHub, rate limit exceeded, response 403 status X-RateLimit-Remaining: 0 header: need function tells long wait. GitHub tells us rate limit resets (number seconds since 1970-01-01) X-RateLimit-Reset header. convert number seconds wait first convert number (since HTTP headers always strings), subtract current time (number seconds since 1970-01-01): pass functions req_retry() httr2 information needs handle rate-limiting automatically: also need supply either max_tries max_seconds order activate req_retry().","code":"resp <- req |> req_perform() resp |> resp_headers(\"ratelimit\") gist_is_transient <- function(resp) { resp_status(resp) == 403 && resp_header(resp, \"X-RateLimit-Remaining\") == \"0\" } gist_is_transient(resp) gist_after <- function(resp) { time <- as.numeric(resp_header(resp, \"X-RateLimit-Reset\")) time - unclass(Sys.time()) } gist_after(resp) request(\"http://api.github.com\") |> req_retry( is_transient = gist_is_transient, after = gist_after, max_seconds = 60 )"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"wrapping-it-all-up","dir":"Articles","previous_headings":"Github Gists API","what":"Wrapping it all up","title":"Wrapping APIs","text":"Let’s wrap everything ’ve learned far single function creates request: ’ll use basis solve next challenge: uploading gist.","code":"req_gist <- function(token) { request(\"https://api.github.com/gists\") |> req_headers(Authorization = paste(\"token\", token)) |> req_error(body = gist_error_body) |> req_retry( is_transient = gist_is_transient, after = gist_after ) } # Check it works: req_gist(token) |> req_perform()"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"sending-data","dir":"Articles","previous_headings":"Github Gists API","what":"Sending data","title":"Wrapping APIs","text":"create gist need change method POST add body contains data encoded JSON. httr2 provides one function things: req_body_json(): Depending API ’re wrapping, might need send data different way. req_body_form() req_body_multipart() make easier encode data two common forms. API requires something different can use req_body_raw(). Typically, API return useful data resource ’ve just created. ’ll extract gist ID can use next examples, culminating deleting gist don’t end bunch duplicated gists 😃.","code":"req <- req_gist(token) |> req_body_json(list( description = \"This is my cool gist!\", files = list(test.R = list(content = \"print('Hi!')\")), public = FALSE )) req |> req_dry_run() resp <- req |> req_perform() id <- resp |> resp_body_json() |> _$id id"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"changing-a-gist","dir":"Articles","previous_headings":"Github Gists API","what":"Changing a gist","title":"Wrapping APIs","text":"Actually, description wasn’t true want change . , need send JSON encoded data, time need use PATCH verb. adding data request, use req_method() override default method:","code":"req <- req_gist(token) |> req_url_path_append(id) |> req_body_json(list(description = \"This is a simple gist\")) |> req_method(\"PATCH\") req |> req_dry_run()"},{"path":"https://httr2.r-lib.org/dev/articles/wrapping-apis.html","id":"deleting-a-gist","dir":"Articles","previous_headings":"Github Gists API","what":"Deleting a gist","title":"Wrapping APIs","text":"Deleting gist similar, except don’t send data, just need adjust default method GET DELETE.","code":"req <- req_gist(token) |> req_url_path_append(id) |> req_method(\"DELETE\") req |> req_dry_run() req |> req_perform()"},{"path":"https://httr2.r-lib.org/dev/authors.html","id":null,"dir":"","previous_headings":"","what":"Authors","title":"Authors and Citation","text":"Hadley Wickham. Author, maintainer. . Copyright holder, funder. Maximilian Girlich. Contributor.","code":""},{"path":"https://httr2.r-lib.org/dev/authors.html","id":"citation","dir":"","previous_headings":"","what":"Citation","title":"Authors and Citation","text":"Wickham H (2024). httr2: Perform HTTP Requests Process Responses. R package version 1.0.5.9000, https://github.com/r-lib/httr2, https://httr2.r-lib.org.","code":"@Manual{, title = {httr2: Perform HTTP Requests and Process the Responses}, author = {Hadley Wickham}, year = {2024}, note = {R package version 1.0.5.9000, https://github.com/r-lib/httr2}, url = {https://httr2.r-lib.org}, }"},{"path":"https://httr2.r-lib.org/dev/index.html","id":"httr2-","dir":"","previous_headings":"","what":"Perform HTTP Requests and Process the Responses","title":"Perform HTTP Requests and Process the Responses","text":"httr2 (pronounced hitter2) ground-rewrite httr provides pipeable API explicit request object solves problems felt packages wrap APIs (e.g. built-rate-limiting, retries, OAuth, secure secrets, ).","code":""},{"path":"https://httr2.r-lib.org/dev/index.html","id":"installation","dir":"","previous_headings":"","what":"Installation","title":"Perform HTTP Requests and Process the Responses","text":"can install httr2 CRAN :","code":"install.packages(\"httr2\")"},{"path":"https://httr2.r-lib.org/dev/index.html","id":"usage","dir":"","previous_headings":"","what":"Usage","title":"Perform HTTP Requests and Process the Responses","text":"use httr2, start creating request: can tailor request req_ family functions: see exactly httr2 send server req_dry_run(): Use req_perform() perform request, retrieving response: resp_ functions help extract various useful components response:","code":"library(httr2) req <- request(\"https://r-project.org\") req #> <httr2_request> #> GET https://r-project.org #> Body: empty # Add custom headers req |> req_headers(\"Accept\" = \"application/json\") #> <httr2_request> #> GET https://r-project.org #> Headers: #> • Accept: 'application/json' #> Body: empty # Add a body, turning it into a POST req |> req_body_json(list(x = 1, y = 2)) #> <httr2_request> #> POST https://r-project.org #> Body: json encoded data # Modify the path in the url req |> req_url_path(path = \"path/to/my/file\") #> <httr2_request> #> GET https://r-project.org/path/to/my/file #> Body: empty # Automatically retry if the request fails req |> req_retry(max_tries = 5) #> <httr2_request> #> GET https://r-project.org #> Body: empty #> Policies: #> • retry_max_tries: 5 #> • retry_on_failure: FALSE # Change the HTTP method req |> req_method(\"PATCH\") #> <httr2_request> #> PATCH https://r-project.org #> Body: empty req |> req_dry_run() #> GET / HTTP/1.1 #> Host: r-project.org #> User-Agent: httr2/1.0.3.9000 r-curl/5.2.2 libcurl/8.6.0 #> Accept: */* #> Accept-Encoding: deflate, gzip resp <- req_perform(req) resp #> <httr2_response> #> GET https://www.r-project.org/ #> Status: 200 OK #> Content-Type: text/html #> Body: In memory (6951 bytes) resp |> resp_content_type() #> [1] \"text/html\" resp |> resp_status_desc() #> [1] \"OK\" resp |> resp_body_html() #> {html_document} #> <html lang=\"en\"> #> [1] <head>\\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8 ... #> [2] <body>\\n <div class=\"container page\">\\n <div class=\"row\">\\n ..."},{"path":"https://httr2.r-lib.org/dev/index.html","id":"major-differences-to-httr","dir":"","previous_headings":"","what":"Major differences to httr","title":"Perform HTTP Requests and Process the Responses","text":"can now create modify request without performing . means ’s now single function perform request fetch result: req_perform(). req_perform() replaces httr::GET(), httr::POST(), httr::DELETE(), . HTTP errors automatically converted R errors. Use req_error() override defaults (turn 4xx 5xx responses errors) add additional details error message. can automatically retry request fails encounters transient HTTP error (e.g. 429 rate limit request). req_retry() defines maximum number retries, errors transient, long wait tries. OAuth support totally overhauled directly support many flows make much easier customise built-flows create . can manage secrets (often needed testing) secret_encrypt() friends. can obfuscate mildly confidential data obfuscate(), preventing scraped published code. can automatically cache cacheable results req_cache(). Relatively API responses cacheable, typically makes big difference.","code":""},{"path":"https://httr2.r-lib.org/dev/index.html","id":"acknowledgements","dir":"","previous_headings":"","what":"Acknowledgements","title":"Perform HTTP Requests and Process the Responses","text":"httr2 wouldn’t possible without curl, openssl, jsonlite, jose, maintained Jeroen Ooms. big thanks also go Jenny Bryan Craig Citro given much useful feedback design internals user facing API.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/curl_translate.html","id":null,"dir":"Reference","previous_headings":"","what":"Translate curl syntax to httr2 — curl_translate","title":"Translate curl syntax to httr2 — curl_translate","text":"curl command line tool commonly used demonstrate HTTP APIs can easily generated browser developer tools. curl_translate() saves pain manually translating calls implementing partial, frequently used, subset curl options. Use curl_help() see supported options, curl_translate() translate curl invocation copy pasted elsewhere. Inspired curlconverter written Bob Rudis.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/curl_translate.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Translate curl syntax to httr2 — curl_translate","text":"","code":"curl_translate(cmd, simplify_headers = TRUE) curl_help()"},{"path":"https://httr2.r-lib.org/dev/reference/curl_translate.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Translate curl syntax to httr2 — curl_translate","text":"cmd Call curl. omitted clipr package installed, retrieved clipboard. simplify_headers Remove typically unimportant headers included copying curl command browser. includes: sec-fetch-* sec-ch-ua* referer, pragma, connection","code":""},{"path":"https://httr2.r-lib.org/dev/reference/curl_translate.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Translate curl syntax to httr2 — curl_translate","text":"string containing translated httr2 code. input copied clipboard, translation copied back clipboard.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/curl_translate.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Translate curl syntax to httr2 — curl_translate","text":"","code":"curl_translate(\"curl http://example.com\") #> request(\"http://example.com\") |> #> req_perform() curl_translate(\"curl http://example.com -X DELETE\") #> request(\"http://example.com\") |> #> req_method(\"DELETE\") |> #> req_perform() curl_translate(\"curl http://example.com --header A:1 --header B:2\") #> request(\"http://example.com\") |> #> req_headers( #> A = \"1\", #> B = \"2\", #> ) |> #> req_perform() curl_translate(\"curl http://example.com --verbose\") #> request(\"http://example.com\") |> #> req_perform(verbosity = 1)"},{"path":"https://httr2.r-lib.org/dev/reference/example_url.html","id":null,"dir":"Reference","previous_headings":"","what":"Code for examples — example_url","title":"Code for examples — example_url","text":"example_url() runs simple websever using webfakes package following endpoints: ones webfakes::httpbin_app() /iris: paginate iris dataset. query parameters page limit control pagination. example_github_client() OAuth client GitHub.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/example_url.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Code for examples — example_url","text":"","code":"example_url() example_github_client()"},{"path":"https://httr2.r-lib.org/dev/reference/httr2-package.html","id":null,"dir":"Reference","previous_headings":"","what":"httr2: Perform HTTP Requests and Process the Responses — httr2-package","title":"httr2: Perform HTTP Requests and Process the Responses — httr2-package","text":"Tools creating modifying HTTP requests, performing processing results. 'httr2' modern re-imagining 'httr' uses pipe-based interface solves problems API wrapping packages face.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/httr2-package.html","id":"author","dir":"Reference","previous_headings":"","what":"Author","title":"httr2: Perform HTTP Requests and Process the Responses — httr2-package","text":"Maintainer: Hadley Wickham hadley@posit.co contributors: Posit Software, PBC [copyright holder, funder] Maximilian Girlich [contributor]","code":""},{"path":"https://httr2.r-lib.org/dev/reference/iterate_with_offset.html","id":null,"dir":"Reference","previous_headings":"","what":"Iteration helpers — iterate_with_offset","title":"Iteration helpers — iterate_with_offset","text":"functions intended use next_req argument req_perform_iterative(). implements iteration common pagination pattern: iterate_with_offset() increments query parameter, e.g. ?page=1, ?page=2, ?offset=1, offset=21. iterate_with_cursor() updates query parameter value cursor found somewhere response. iterate_with_link_url() follows url found Link header. See resp_link_url() details.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/iterate_with_offset.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Iteration helpers — iterate_with_offset","text":"","code":"iterate_with_offset( param_name, start = 1, offset = 1, resp_pages = NULL, resp_complete = NULL ) iterate_with_cursor(param_name, resp_param_value) iterate_with_link_url(rel = \"next\")"},{"path":"https://httr2.r-lib.org/dev/reference/iterate_with_offset.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Iteration helpers — iterate_with_offset","text":"param_name Name query parameter. start Starting value. offset Offset page. default set 1 get (e.g.) ?page=1, ?page=2, ... param_name refers element index (rather page index) want set larger number get (e.g.) ?items=20, ?items=40, ... resp_pages callback function takes response (resp) returns total number pages, NULL unknown. called . resp_complete callback function takes response (resp) returns TRUE pages. resp_param_value callback function takes response (resp) returns next cursor value. Return NULL pages. rel \"link relation type\" use retrieve next page.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/iterate_with_offset.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Iteration helpers — iterate_with_offset","text":"","code":"req <- request(example_url()) |> req_url_path(\"/iris\") |> req_throttle(10) |> req_url_query(limit = 50) # If you don't know the total number of pages in advance, you can # provide a `resp_complete()` callback is_complete <- function(resp) { length(resp_body_json(resp)$data) == 0 } resps <- req_perform_iterative( req, next_req = iterate_with_offset(\"page_index\", resp_complete = is_complete), max_reqs = Inf ) if (FALSE) { # \\dontrun{ # Alternatively, if the response returns the total number of pages (or you # can easily calculate it), you can use the `resp_pages()` callback which # will generate a better progress bar. resps <- req_perform_iterative( req |> req_url_query(limit = 1), next_req = iterate_with_offset( \"page_index\", resp_pages = function(resp) resp_body_json(resp)$pages ), max_reqs = Inf ) } # }"},{"path":"https://httr2.r-lib.org/dev/reference/jwt_claim.html","id":null,"dir":"Reference","previous_headings":"","what":"Create and encode a JWT — jwt_claim","title":"Create and encode a JWT — jwt_claim","text":"jwt_claim() wrapper around jose::jwt_claim() creates JWT claim set extra default values. jwt_encode_sig() jwt_encode_hmac() thin wrappers around jose::jwt_encode_sig() jose::jwt_encode_hmac() exist primarily make specification functions little simpler.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/jwt_claim.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Create and encode a JWT — jwt_claim","text":"","code":"jwt_claim( iss = NULL, sub = NULL, aud = NULL, exp = unix_time() + 5L * 60L, nbf = unix_time(), iat = unix_time(), jti = NULL, ... ) jwt_encode_sig(claim, key, size = 256, header = list()) jwt_encode_hmac(claim, secret, size = 256, header = list())"},{"path":"https://httr2.r-lib.org/dev/reference/jwt_claim.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Create and encode a JWT — jwt_claim","text":"iss Issuer claim. Identifies principal issued JWT. sub Subject claim. Identifies principal subject JWT (.e. entity claims apply ). aud Audience claim. Identifies recipients JWT intended. principle intended process JWT must identified unique value. exp Expiration claim. Identifies expiration time JWT MUST accepted processing. Defaults 5 minutes. nbf claim. Identifies time JWT MUST accepted processing. Defaults current time. iat Issued claim. Identifies time JWT issued. Defaults current time. jti JWT ID claim. Provides unique identifier JWT. omitted, uses random 32-byte sequence encoded base64url. ... additional claims include claim set. claim Claim set produced jwt_claim(). key RSA EC private key either specified path file, connection, string (PEM/SSH format), raw vector (DER format). size Size, bits, sha2 signature, .e. 256, 384 512. HMAC/RSA, applicable ECDSA keys. header named list giving additional fields include JWT header. secret String raw vector secret passphrase.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/jwt_claim.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Create and encode a JWT — jwt_claim","text":"S3 list class jwt_claim.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/jwt_claim.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Create and encode a JWT — jwt_claim","text":"","code":"claim <- jwt_claim() str(claim) #> List of 4 #> $ exp: num 1.73e+09 #> $ nbf: num 1.73e+09 #> $ iat: num 1.73e+09 #> $ jti: chr \"v0IVNc-RVHlZuw1NTbPJZ9tuFaltYUYUQshm4fvmjo8\" #> - attr(*, \"class\")= chr [1:2] \"jwt_claim\" \"list\""},{"path":"https://httr2.r-lib.org/dev/reference/last_response.html","id":null,"dir":"Reference","previous_headings":"","what":"Retrieve most recent request/response — last_response","title":"Retrieve most recent request/response — last_response","text":"functions retrieve recent request made httr2 response received, facilitate debugging problems occur. request succeed (requests made) last_response() NULL.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/last_response.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Retrieve most recent request/response — last_response","text":"","code":"last_response() last_request()"},{"path":"https://httr2.r-lib.org/dev/reference/last_response.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Retrieve most recent request/response — last_response","text":"HTTP response/request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/last_response.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Retrieve most recent request/response — last_response","text":"","code":"invisible(request(\"http://httr2.r-lib.org\") |> req_perform()) last_request() #> <httr2_request> #> GET http://httr2.r-lib.org #> Body: empty last_response() #> <httr2_response> #> GET https://httr2.r-lib.org/ #> Status: 200 OK #> Content-Type: text/html #> Body: In memory (18819 bytes)"},{"path":"https://httr2.r-lib.org/dev/reference/multi_req_perform.html","id":null,"dir":"Reference","previous_headings":"","what":"Perform a list of requests in parallel — multi_req_perform","title":"Perform a list of requests in parallel — multi_req_perform","text":"Please use req_perform_parallel() instead, note: cancel_on_error = FALSE now on_error = \"continue\" cancel_on_error = TRUE now on_error = \"return\"","code":""},{"path":"https://httr2.r-lib.org/dev/reference/multi_req_perform.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Perform a list of requests in parallel — multi_req_perform","text":"","code":"multi_req_perform(reqs, paths = NULL, pool = NULL, cancel_on_error = FALSE)"},{"path":"https://httr2.r-lib.org/dev/reference/multi_req_perform.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Perform a list of requests in parallel — multi_req_perform","text":"reqs list requests. paths optional character vector paths, want download request bodies disk. supplied, must length reqs. pool Optionally, curl pool made curl::new_pool(). Supply want override defaults total concurrent connections (100) concurrent connections per host (6). cancel_on_error pending requests cancelled hit error? Set TRUE stop requests soon hit error. Responses never performed NULL result.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_cache_path.html","id":null,"dir":"Reference","previous_headings":"","what":"httr2 OAuth cache location — oauth_cache_path","title":"httr2 OAuth cache location — oauth_cache_path","text":"opted-, httr2 caches OAuth tokens directory. default, uses OS-standard cache directory, , needed, can override location setting HTTR2_OAUTH_CACHE env var.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_cache_path.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"httr2 OAuth cache location — oauth_cache_path","text":"","code":"oauth_cache_path()"},{"path":"https://httr2.r-lib.org/dev/reference/oauth_client.html","id":null,"dir":"Reference","previous_headings":"","what":"Create an OAuth client — oauth_client","title":"Create an OAuth client — oauth_client","text":"OAuth app combination client, set endpoints (.e. urls various requests sent), authentication mechanism. client consists least client_id, also often client_secret. get values create client API's website.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_client.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Create an OAuth client — oauth_client","text":"","code":"oauth_client( id, token_url, secret = NULL, key = NULL, auth = c(\"body\", \"header\", \"jwt_sig\"), auth_params = list(), name = hash(id) )"},{"path":"https://httr2.r-lib.org/dev/reference/oauth_client.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Create an OAuth client — oauth_client","text":"id Client identifier. token_url Url retrieve access token. secret Client secret. apps, technically confidential principle avoid storing source code. However, many APIs require order provide user friendly authentication experience, risks including usually low. make things little safer, recommend using obfuscate() recording client secret public code. key Client key. alternative using secret, can instead supply confidential private key. never included package. auth Authentication mechanism used client prove API. Can one three built-methods (\"body\", \"header\", \"jwt\"), function called arguments req, client, contents auth_params. common mechanism wild \"body\" client_id (optionally) client_secret added body. \"header\" sends client_id client_secret HTTP Authorization header. \"jwt_sig\" generate JWT, include client_assertion field body. See oauth_client_req_auth() details. auth_params Additional parameters passed function specified auth. name Optional name client. Used generating cache directory. NULL, generated hash client_id. defining client use package, recommend use package name.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_client.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Create an OAuth client — oauth_client","text":"OAuth client: S3 list class httr2_oauth_client.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_client.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Create an OAuth client — oauth_client","text":"","code":"oauth_client(\"myclient\", \"http://example.com/token_url\", secret = \"DONTLOOK\") #> <httr2_oauth_client> #> name: 920903ca1274bc747bb367c6b5abe4a4 #> id: myclient #> secret: <REDACTED> #> token_url: http://example.com/token_url #> auth: oauth_client_req_auth_body"},{"path":"https://httr2.r-lib.org/dev/reference/oauth_client_req_auth.html","id":null,"dir":"Reference","previous_headings":"","what":"OAuth client authentication — oauth_client_req_auth","title":"OAuth client authentication — oauth_client_req_auth","text":"oauth_client_req_auth() authenticates request using authentication strategy defined auth auth_param arguments oauth_client(). used authenticate client part OAuth flow, authenticate request behalf user. three built-strategies: oauth_client_req_body() adds client id (optionally) secret request body, described Section 2.3.1 RFC 6749. oauth_client_req_header() adds client id secret using HTTP basic authentication Authorization header, described Section 2.3.1 RFC 6749. oauth_client_jwt_rs256() adds client assertion body using JWT signed jwt_sign_rs256() using private key, described Section 2.2 RFC 7523. generally call functions directly instead specify auth argument oauth_client(). req client parameters automatically filled ; parameters come auth_params argument.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_client_req_auth.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"OAuth client authentication — oauth_client_req_auth","text":"","code":"oauth_client_req_auth(req, client) oauth_client_req_auth_header(req, client) oauth_client_req_auth_body(req, client) oauth_client_req_auth_jwt_sig(req, client, claim, size = 256, header = list())"},{"path":"https://httr2.r-lib.org/dev/reference/oauth_client_req_auth.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"OAuth client authentication — oauth_client_req_auth","text":"req httr2 request object. client oauth_client. claim Claim set produced jwt_claim(). size Size, bits, sha2 signature, .e. 256, 384 512. HMAC/RSA, applicable ECDSA keys. header named list giving additional fields include JWT header.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_client_req_auth.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"OAuth client authentication — oauth_client_req_auth","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_client_req_auth.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"OAuth client authentication — oauth_client_req_auth","text":"","code":"# Show what the various forms of client authentication look like req <- request(\"https://example.com/whoami\") client1 <- oauth_client( id = \"12345\", secret = \"56789\", token_url = \"https://example.com/oauth/access_token\", name = \"oauth-example\", auth = \"body\" # the default ) # calls oauth_client_req_auth_body() req_dry_run(oauth_client_req_auth(req, client1)) #> POST /whoami HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Content-Type: application/x-www-form-urlencoded #> Content-Length: 35 #> #> client_id=12345&client_secret=56789 client2 <- oauth_client( id = \"12345\", secret = \"56789\", token_url = \"https://example.com/oauth/access_token\", name = \"oauth-example\", auth = \"header\" ) # calls oauth_client_req_auth_header() req_dry_run(oauth_client_req_auth(req, client2)) #> GET /whoami HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Authorization: <REDACTED> #> client3 <- oauth_client( id = \"12345\", key = openssl::rsa_keygen(), token_url = \"https://example.com/oauth/access_token\", name = \"oauth-example\", auth = \"jwt_sig\", auth_params = list(claim = jwt_claim()) ) # calls oauth_client_req_auth_header_jwt_sig() req_dry_run(oauth_client_req_auth(req, client3)) #> POST /whoami HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Content-Type: application/x-www-form-urlencoded #> Content-Length: 623 #> #> client_assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJleHAiOjE3Mjk3MjE3MzcsIm5iZiI6MTcyOTcyMTQzNywiaWF0IjoxNzI5NzIxNDM3LCJqdGkiOiIzY1FzdmdQM1VqNXFwQzRRMEl5VkVHNzZmREZyOV80azFUQ3NiQ0x4aDJZIn0.HIaVxphmGoHbBe1mWDW_sLfppj8V7B7ZIQNdqOJ-qjHPUdOEo3OLQEiLa56AHcCPJaARxofMnFBeeeuEwDAglSVDSCct5w7QGzWtw-j5cGvFVrrRUz68GfUN_0DZGJilpcMS0DCOZxKjm014z_jWSpQM3B4jfq0KHWJ2Tq3HC2RpclmFGvlzaGmOBlrA18dmxcU7-BqpaJ0S3vZ0hTPRlcj4HrFAJv3ZgHUmoyYhNQezrFJLLtR4kzZr0wVQToiXKTMfskm_qU3xvsJJhRKHhvJU0gVT6n-_plbxtRi6yjTbuSFAK9ytjex4JSkDGGvYI5gqpytEEX47QChCnKeieg&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer"},{"path":"https://httr2.r-lib.org/dev/reference/oauth_flow_auth_code_url.html","id":null,"dir":"Reference","previous_headings":"","what":"OAuth authorization code components — oauth_flow_auth_code_url","title":"OAuth authorization code components — oauth_flow_auth_code_url","text":"low-level functions can used assemble custom flow APIs spec: oauth_flow_auth_code_url() generates url opened browser. oauth_flow_auth_code_listen() starts temporary local webserver listens response resource server. oauth_flow_auth_code_parse() parses query parameters returned server redirect, verifying state correct, returning authorisation code. oauth_flow_auth_code_pkce() generates code verifier, method, challenge components needed PKCE, defined RFC 7636.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_flow_auth_code_url.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"OAuth authorization code components — oauth_flow_auth_code_url","text":"","code":"oauth_flow_auth_code_url( client, auth_url, redirect_uri = NULL, scope = NULL, state = NULL, auth_params = list() ) oauth_flow_auth_code_listen(redirect_uri = \"http://localhost:1410\") oauth_flow_auth_code_parse(query, state) oauth_flow_auth_code_pkce()"},{"path":"https://httr2.r-lib.org/dev/reference/oauth_flow_auth_code_url.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"OAuth authorization code components — oauth_flow_auth_code_url","text":"state Random state generated oauth_flow_auth_code(). Used verify working authentication request created. (unlikely threat R packages since webserver listens authorization responses transient.) query List query parameters returned oauth_flow_auth_code_listen().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_redirect_uri.html","id":null,"dir":"Reference","previous_headings":"","what":"Default redirect url for OAuth — oauth_redirect_uri","title":"Default redirect url for OAuth — oauth_redirect_uri","text":"default redirect uri used req_oauth_auth_code(). Defaults http://localhost unless HTTR2_OAUTH_REDIRECT_URL envvar set.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_redirect_uri.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Default redirect url for OAuth — oauth_redirect_uri","text":"","code":"oauth_redirect_uri()"},{"path":"https://httr2.r-lib.org/dev/reference/oauth_token.html","id":null,"dir":"Reference","previous_headings":"","what":"Create an OAuth token — oauth_token","title":"Create an OAuth token — oauth_token","text":"Creates S3 object class <httr2_token> representing OAuth token returned access token endpoint.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_token.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Create an OAuth token — oauth_token","text":"","code":"oauth_token( access_token, token_type = \"bearer\", expires_in = NULL, refresh_token = NULL, ..., .date = Sys.time() )"},{"path":"https://httr2.r-lib.org/dev/reference/oauth_token.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Create an OAuth token — oauth_token","text":"access_token access token used authenticate request token_type Type token; \"bearer\" currently supported. expires_in Number seconds token expires. refresh_token Optional refresh token; supplied, can used cheaply get new access token one expires. ... Additional components returned endpoint .date Date request made; used convert relative expires_in absolute expires_at.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_token.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Create an OAuth token — oauth_token","text":"OAuth token: S3 list class httr2_token.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/oauth_token.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Create an OAuth token — oauth_token","text":"","code":"oauth_token(\"abcdef\") #> <httr2_token> #> token_type: bearer #> access_token: <REDACTED> oauth_token(\"abcdef\", expires_in = 3600) #> <httr2_token> #> token_type: bearer #> access_token: <REDACTED> #> expires_at: 2024-10-23 23:10:38 oauth_token(\"abcdef\", refresh_token = \"ghijkl\") #> <httr2_token> #> token_type: bearer #> access_token: <REDACTED> #> refresh_token: <REDACTED>"},{"path":"https://httr2.r-lib.org/dev/reference/oauth_token_cached.html","id":null,"dir":"Reference","previous_headings":"","what":"Retrieve an OAuth token using the cache — oauth_token_cached","title":"Retrieve an OAuth token using the cache — oauth_token_cached","text":"function wraps around oauth_flow_ function retrieve token cache, generate cache token needed. Use manual token management still takes advantage httr2's caching system. need use function passing token","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_token_cached.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Retrieve an OAuth token using the cache — oauth_token_cached","text":"","code":"oauth_token_cached( client, flow, flow_params = list(), cache_disk = FALSE, cache_key = NULL, reauth = FALSE )"},{"path":"https://httr2.r-lib.org/dev/reference/oauth_token_cached.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Retrieve an OAuth token using the cache — oauth_token_cached","text":"client oauth_client(). flow oauth_flow_ function used generate access token. flow_params Parameters flow. named list whose names match argument names flow. cache_disk access token cached disk? reduces number times need re-authenticate cost storing access credentials disk. Learn https://httr2.r-lib.org/articles/oauth.html. cache_key want cache multiple tokens per app, use key disambiguate . reauth Set TRUE force re-authentication via flow, regardless whether token expired.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/oauth_token_cached.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Retrieve an OAuth token using the cache — oauth_token_cached","text":"","code":"if (FALSE) { # \\dontrun{ token <- oauth_token_cached( client = example_github_client(), flow = oauth_flow_auth_code, flow_params = list( auth_url = \"https://github.com/login/oauth/authorize\" ), cache_disk = TRUE ) token } # }"},{"path":"https://httr2.r-lib.org/dev/reference/obfuscate.html","id":null,"dir":"Reference","previous_headings":"","what":"Obfuscate mildly secret information — obfuscate","title":"Obfuscate mildly secret information — obfuscate","text":"Use obfuscate(\"value\") generate call obfuscated(), unobfuscate value last possible moment. Obfuscated values work limited locations: secret argument oauth_client() Elements data argument req_body_form(), req_body_json(), req_body_multipart(). Working together pair functions provides way obfuscate mildly confidential information, like OAuth client secrets. secret can revealed inspecting source code, skilled R programmer figure effort. main goal protect scraping; way automated tool grab obfuscated secrets.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/obfuscate.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Obfuscate mildly secret information — obfuscate","text":"","code":"obfuscate(x) obfuscated(x)"},{"path":"https://httr2.r-lib.org/dev/reference/obfuscate.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Obfuscate mildly secret information — obfuscate","text":"x string obfuscate, mark obfuscated.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/obfuscate.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Obfuscate mildly secret information — obfuscate","text":"obfuscate() prints obfuscated() call include code. obfuscated() returns S3 class marking string obfuscated can unobfuscated needed.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/obfuscate.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Obfuscate mildly secret information — obfuscate","text":"","code":"obfuscate(\"good morning\") #> obfuscated(\"XXa_ZWUfuJ-2s8lzn1-9Yyg-ygTLEPrLxqB5Fw\") # Every time you obfuscate you'll get a different value because it # includes 16 bytes of random data which protects against certain types of # brute force attack obfuscate(\"good morning\") #> obfuscated(\"VWky166VQAi5nEWAmEDpQLzHI9R2LXuSARDVDw\")"},{"path":"https://httr2.r-lib.org/dev/reference/pipe.html","id":null,"dir":"Reference","previous_headings":"","what":"Pipe operator — %>%","title":"Pipe operator — %>%","text":"See magrittr::%>% details.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/pipe.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Pipe operator — %>%","text":"","code":"lhs %>% rhs"},{"path":"https://httr2.r-lib.org/dev/reference/pipe.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Pipe operator — %>%","text":"lhs value magrittr placeholder. rhs function call using magrittr semantics.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/pipe.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Pipe operator — %>%","text":"result calling rhs(lhs).","code":""},{"path":"https://httr2.r-lib.org/dev/reference/progress_bars.html","id":null,"dir":"Reference","previous_headings":"","what":"Progress bars in httr2 — progress_bars","title":"Progress bars in httr2 — progress_bars","text":"httr2's perform functions progress argument can use create progress bar. progress can : FALSE, default: create progress bar. TRUE: creates basic unnamed progress bar. string: creates basic progress bar given name. named list progress bar parameters, described . good practice name progress bars, make clear calculation process belong . recommend keeping names 20 characters, whole progress bar fits comfortably even narrower displays.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/progress_bars.html","id":"progress-bar-parameters","dir":"Reference","previous_headings":"","what":"Progress bar parameters","title":"Progress bars in httr2 — progress_bars","text":"clear: whether remove progress bar screen termination. Defaults TRUE. format: format string. overrides default format string progress bar type. must given custom type. Format strings may contain R expressions evaluate braces. support cli pluralization, styling can contain special progress variables. format_done: format string successful termination. default format. format_failed: format string unsuccessful termination. default format. name: progress bar name. default empty string displayed beginning progress bar. show_after: numeric scalar. show progress bar number seconds. overrides cli.progress_show_after global option. type: progress bar type. Currently supported types : iterator: default, loop mapping function, tasks: (typically small) number tasks, download: download one file, custom: custom type, format must NULL type. default display different progress bar type.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/progress_bars.html","id":"further-documentation","dir":"Reference","previous_headings":"","what":"Further documentation","title":"Progress bars in httr2 — progress_bars","text":"purrr's progress bars powered cli, see Introduction progress bars cli Advanced cli progress bars details.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_aws_v4.html","id":null,"dir":"Reference","previous_headings":"","what":"Sign a request with the AWS SigV4 signing protocol — req_auth_aws_v4","title":"Sign a request with the AWS SigV4 signing protocol — req_auth_aws_v4","text":"custom auth protocol implemented AWS.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_aws_v4.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Sign a request with the AWS SigV4 signing protocol — req_auth_aws_v4","text":"","code":"req_auth_aws_v4( req, aws_access_key_id, aws_secret_access_key, aws_session_token = NULL, aws_service = NULL, aws_region = NULL )"},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_aws_v4.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Sign a request with the AWS SigV4 signing protocol — req_auth_aws_v4","text":"req httr2 request object. aws_access_key_id, aws_secret_access_key AWS key secret. aws_session_token AWS session token, required. aws_service, aws_region AWS service region use request. supplied, automatically parsed URL hostname.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_aws_v4.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Sign a request with the AWS SigV4 signing protocol — req_auth_aws_v4","text":"","code":"if (FALSE) { # httr2:::has_paws_credentials() creds <- paws.common::locate_credentials() model_id <- \"anthropic.claude-3-5-sonnet-20240620-v1:0\" req <- request(\"https://bedrock-runtime.us-east-1.amazonaws.com\") # https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_Converse.html req <- req_url_path_append(req, \"model\", model_id, \"converse\") req <- req_body_json(req, list( messages = list(list( role = \"user\", content = list(list(text = \"What's your name?\")) )) )) req <- req_auth_aws_v4( req, aws_access_key_id = creds$access_key_id, aws_secret_access_key = creds$secret_access_key, aws_session_token = creds$session_token ) resp <- req_perform_connection(req) str(resp_body_json(resp)) }"},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_basic.html","id":null,"dir":"Reference","previous_headings":"","what":"Authenticate request with HTTP basic authentication — req_auth_basic","title":"Authenticate request with HTTP basic authentication — req_auth_basic","text":"sets Authorization header. See details https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_basic.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Authenticate request with HTTP basic authentication — req_auth_basic","text":"","code":"req_auth_basic(req, username, password = NULL)"},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_basic.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Authenticate request with HTTP basic authentication — req_auth_basic","text":"req httr2 request object. username User name. password Password. avoid entering password directly calling function captured .Rhistory. Instead, leave unset default behaviour prompt interactively.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_basic.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Authenticate request with HTTP basic authentication — req_auth_basic","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_basic.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Authenticate request with HTTP basic authentication — req_auth_basic","text":"","code":"req <- request(\"http://example.com\") |> req_auth_basic(\"hadley\", \"SECRET\") req #> <httr2_request> #> GET http://example.com #> Headers: #> • Authorization: '<REDACTED>' #> Body: empty req |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Authorization: <REDACTED> #> # httr2 does its best to redact the Authorization header so that you don't # accidentally reveal confidential data. Use `redact_headers` to reveal it: print(req, redact_headers = FALSE) #> <httr2_request> #> GET http://example.com #> Headers: #> • Authorization: 'Basic aGFkbGV5OlNFQ1JFVA==' #> Body: empty req |> req_dry_run(redact_headers = FALSE) #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Authorization: Basic aGFkbGV5OlNFQ1JFVA== #> # We do this because the authorization header is not encrypted and the # so password can easily be discovered: rawToChar(jsonlite::base64_dec(\"aGFkbGV5OlNFQ1JFVA==\")) #> [1] \"hadley:SECRET\""},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_bearer_token.html","id":null,"dir":"Reference","previous_headings":"","what":"Authenticate request with bearer token — req_auth_bearer_token","title":"Authenticate request with bearer token — req_auth_bearer_token","text":"bearer token gives bearer access confidential resources (keep secure like user name password). usually produced large authentication scheme (like various OAuth 2.0 flows), sometimes given directly.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_bearer_token.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Authenticate request with bearer token — req_auth_bearer_token","text":"","code":"req_auth_bearer_token(req, token)"},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_bearer_token.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Authenticate request with bearer token — req_auth_bearer_token","text":"req httr2 request object. token bearer token","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_bearer_token.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Authenticate request with bearer token — req_auth_bearer_token","text":"modified HTTP request.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_auth_bearer_token.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Authenticate request with bearer token — req_auth_bearer_token","text":"","code":"req <- request(\"http://example.com\") |> req_auth_bearer_token(\"sdaljsdf093lkfs\") req #> <httr2_request> #> GET http://example.com #> Headers: #> • Authorization: '<REDACTED>' #> Body: empty # httr2 does its best to redact the Authorization header so that you don't # accidentally reveal confidential data. Use `redact_headers` to reveal it: print(req, redact_headers = FALSE) #> <httr2_request> #> GET http://example.com #> Headers: #> • Authorization: 'Bearer sdaljsdf093lkfs' #> Body: empty"},{"path":"https://httr2.r-lib.org/dev/reference/req_body.html","id":null,"dir":"Reference","previous_headings":"","what":"Send data in request body — req_body","title":"Send data in request body — req_body","text":"req_body_file() sends local file. req_body_raw() sends string raw vector. req_body_json() sends JSON encoded data. Named components data can later modified req_body_json_modify(). req_body_form() sends form encoded data. req_body_multipart() creates multi-part body. Adding body request automatically switch method POST.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_body.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Send data in request body — req_body","text":"","code":"req_body_raw(req, body, type = NULL) req_body_file(req, path, type = NULL) req_body_json( req, data, auto_unbox = TRUE, digits = 22, null = \"null\", type = \"application/json\", ... ) req_body_json_modify(req, ...) req_body_form(.req, ..., .multi = c(\"error\", \"comma\", \"pipe\", \"explode\")) req_body_multipart(.req, ...)"},{"path":"https://httr2.r-lib.org/dev/reference/req_body.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Send data in request body — req_body","text":"req, .req httr2 request object. body literal string raw vector send body. type MIME content type. ignored manually set Content-Type header. path Path file upload. data Data include body. auto_unbox length-1 vectors automatically \"unboxed\" JSON scalars? digits many digits precision numbers use JSON? null NULL translated JSON's null (\"null\") empty list (\"list\"). ... <dynamic-dots> Name-data pairs used send data body. req_body_form(), values must strings (things easily coerced strings); req_body_multipart() values must strings objects produced curl::form_file()/curl::form_data(). req_body_json_modify(), simple data made atomic vectors lists. req_body_json() uses argument differently; takes additional arguments passed jsonlite::toJSON(). .multi Controls happens element ... vector containing multiple values: \"error\", default, throws error. \"comma\", separates values ,, e.g. ?x=1,2. \"pipe\", separates values |, e.g. ?x=1|2. \"explode\", turns element parameter, e.g. ?x=1&x=2. none functions work, can alternatively supply function takes character vector returns string.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_body.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Send data in request body — req_body","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_body.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Send data in request body — req_body","text":"","code":"req <- request(example_url()) |> req_url_path(\"/post\") # Most APIs expect small amounts of data in either form or json encoded: req |> req_body_form(x = \"A simple text string\") |> req_dry_run() #> POST /post HTTP/1.1 #> Host: 127.0.0.1:36861 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Content-Type: application/x-www-form-urlencoded #> Content-Length: 28 #> #> x=A%20simple%20text%20string req |> req_body_json(list(x = \"A simple text string\")) |> req_dry_run() #> POST /post HTTP/1.1 #> Host: 127.0.0.1:36861 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Content-Type: application/json #> Content-Length: 28 #> #> {\"x\":\"A simple text string\"} # For total control over the body, send a string or raw vector req |> req_body_raw(\"A simple text string\") |> req_dry_run() #> POST /post HTTP/1.1 #> Host: 127.0.0.1:36861 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Content-Length: 20 #> #> A simple text string # There are two main ways that APIs expect entire files path <- tempfile() writeLines(letters[1:6], path) # You can send a single file as the body: req |> req_body_file(path) |> req_dry_run() #> POST /post HTTP/1.1 #> Host: 127.0.0.1:36861 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Content-Length: 12 #> #> a #> b #> c #> d #> e #> f # You can send multiple files, or a mix of files and data # with multipart encoding req |> req_body_multipart(a = curl::form_file(path), b = \"some data\") |> req_dry_run() #> POST /post HTTP/1.1 #> Host: 127.0.0.1:36861 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Content-Length: 315 #> Content-Type: multipart/form-data; boundary=------------------------fa97a1b7e15c7405 #> #> --------------------------fa97a1b7e15c7405 #> Content-Disposition: form-data; name=\"a\"; filename=\"file1714154b3eb\" #> Content-Type: application/octet-stream #> #> a #> b #> c #> d #> e #> f #> #> --------------------------fa97a1b7e15c7405 #> Content-Disposition: form-data; name=\"b\" #> #> some data #> --------------------------fa97a1b7e15c7405--"},{"path":"https://httr2.r-lib.org/dev/reference/req_cache.html","id":null,"dir":"Reference","previous_headings":"","what":"Automatically cache requests — req_cache","title":"Automatically cache requests — req_cache","text":"Use req_perform() automatically cache HTTP requests. API requests cacheable, static files often . req_cache() caches responses GET requests status code 200 least one standard caching headers (e.g. Expires, Etag, Last-Modified, Cache-Control), unless caching expressly prohibited Cache-Control: -store. Typically, request still sent server check cached value still --date, need re-download body value. learn HTTP caching, recommend MDN article HTTP caching.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_cache.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Automatically cache requests — req_cache","text":"","code":"req_cache( req, path, use_on_error = FALSE, debug = getOption(\"httr2_cache_debug\", FALSE), max_age = Inf, max_n = Inf, max_size = 1024^3 )"},{"path":"https://httr2.r-lib.org/dev/reference/req_cache.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Automatically cache requests — req_cache","text":"req httr2 request object. path Path cache directory. created automatically exist. quick easy caching within session, can use tempfile(). cache requests within package, can use something like file.path(tools::R_user_dir(\"pkgdown\", \"cache\"), \"httr2\"). httr2 provide helpers manage cache, want empty , can use something like unlink(dir(cache_path, full.names = TRUE)). use_on_error request errors, cache response, req_perform() return instead generating error? debug TRUE emit useful messages telling cache hits misses. can helpful understand whether caching actually anything use case. max_n, max_age, max_size Automatically prune cache specifying one : max_age: delete files older number seconds. max_n: delete files (oldest newest) preserve many files. max_size: delete files (oldest newest) preserve many bytes. cache pruning performed per minute.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_cache.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Automatically cache requests — req_cache","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_cache.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Automatically cache requests — req_cache","text":"","code":"# GitHub uses HTTP caching for all raw files. url <- paste0( \"https://raw.githubusercontent.com/allisonhorst/palmerpenguins/\", \"master/inst/extdata/penguins.csv\" ) # Here I set debug = TRUE so you can see what's happening req <- request(url) |> req_cache(tempdir(), debug = TRUE) # First request downloads the data resp <- req |> req_perform() #> Pruning cache #> Saving response to cache \"d5d1ddd7f99f55dbc920c63f942804c0\" # Second request retrieves it from the cache resp <- req |> req_perform() #> Found url in cache \"d5d1ddd7f99f55dbc920c63f942804c0\" #> Cached value is fresh; using response from cache"},{"path":"https://httr2.r-lib.org/dev/reference/req_cookie_preserve.html","id":null,"dir":"Reference","previous_headings":"","what":"Set and preserve cookies — req_cookie_preserve","title":"Set and preserve cookies — req_cookie_preserve","text":"Use req_cookie_set() set client side cookies sent server. default, httr2 uses clean slate every request meaning cookies automatically preserved across requests. preserve cookies, use req_cookie_preserve() along path cookie file read updated request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_cookie_preserve.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Set and preserve cookies — req_cookie_preserve","text":"","code":"req_cookie_preserve(req, path) req_cookies_set(req, ...)"},{"path":"https://httr2.r-lib.org/dev/reference/req_cookie_preserve.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Set and preserve cookies — req_cookie_preserve","text":"req httr2 request object. path path file cookies read updated request. ... <dynamic-dots> Name-value pairs define query parameters. value must atomic vector, automatically escaped. opt-escaping, wrap strings ().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_cookie_preserve.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Set and preserve cookies — req_cookie_preserve","text":"","code":"# Use `req_cookies_set()` to set client-side cookies request(example_url()) |> req_cookies_set(a = 1, b = 1) |> req_dry_run() #> GET / HTTP/1.1 #> Host: 127.0.0.1:36861 #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Cookie: a=1;b=1 #> # Use `req_cookie_preserve()` to preserve server-side cookies across requests path <- tempfile() # Set a server-side cookie request(example_url()) |> req_cookie_preserve(path) |> req_template(\"/cookies/set/:name/:value\", name = \"chocolate\", value = \"chip\") |> req_perform() |> resp_body_json() #> $cookies #> $cookies$chocolate #> [1] \"chip\" #> #> # Set another sever-side cookie request(example_url()) |> req_cookie_preserve(path) |> req_template(\"/cookies/set/:name/:value\", name = \"oatmeal\", value = \"raisin\") |> req_perform() |> resp_body_json() #> $cookies #> $cookies$chocolate #> [1] \"chip\" #> #> $cookies$oatmeal #> [1] \"raisin\" #> #> # Add a client side cookie request(example_url()) |> req_url_path(\"/cookies/set\") |> req_cookie_preserve(path) |> req_cookies_set(snicker = \"doodle\") |> req_perform() |> resp_body_json() #> $cookies #> $cookies$chocolate #> [1] \"chip\" #> #> $cookies$oatmeal #> [1] \"raisin\" #> #> $cookies$snicker #> [1] \"doodle\" #> #> # The cookie path has a straightforward format cat(readChar(path, nchars = 1e4)) #> # Netscape HTTP Cookie File #> # https://curl.se/docs/http-cookies.html #> # This file was generated by libcurl! Edit at your own risk. #> #> 127.0.0.1\tFALSE\t/\tFALSE\t0\tchocolate\tchip #> 127.0.0.1\tFALSE\t/\tFALSE\t0\toatmeal\traisin"},{"path":"https://httr2.r-lib.org/dev/reference/req_dry_run.html","id":null,"dir":"Reference","previous_headings":"","what":"Perform a dry run — req_dry_run","title":"Perform a dry run — req_dry_run","text":"shows exactly httr2 send server, without actually sending anything. requires httpuv package works sending real HTTP request local webserver, thanks magic curl::curl_echo().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_dry_run.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Perform a dry run — req_dry_run","text":"","code":"req_dry_run(req, quiet = FALSE, redact_headers = TRUE)"},{"path":"https://httr2.r-lib.org/dev/reference/req_dry_run.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Perform a dry run — req_dry_run","text":"req httr2 request object. quiet TRUE print anything. redact_headers Redact confidential data headers? Currently redacts contents Authorization header prevent accidentally leaking credentials debugging/reprexing.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_dry_run.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Perform a dry run — req_dry_run","text":"Invisibly, list containing information request, including method, path, headers.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_dry_run.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Perform a dry run — req_dry_run","text":"","code":"# httr2 adds default User-Agent, Accept, and Accept-Encoding headers request(\"http://example.com\") |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> # the Authorization header is automatically redacted to avoid leaking # credentials on the console req <- request(\"http://example.com\") |> req_auth_basic(\"user\", \"password\") req |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Authorization: <REDACTED> #> # if you need to see it, use redact_headers = FALSE req |> req_dry_run(redact_headers = FALSE) #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Authorization: Basic dXNlcjpwYXNzd29yZA== #>"},{"path":"https://httr2.r-lib.org/dev/reference/req_error.html","id":null,"dir":"Reference","previous_headings":"","what":"Control handling of HTTP errors — req_error","title":"Control handling of HTTP errors — req_error","text":"req_perform() automatically convert HTTP errors (.e. 4xx 5xx status code) R errors. Use req_error() either override defaults, extract additional information response useful expose user.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_error.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Control handling of HTTP errors — req_error","text":"","code":"req_error(req, is_error = NULL, body = NULL)"},{"path":"https://httr2.r-lib.org/dev/reference/req_error.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Control handling of HTTP errors — req_error","text":"req httr2 request object. is_error predicate function takes single argument (response) returns TRUE FALSE indicating whether R error signalled. body callback function takes single argument (response) returns character vector additional information include body error. vector passed along message argument rlang::abort() can use formatting supports.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_error.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Control handling of HTTP errors — req_error","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_error.html","id":"error-handling","dir":"Reference","previous_headings":"","what":"Error handling","title":"Control handling of HTTP errors — req_error","text":"req_perform() designed succeed get valid HTTP response. two ways request can fail: HTTP request might fail, example connection dropped server exist. type error class c(\"httr2_failure\", \"httr2_error\"). HTTP request might succeed, return HTTP status code represents error, e.g. 404 Found specified resource found. type error (e.g.) class c(\"httr2_http_404\", \"httr2_http\", \"httr2_error\"). error classes designed used conjunction R's condition handling tools (https://adv-r.hadley.nz/conditions.html). example, want return default value server returns 404, use tryCatch(): want re-throw error additional context, use withCallingHandlers(), e.g.: Learn error chaining rlang::topic-error-chaining.","code":"tryCatch( req |> req_perform() |> resp_body_json(), httr2_http_404 = function(cnd) NULL ) withCallingHandlers( req |> req_perform() |> resp_body_json(), httr2_http_404 = function(cnd) { rlang::abort(\"Couldn't find user\", parent = cnd) } )"},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_error.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Control handling of HTTP errors — req_error","text":"","code":"# Performing this request usually generates an error because httr2 # converts HTTP errors into R errors: req <- request(example_url()) |> req_url_path(\"/status/404\") try(req |> req_perform()) #> Error in req_perform(req) : HTTP 404 Not Found. # You can still retrieve it with last_response() last_response() #> <httr2_response> #> GET http://127.0.0.1:36861/status/404 #> Status: 404 Not Found #> Content-Type: text/plain #> Body: None # But you might want to suppress this behaviour: resp <- req |> req_error(is_error = \\(resp) FALSE) |> req_perform() resp #> <httr2_response> #> GET http://127.0.0.1:36861/status/404 #> Status: 404 Not Found #> Content-Type: text/plain #> Body: None # Or perhaps you're working with a server that routinely uses the # wrong HTTP error codes only 500s are really errors request(\"http://example.com\") |> req_error(is_error = \\(resp) resp_status(resp) == 500) #> <httr2_request> #> GET http://example.com #> Body: empty #> Policies: #> • error_is_error: a function # Most typically you'll use req_error() to add additional information # extracted from the response body (or sometimes header): error_body <- function(resp) { resp_body_json(resp)$error } request(\"http://example.com\") |> req_error(body = error_body) #> <httr2_request> #> GET http://example.com #> Body: empty #> Policies: #> • error_body: a function # Learn more in https://httr2.r-lib.org/articles/wrapping-apis.html"},{"path":"https://httr2.r-lib.org/dev/reference/req_headers.html","id":null,"dir":"Reference","previous_headings":"","what":"Modify request headers — req_headers","title":"Modify request headers — req_headers","text":"req_headers() allows set value header.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_headers.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Modify request headers — req_headers","text":"","code":"req_headers(.req, ..., .redact = NULL)"},{"path":"https://httr2.r-lib.org/dev/reference/req_headers.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Modify request headers — req_headers","text":".req request. ... <dynamic-dots> Name-value pairs headers values. Use NULL reset value httr2's default Use \"\" remove header Use character vector repeat header. .redact Headers redact. NULL, default, added headers redacted.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_headers.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Modify request headers — req_headers","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_headers.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Modify request headers — req_headers","text":"","code":"req <- request(\"http://example.com\") # Use req_headers() to add arbitrary additional headers to the request req |> req_headers(MyHeader = \"MyValue\") |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> MyHeader: MyValue #> # Repeated use overrides the previous value: req |> req_headers(MyHeader = \"Old value\") |> req_headers(MyHeader = \"New value\") |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> MyHeader: New value #> # Setting Accept to NULL uses curl's default: req |> req_headers(Accept = NULL) |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> # Setting it to \"\" removes it: req |> req_headers(Accept = \"\") |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept-Encoding: deflate, gzip, br, zstd #> # If you need to repeat a header, provide a vector of values # (this is rarely needed, but is important in a handful of cases) req |> req_headers(HeaderName = c(\"Value 1\", \"Value 2\", \"Value 3\")) |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> HeaderName: Value 1 #> HeaderName: Value 2 #> HeaderName: Value 3 #> # If you have headers in a list, use !!! headers <- list(HeaderOne = \"one\", HeaderTwo = \"two\") req |> req_headers(!!!headers, HeaderThree = \"three\") |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> HeaderOne: one #> HeaderTwo: two #> HeaderThree: three #> # Use `.redact` to hide a header in the output req |> req_headers(Secret = \"this-is-private\", Public = \"but-this-is-not\", .redact = \"Secret\") |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> Secret: <REDACTED> #> Public: but-this-is-not #>"},{"path":"https://httr2.r-lib.org/dev/reference/req_method.html","id":null,"dir":"Reference","previous_headings":"","what":"Set HTTP method in request — req_method","title":"Set HTTP method in request — req_method","text":"Use function use custom HTTP method like HEAD, DELETE, PATCH, UPDATE, OPTIONS. default method GET requests without body, POST requests body.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_method.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Set HTTP method in request — req_method","text":"","code":"req_method(req, method)"},{"path":"https://httr2.r-lib.org/dev/reference/req_method.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Set HTTP method in request — req_method","text":"req httr2 request object. method Custom HTTP method","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_method.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Set HTTP method in request — req_method","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_method.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Set HTTP method in request — req_method","text":"","code":"request(example_url()) |> req_method(\"PATCH\") #> <httr2_request> #> PATCH http://127.0.0.1:36861/ #> Body: empty request(example_url()) |> req_method(\"PUT\") #> <httr2_request> #> PUT http://127.0.0.1:36861/ #> Body: empty request(example_url()) |> req_method(\"HEAD\") #> <httr2_request> #> HEAD http://127.0.0.1:36861/ #> Body: empty"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth.html","id":null,"dir":"Reference","previous_headings":"","what":"OAuth authentication — req_oauth","title":"OAuth authentication — req_oauth","text":"low-level helper automatically authenticating request OAuth flow, caching access token refreshing possible. need use function implementing OAuth flow.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"OAuth authentication — req_oauth","text":"","code":"req_oauth(req, flow, flow_params, cache)"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"OAuth authentication — req_oauth","text":"req httr2 request object. flow oauth_flow_ function used generate access token. flow_params Parameters flow. named list whose names match argument names flow. cache object controls token cached. list containing three functions: get() retrieves token cache, returning NULL cached yet. set() saves token cache. clear() removes token cache","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"OAuth authentication — req_oauth","text":"oauth_token.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_auth_code.html","id":null,"dir":"Reference","previous_headings":"","what":"OAuth with authorization code — req_oauth_auth_code","title":"OAuth with authorization code — req_oauth_auth_code","text":"Authenticate using OAuth authorization code flow, defined Section 4.1 RFC 6749. flow commonly used OAuth flow user opens page browser, approves access, returns R. possible, redirects browser back temporary local webserver capture authorization code. possible (e.g. running hosted platform like RStudio Server), provide custom redirect_uri httr2 prompt user enter code manually. Learn overall OAuth authentication flow https://httr2.r-lib.org/articles/oauth.html.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_auth_code.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"OAuth with authorization code — req_oauth_auth_code","text":"","code":"req_oauth_auth_code( req, client, auth_url, scope = NULL, pkce = TRUE, auth_params = list(), token_params = list(), redirect_uri = oauth_redirect_uri(), cache_disk = FALSE, cache_key = NULL, host_name = deprecated(), host_ip = deprecated(), port = deprecated() ) oauth_flow_auth_code( client, auth_url, scope = NULL, pkce = TRUE, auth_params = list(), token_params = list(), redirect_uri = oauth_redirect_uri(), host_name = deprecated(), host_ip = deprecated(), port = deprecated() )"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_auth_code.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"OAuth with authorization code — req_oauth_auth_code","text":"req httr2 request object. client oauth_client(). auth_url Authorization url; need discover reading documentation. scope Scopes requested resource owner. pkce Use \"Proof Key Code Exchange\"? adds extra layer security always used supported server. auth_params list containing additional parameters passed oauth_flow_auth_code_url(). token_params List containing additional parameters passed token_url. redirect_uri URL redirect back authorization complete. Often must registered API advance. httr2 supports three forms redirect. Firstly, can use localhost url (default), httr2 set temporary webserver listen OAuth redirect. case, httr2 automatically append random port. need set fixed port API requires , specify (e.g.) \"http://localhost:1011\". technique works well working computer. Secondly, can provide URL website uses Javascript give user code copy paste back R session (see https://www.tidyverse.org/google-callback/ https://github.com/r-lib/gargle/blob/main/inst/pseudo-oob/google-callback/index.html examples). less convenient (requires user interaction) also works hosted environments like RStudio Server. Finally, hosted platforms might set HTTR2_OAUTH_REDIRECT_URL HTTR2_OAUTH_CODE_SOURCE_URL environment variables. case, httr2 use HTTR2_OAUTH_REDIRECT_URL redirects default, poll HTTR2_OAUTH_CODE_SOURCE_URL endpoint state parameter receives code response (encounters error). delegates completion authorization flow hosted platform. cache_disk access token cached disk? reduces number times need re-authenticate cost storing access credentials disk. Learn https://httr2.r-lib.org/articles/oauth.html. cache_key want cache multiple tokens per app, use key disambiguate . host_name, host_ip, port Now use redirect_uri instead.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_auth_code.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"OAuth with authorization code — req_oauth_auth_code","text":"req_oauth_auth_code() returns modified HTTP request use OAuth; oauth_flow_auth_code() returns oauth_token.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_auth_code.html","id":"security-considerations","dir":"Reference","previous_headings":"","what":"Security considerations","title":"OAuth with authorization code — req_oauth_auth_code","text":"authorization code flow used web applications native applications (equivalent R packages). RFC 8252 spells important considerations native apps. importantly way native apps keep secrets users. means server either require client_secret (.e. public client confidential client) ensure possession client_secret bestow meaningful rights. modern APIs bigger players (Azure, Google, etc) explicitly native apps. However, cases, even older APIs, possessing client_secret gives ability anything harmful, general principle fine include R package, long mildly obfuscated protect credential scraping. incentive steal client credentials takes less time create new client find client secret.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_auth_code.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"OAuth with authorization code — req_oauth_auth_code","text":"","code":"req_auth_github <- function(req) { req_oauth_auth_code( req, client = example_github_client(), auth_url = \"https://github.com/login/oauth/authorize\" ) } request(\"https://api.github.com/user\") |> req_auth_github() #> <httr2_request> #> GET https://api.github.com/user #> Body: empty #> Policies: #> • auth_sign: a list #> • auth_oauth: TRUE"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_bearer_jwt.html","id":null,"dir":"Reference","previous_headings":"","what":"OAuth with a bearer JWT (JSON web token) — req_oauth_bearer_jwt","title":"OAuth with a bearer JWT (JSON web token) — req_oauth_bearer_jwt","text":"Authenticate using Bearer JWT (JSON web token) authorization grant get access token, defined Section 2.1 RFC 7523. often used service accounts, accounts used primarily automated environments. Learn overall OAuth authentication flow https://httr2.r-lib.org/articles/oauth.html.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_bearer_jwt.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"OAuth with a bearer JWT (JSON web token) — req_oauth_bearer_jwt","text":"","code":"req_oauth_bearer_jwt( req, client, claim, signature = \"jwt_encode_sig\", signature_params = list(), scope = NULL, token_params = list() ) oauth_flow_bearer_jwt( client, claim, signature = \"jwt_encode_sig\", signature_params = list(), scope = NULL, token_params = list() )"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_bearer_jwt.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"OAuth with a bearer JWT (JSON web token) — req_oauth_bearer_jwt","text":"req httr2 request object. client oauth_client(). claim list claims. elements claim set static apart iat, nbf, exp, jti, provide list jwt_claim() automatically fill dynamic components. components need vary, can instead provide zero-argument callback function call jwt_claim(). signature Function use sign claim, e.g. jwt_encode_sig(). signature_params Additional arguments passed signature, e.g. size, header. scope Scopes requested resource owner. token_params List containing additional parameters passed token_url.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_bearer_jwt.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"OAuth with a bearer JWT (JSON web token) — req_oauth_bearer_jwt","text":"req_oauth_bearer_jwt() returns modified HTTP request use OAuth; oauth_flow_bearer_jwt() returns oauth_token.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_bearer_jwt.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"OAuth with a bearer JWT (JSON web token) — req_oauth_bearer_jwt","text":"","code":"req_auth <- function(req) { req_oauth_bearer_jwt( req, client = oauth_client(\"example\", \"https://example.com/get_token\"), claim = jwt_claim() ) } request(\"https://example.com\") |> req_auth() #> <httr2_request> #> GET https://example.com #> Body: empty #> Policies: #> • auth_sign: a list #> • auth_oauth: TRUE"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_client_credentials.html","id":null,"dir":"Reference","previous_headings":"","what":"OAuth with client credentials — req_oauth_client_credentials","title":"OAuth with client credentials — req_oauth_client_credentials","text":"Authenticate using OAuth client credentials flow, defined Section 4.4 RFC 6749. used allow client access resources controls directly, behalf user. Learn overall OAuth authentication flow https://httr2.r-lib.org/articles/oauth.html.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_client_credentials.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"OAuth with client credentials — req_oauth_client_credentials","text":"","code":"req_oauth_client_credentials(req, client, scope = NULL, token_params = list()) oauth_flow_client_credentials(client, scope = NULL, token_params = list())"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_client_credentials.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"OAuth with client credentials — req_oauth_client_credentials","text":"req httr2 request object. client oauth_client(). scope Scopes requested resource owner. token_params List containing additional parameters passed token_url.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_client_credentials.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"OAuth with client credentials — req_oauth_client_credentials","text":"req_oauth_client_credentials() returns modified HTTP request use OAuth; oauth_flow_client_credentials() returns oauth_token.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_client_credentials.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"OAuth with client credentials — req_oauth_client_credentials","text":"","code":"req_auth <- function(req) { req_oauth_client_credentials( req, client = oauth_client(\"example\", \"https://example.com/get_token\") ) } request(\"https://example.com\") |> req_auth() #> <httr2_request> #> GET https://example.com #> Body: empty #> Policies: #> • auth_sign: a list #> • auth_oauth: TRUE"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_device.html","id":null,"dir":"Reference","previous_headings":"","what":"OAuth with device flow — req_oauth_device","title":"OAuth with device flow — req_oauth_device","text":"Authenticate using OAuth device flow, defined RFC 8628. designed devices access web browser (ever authenticated app TV, probably flow used), also works well within R. Learn overall OAuth authentication flow https://httr2.r-lib.org/articles/oauth.html.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_device.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"OAuth with device flow — req_oauth_device","text":"","code":"req_oauth_device( req, client, auth_url, scope = NULL, auth_params = list(), token_params = list(), cache_disk = FALSE, cache_key = NULL ) oauth_flow_device( client, auth_url, pkce = FALSE, scope = NULL, auth_params = list(), token_params = list() )"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_device.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"OAuth with device flow — req_oauth_device","text":"req httr2 request object. client oauth_client(). auth_url Authorization url; need discover reading documentation. scope Scopes requested resource owner. auth_params list containing additional parameters passed oauth_flow_auth_code_url(). token_params List containing additional parameters passed token_url. cache_disk access token cached disk? reduces number times need re-authenticate cost storing access credentials disk. Learn https://httr2.r-lib.org/articles/oauth.html. cache_key want cache multiple tokens per app, use key disambiguate . pkce Use \"Proof Key Code Exchange\"? adds extra layer security always used supported server.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_device.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"OAuth with device flow — req_oauth_device","text":"req_oauth_device() returns modified HTTP request use OAuth; oauth_flow_device() returns oauth_token.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_device.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"OAuth with device flow — req_oauth_device","text":"","code":"req_auth_github <- function(req) { req_oauth_device( req, client = example_github_client(), auth_url = \"https://github.com/login/device/code\" ) } request(\"https://api.github.com/user\") |> req_auth_github() #> <httr2_request> #> GET https://api.github.com/user #> Body: empty #> Policies: #> • auth_sign: a list #> • auth_oauth: TRUE"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_password.html","id":null,"dir":"Reference","previous_headings":"","what":"OAuth with username and password — req_oauth_password","title":"OAuth with username and password — req_oauth_password","text":"function implements OAuth resource owner password flow, defined Section 4.3 RFC 6749. allows user supply password , exchanging access token can cached locally. Learn overall OAuth authentication flow https://httr2.r-lib.org/articles/oauth.html","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_password.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"OAuth with username and password — req_oauth_password","text":"","code":"req_oauth_password( req, client, username, password = NULL, scope = NULL, token_params = list(), cache_disk = FALSE, cache_key = username ) oauth_flow_password( client, username, password = NULL, scope = NULL, token_params = list() )"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_password.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"OAuth with username and password — req_oauth_password","text":"req httr2 request object. client oauth_client(). username User name. password Password. avoid entering password directly calling function captured .Rhistory. Instead, leave unset default behaviour prompt interactively. scope Scopes requested resource owner. token_params List containing additional parameters passed token_url. cache_disk access token cached disk? reduces number times need re-authenticate cost storing access credentials disk. Learn https://httr2.r-lib.org/articles/oauth.html. cache_key want cache multiple tokens per app, use key disambiguate .","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_password.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"OAuth with username and password — req_oauth_password","text":"req_oauth_password() returns modified HTTP request use OAuth; oauth_flow_password() returns oauth_token.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_password.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"OAuth with username and password — req_oauth_password","text":"","code":"req_auth <- function(req) { req_oauth_password(req, client = oauth_client(\"example\", \"https://example.com/get_token\"), username = \"username\" ) } if (interactive()) { request(\"https://example.com\") |> req_auth() }"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_refresh.html","id":null,"dir":"Reference","previous_headings":"","what":"OAuth with a refresh token — req_oauth_refresh","title":"OAuth with a refresh token — req_oauth_refresh","text":"Authenticate using refresh token, following process described Section 6 RFC 6749. technique primarily useful testing: can manually retrieve OAuth token using another OAuth flow (e.g. oauth_flow_auth_code()), extract refresh token result, save environment variable use automated tests. requesting access token, server may also return new refresh token. happens, oauth_flow_refresh() warn, retrieve new update refresh token update stored value. find happening lot, sign using different flow automated tests. Learn overall OAuth authentication flow https://httr2.r-lib.org/articles/oauth.html.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_refresh.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"OAuth with a refresh token — req_oauth_refresh","text":"","code":"req_oauth_refresh( req, client, refresh_token = Sys.getenv(\"HTTR2_REFRESH_TOKEN\"), scope = NULL, token_params = list() ) oauth_flow_refresh( client, refresh_token = Sys.getenv(\"HTTR2_REFRESH_TOKEN\"), scope = NULL, token_params = list() )"},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_refresh.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"OAuth with a refresh token — req_oauth_refresh","text":"req httr2 request object. client oauth_client(). refresh_token refresh token. equivalent password typed console stored script. Instead, recommend placing environment variable; default behaviour look HTTR2_REFRESH_TOKEN. scope Scopes requested resource owner. token_params List containing additional parameters passed token_url.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_refresh.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"OAuth with a refresh token — req_oauth_refresh","text":"req_oauth_refresh() returns modified HTTP request use OAuth; oauth_flow_refresh() returns oauth_token.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_oauth_refresh.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"OAuth with a refresh token — req_oauth_refresh","text":"","code":"client <- oauth_client(\"example\", \"https://example.com/get_token\") req <- request(\"https://example.com\") req |> req_oauth_refresh(client) #> <httr2_request> #> GET https://example.com #> Body: empty #> Policies: #> • auth_sign: a list #> • auth_oauth: TRUE"},{"path":"https://httr2.r-lib.org/dev/reference/req_options.html","id":null,"dir":"Reference","previous_headings":"","what":"Set arbitrary curl options in request — req_options","title":"Set arbitrary curl options in request — req_options","text":"req_options() expert use ; allows directly set libcurl options access features otherwise available httr2.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_options.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Set arbitrary curl options in request — req_options","text":"","code":"req_options(.req, ...)"},{"path":"https://httr2.r-lib.org/dev/reference/req_options.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Set arbitrary curl options in request — req_options","text":".req request. ... <dynamic-dots> Name-value pairs. name valid curl option, found curl::curl_options().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_options.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Set arbitrary curl options in request — req_options","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_options.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Set arbitrary curl options in request — req_options","text":"","code":"# req_options() allows you to access curl options that are not otherwise # exposed by httr2. For example, in very special cases you may need to # turn off SSL verification. This is generally a bad idea so httr2 doesn't # provide a convenient wrapper, but if you really know what you're doing # you can still access this libcurl option: req <- request(\"https://example.com\") |> req_options(ssl_verifypeer = 0)"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform.html","id":null,"dir":"Reference","previous_headings":"","what":"Perform a request to get a response — req_perform","title":"Perform a request to get a response — req_perform","text":"preparing request, call req_perform() perform , fetching results back R response. default HTTP method GET unless body (set req_body_json friends) present, case POST. can override defaults req_method().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Perform a request to get a response — req_perform","text":"","code":"req_perform( req, path = NULL, verbosity = NULL, mock = getOption(\"httr2_mock\", NULL), error_call = current_env() )"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Perform a request to get a response — req_perform","text":"req httr2 request object. path Optionally, path save body response. useful large responses since avoids storing response memory. verbosity much information print? wrapper around req_verbose() uses integer control verbosity: 0: output 1: show headers 2: show headers bodies 3: show headers, bodies, curl status messages. Use with_verbosity() control verbosity requests affect directly. mock mocking function. supplied, function called request. return either NULL (want handle request) response (). See with_mock()/ local_mock() details. error_call execution environment currently running function, e.g. caller_env(). function mentioned error messages source error. See call argument abort() information.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Perform a request to get a response — req_perform","text":"HTTP request succeeds, status code ok (e.g. 200), HTTP response. HTTP request succeeds, status code error (e.g 404), error class c(\"httr2_http_404\", \"httr2_http\"). default, 400 500 status codes treated error, can customise req_error(). HTTP request fails (e.g. connection dropped server exist), error class \"httr2_failure\".","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform.html","id":"requests","dir":"Reference","previous_headings":"","what":"Requests","title":"Perform a request to get a response — req_perform","text":"Note one call req_perform() may perform multiple HTTP requests: url redirected 301, 302, 303, 307, curl automatically follow Location header new location. configured retries req_retry() request fails transient problem, req_perform() try waiting bit. See req_retry() details. using OAuth, cached token expired, req_perform() get new token either using refresh token (available) running OAuth flow.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform.html","id":"progress-bar","dir":"Reference","previous_headings":"","what":"Progress bar","title":"Perform a request to get a response — req_perform","text":"req_perform() automatically add progress bar needs wait requests req_throttle() req_retry(). can turn progress bar (just show total time wait) setting options(httr2_progress = FALSE).","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_perform.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Perform a request to get a response — req_perform","text":"","code":"request(\"https://google.com\") |> req_perform() #> <httr2_response> #> GET https://www.google.com/ #> Status: 200 OK #> Content-Type: text/html #> Body: In memory (22243 bytes)"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_connection.html","id":null,"dir":"Reference","previous_headings":"","what":"Perform a request and return a streaming connection — req_perform_connection","title":"Perform a request and return a streaming connection — req_perform_connection","text":"Use req_perform_connection() perform request want stream response body. response returned req_perform_connection() includes connection body. can use resp_stream_raw(), resp_stream_lines(), resp_stream_sse() retrieve data chunk time. Always finish closing connection calling close(response). alternative interface req_perform_stream() returns connection can use pull data, rather providing callbacks data pushed . useful want work handling inputs stream.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_connection.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Perform a request and return a streaming connection — req_perform_connection","text":"","code":"req_perform_connection(req, blocking = TRUE)"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_connection.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Perform a request and return a streaming connection — req_perform_connection","text":"req httr2 request object. blocking retrieving data, connection block wait desired information immediately return (possibly nothing)?","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_connection.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Perform a request and return a streaming connection — req_perform_connection","text":"","code":"req <- request(example_url()) |> req_url_path(\"/stream-bytes/32768\") resp <- req_perform_connection(req) length(resp_stream_raw(resp, kb = 16)) #> [1] 16384 length(resp_stream_raw(resp, kb = 16)) #> [1] 16384 # When the stream has no more data, you'll get an empty result: length(resp_stream_raw(resp, kb = 16)) #> [1] 0 # Always close the response when you're done close(resp)"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_iterative.html","id":null,"dir":"Reference","previous_headings":"","what":"Perform requests iteratively, generating new requests from previous responses — req_perform_iterative","title":"Perform requests iteratively, generating new requests from previous responses — req_perform_iterative","text":"req_perform_iterative() iteratively generates performs requests, using callback function, next_req, define next request based current request response. probably want pair iteration helper use multi-response handler process result.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_iterative.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Perform requests iteratively, generating new requests from previous responses — req_perform_iterative","text":"","code":"req_perform_iterative( req, next_req, path = NULL, max_reqs = 20, on_error = c(\"stop\", \"return\"), progress = TRUE )"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_iterative.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Perform requests iteratively, generating new requests from previous responses — req_perform_iterative","text":"req first request perform. next_req function takes previous response (resp) request (req) returns request next page NULL iteration terminate. See details. path Optionally, path save body request. glue string uses {} distinguish different requests. Useful large responses avoids storing response memory. max_reqs maximum number requests perform. Use Inf perform requests next_req() returns NULL. on_error happen request fails? \"stop\", default: stop iterating error. \"return\": stop iterating, returning successful responses far, well error object failed request. progress Display progress bar? Use TRUE turn basic progress bar, use string give name, see progress_bars customise ways.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_iterative.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Perform requests iteratively, generating new requests from previous responses — req_perform_iterative","text":"list, length max_reqs, containing responses possibly one error object, on_error \"return\" one requests errors. present, error object always last element list. httr2 errors captured; see req_error() details.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_iterative.html","id":"next-req-","dir":"Reference","previous_headings":"","what":"next_req()","title":"Perform requests iteratively, generating new requests from previous responses — req_perform_iterative","text":"key piece makes req_perform_iterative() work next_req() argument. common cases, can use one canned helpers, like iterate_with_offset(). , however, API wrapping uses different pagination system, need write . section gives advice. Generally, function needs inspect response, extract data , use modify previous request. example, imagine response returns cursor, needs added body request. simplest version function might look like : one problem : pages return, cursor NULL, req_body_json_modify() still generate meaningful request. need handle specifically returning NULL: value NULL lets req_perform_iterative() know pages remaining. one last feature might want add iterator: know total number pages, nice let req_perform_iterative() know can adjust progress bar. (ever decrease number pages, increase .) can signal total number pages calling signal_total_pages(), like :","code":"next_req <- function(resp, req) { cursor <- resp_body_json(resp)$next_cursor req |> req_body_json_modify(cursor = cursor) } next_req <- function(resp, req) { cursor <- resp_body_json(resp)$next_cursor if (is.null(cursor)) return(NULL) req |> req_body_json_modify(cursor = cursor) } next_req <- function(resp, req) { body <- resp_body_json(resp) cursor <- body$next_cursor if (is.null(cursor)) return(NULL) signal_total_pages(body$pages) req |> req_body_json_modify(cursor = cursor) }"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_iterative.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Perform requests iteratively, generating new requests from previous responses — req_perform_iterative","text":"","code":"req <- request(example_url()) |> req_url_path(\"/iris\") |> req_throttle(10) |> req_url_query(limit = 5) resps <- req_perform_iterative(req, iterate_with_offset(\"page_index\")) #> Iterating ■■■■■■■■■■■■■■■■ 50% | ETA: 1s #> Iterating ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 95% | ETA: 0s #> Iterating ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 100% | ETA: 0s data <- resps |> resps_data(function(resp) { data <- resp_body_json(resp)$data data.frame( Sepal.Length = sapply(data, `[[`, \"Sepal.Length\"), Sepal.Width = sapply(data, `[[`, \"Sepal.Width\"), Petal.Length = sapply(data, `[[`, \"Petal.Length\"), Petal.Width = sapply(data, `[[`, \"Petal.Width\"), Species = sapply(data, `[[`, \"Species\") ) }) str(data) #> 'data.frame':\t100 obs. of 5 variables: #> $ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ... #> $ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ... #> $ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ... #> $ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ... #> $ Species : chr \"setosa\" \"setosa\" \"setosa\" \"setosa\" ..."},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_parallel.html","id":null,"dir":"Reference","previous_headings":"","what":"Perform a list of requests in parallel — req_perform_parallel","title":"Perform a list of requests in parallel — req_perform_parallel","text":"variation req_perform_sequential() performs multiple requests parallel. Exercise caution using function; easy pummel server many simultaneous requests. use hosts designed serve many files , typically web servers, API servers. req_perform_parallel() limitations: retrieve new OAuth token expires part way requests. perform throttling req_throttle(). attempt retries described req_retry(). consults cache set req_cache() /requests. limitations problematic use case, recommend req_perform_sequential() instead.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_parallel.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Perform a list of requests in parallel — req_perform_parallel","text":"","code":"req_perform_parallel( reqs, paths = NULL, pool = NULL, on_error = c(\"stop\", \"return\", \"continue\"), progress = TRUE )"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_parallel.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Perform a list of requests in parallel — req_perform_parallel","text":"reqs list requests. paths optional character vector paths, want download request bodies disk. supplied, must length reqs. pool Optionally, curl pool made curl::new_pool(). Supply want override defaults total concurrent connections (100) concurrent connections per host (6). on_error happen one requests fails? stop, default: stop iterating error. return: stop iterating, returning successful responses received far, well error object failed request. continue: continue iterating, recording errors result. progress Display progress bar? Use TRUE turn basic progress bar, use string give name, see progress_bars customise ways.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_parallel.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Perform a list of requests in parallel — req_perform_parallel","text":"list, length reqs, containing responses possibly error objects, on_error \"return\" \"continue\" one responses errors. on_error \"return\" errors ith request, ith element result error object, remaining elements NULL. on_error \"continue\", mix requests error objects. httr2 errors captured; see req_error() details.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_parallel.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Perform a list of requests in parallel — req_perform_parallel","text":"","code":"# Requesting these 4 pages one at a time would take 2 seconds: request_base <- request(example_url()) reqs <- list( request_base |> req_url_path(\"/delay/0.5\"), request_base |> req_url_path(\"/delay/0.5\"), request_base |> req_url_path(\"/delay/0.5\"), request_base |> req_url_path(\"/delay/0.5\") ) # But it's much faster if you request in parallel system.time(resps <- req_perform_parallel(reqs)) #> user system elapsed #> 0.340 0.689 1.030 # req_perform_parallel() will fail on error reqs <- list( request_base |> req_url_path(\"/status/200\"), request_base |> req_url_path(\"/status/400\"), request(\"FAILURE\") ) try(resps <- req_perform_parallel(reqs)) #> Error in req_perform_parallel(reqs) : HTTP 400 Bad Request. # but can use on_error to capture all successful results resps <- req_perform_parallel(reqs, on_error = \"continue\") # Inspect the successful responses resps |> resps_successes() #> [[1]] #> <httr2_response> #> GET http://127.0.0.1:36861/status/200 #> Status: 200 OK #> Content-Type: text/plain #> Body: None #> # And the failed responses resps |> resps_failures() |> resps_requests() #> [[1]] #> <httr2_request> #> GET http://127.0.0.1:36861/status/400 #> Body: empty #> #> [[2]] #> <httr2_request> #> GET FAILURE #> Body: empty #>"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_promise.html","id":null,"dir":"Reference","previous_headings":"","what":"Perform request asynchronously using the promises package — req_perform_promise","title":"Perform request asynchronously using the promises package — req_perform_promise","text":"variation req_perform() returns promises::promise() object immediately performs request background, returning program control request finished. See promises package documentation details work resulting promise object. Like req_perform_parallel(), exercise caution using function; easy pummel server many simultaneous requests. Also, servers can handle 1 request time, responses may still return sequentially. req_perform_promise() also similar limitations req_perform_parallel() function, : retrieve new OAuth token expires promised request created actually requested. perform throttling req_throttle(). attempt retries described req_retry(). consults cache set req_cache() request promised.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_promise.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Perform request asynchronously using the promises package — req_perform_promise","text":"","code":"req_perform_promise(req, path = NULL, pool = NULL)"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_promise.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Perform request asynchronously using the promises package — req_perform_promise","text":"req httr2 request object. path Optionally, path save body response. useful large responses since avoids storing response memory. pool Optionally, curl pool made curl::new_pool(). Supply want override defaults total concurrent connections (100) concurrent connections per host (6).","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_promise.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Perform request asynchronously using the promises package — req_perform_promise","text":"promises::promise() object resolves response successful rejects errors thrown req_perform().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_promise.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Perform request asynchronously using the promises package — req_perform_promise","text":"","code":"if (FALSE) { # \\dontrun{ library(promises) request_base <- request(example_url()) |> req_url_path_append(\"delay\") p <- request_base |> req_url_path_append(2) |> req_perform_promise() # A promise object, not particularly useful on its own p # Use promise chaining functions to access results p %...>% resp_body_json() %...>% print() # Can run two requests at the same time p1 <- request_base |> req_url_path_append(2) |> req_perform_promise() p2 <- request_base |> req_url_path_append(1) |> req_perform_promise() p1 %...>% resp_url_path %...>% paste0(., \" finished\") %...>% print() p2 %...>% resp_url_path %...>% paste0(., \" finished\") %...>% print() # See the [promises package documentation](https://rstudio.github.io/promises/) # for more information on working with promises } # }"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_sequential.html","id":null,"dir":"Reference","previous_headings":"","what":"Perform multiple requests in sequence — req_perform_sequential","title":"Perform multiple requests in sequence — req_perform_sequential","text":"Given list requests, function performs turn, returning list responses. slower req_perform_parallel() fewer limitations.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_sequential.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Perform multiple requests in sequence — req_perform_sequential","text":"","code":"req_perform_sequential( reqs, paths = NULL, on_error = c(\"stop\", \"return\", \"continue\"), progress = TRUE )"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_sequential.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Perform multiple requests in sequence — req_perform_sequential","text":"reqs list requests. paths optional character vector paths, want download request bodies disk. supplied, must length reqs. on_error happen one requests fails? stop, default: stop iterating error. return: stop iterating, returning successful responses received far, well error object failed request. continue: continue iterating, recording errors result. progress Display progress bar? Use TRUE turn basic progress bar, use string give name, see progress_bars customise ways.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_sequential.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Perform multiple requests in sequence — req_perform_sequential","text":"list, length reqs, containing responses possibly error objects, on_error \"return\" \"continue\" one responses errors. on_error \"return\" errors ith request, ith element result error object, remaining elements NULL. on_error \"continue\", mix requests error objects. httr2 errors captured; see req_error() details.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_sequential.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Perform multiple requests in sequence — req_perform_sequential","text":"","code":"# One use of req_perform_sequential() is if the API allows you to request # data for multiple objects, you want data for more objects than can fit # in one request. req <- request(\"https://api.restful-api.dev/objects\") # Imagine we have 50 ids: ids <- sort(sample(100, 50)) # But the API only allows us to request 10 at time. So we first use split # and some modulo arithmetic magic to generate chunks of length 10 chunks <- unname(split(ids, (seq_along(ids) - 1) %/% 10)) # Then we use lapply to generate one request for each chunk: reqs <- chunks |> lapply(\\(idx) req |> req_url_query(id = idx, .multi = \"comma\")) # Then we can perform them all and get the results if (FALSE) { # \\dontrun{ resps <- reqs |> req_perform_sequential() resps_data(resps, \\(resp) resp_body_json(resp)) } # }"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_stream.html","id":null,"dir":"Reference","previous_headings":"","what":"Perform a request and handle data as it streams back — req_perform_stream","title":"Perform a request and handle data as it streams back — req_perform_stream","text":"preparing request, call req_perform_stream() perform request handle result streaming callback. useful streaming HTTP APIs potentially stream never ends. callback called result successful. need stream error response, can use req_error() suppress error handling body streamed .","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_stream.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Perform a request and handle data as it streams back — req_perform_stream","text":"","code":"req_perform_stream( req, callback, timeout_sec = Inf, buffer_kb = 64, round = c(\"byte\", \"line\") )"},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_stream.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Perform a request and handle data as it streams back — req_perform_stream","text":"req httr2 request object. callback single argument callback function. called repeatedly raw vector whenever least buffer_kb worth data process. must return TRUE continue streaming. timeout_sec Number seconds process stream . buffer_kb Buffer size, kilobytes. round raw vector sent callback rounded? Choose \"byte\", \"line\", supply function takes raw vector bytes returns locations possible cut points (integer() none).","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_stream.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Perform a request and handle data as it streams back — req_perform_stream","text":"HTTP response. body empty request successful (since callback function handled ). body contain HTTP response body request unsuccessful.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_perform_stream.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Perform a request and handle data as it streams back — req_perform_stream","text":"","code":"show_bytes <- function(x) { cat(\"Got \", length(x), \" bytes\\n\", sep = \"\") TRUE } resp <- request(example_url()) |> req_url_path(\"/stream-bytes/100000\") |> req_perform_stream(show_bytes, buffer_kb = 32) #> Got 32768 bytes #> Got 32768 bytes #> Got 32768 bytes #> Got 1696 bytes resp #> <httr2_response> #> GET http://127.0.0.1:36861/stream-bytes/100000 #> Status: 200 OK #> Content-Type: application/octet-stream #> Body: None"},{"path":"https://httr2.r-lib.org/dev/reference/req_progress.html","id":null,"dir":"Reference","previous_headings":"","what":"Add a progress bar to long downloads or uploads — req_progress","title":"Add a progress bar to long downloads or uploads — req_progress","text":"uploading downloading large file, often useful provide progress bar know long wait.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_progress.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Add a progress bar to long downloads or uploads — req_progress","text":"","code":"req_progress(req, type = c(\"down\", \"up\"))"},{"path":"https://httr2.r-lib.org/dev/reference/req_progress.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Add a progress bar to long downloads or uploads — req_progress","text":"req request. type Type progress display: either number bytes uploaded downloaded.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_progress.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Add a progress bar to long downloads or uploads — req_progress","text":"","code":"req <- request(\"https://r4ds.s3.us-west-2.amazonaws.com/seattle-library-checkouts.csv\") |> req_progress() if (FALSE) { # \\dontrun{ path <- tempfile() req |> req_perform(path = path) } # }"},{"path":"https://httr2.r-lib.org/dev/reference/req_proxy.html","id":null,"dir":"Reference","previous_headings":"","what":"Use a proxy for a request — req_proxy","title":"Use a proxy for a request — req_proxy","text":"Use proxy request","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_proxy.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Use a proxy for a request — req_proxy","text":"","code":"req_proxy( req, url, port = NULL, username = NULL, password = NULL, auth = \"basic\" )"},{"path":"https://httr2.r-lib.org/dev/reference/req_proxy.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Use a proxy for a request — req_proxy","text":"req httr2 request object. url, port Location proxy. username, password Login details proxy, needed. auth Type HTTP authentication use. one following: basic, digest, digest_ie, gssnegotiate, ntlm, .","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_proxy.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Use a proxy for a request — req_proxy","text":"","code":"# Proxy from https://www.proxynova.com/proxy-server-list/ if (FALSE) { # \\dontrun{ request(\"http://hadley.nz\") |> req_proxy(\"20.116.130.70\", 3128) |> req_perform() } # }"},{"path":"https://httr2.r-lib.org/dev/reference/req_retry.html","id":null,"dir":"Reference","previous_headings":"","what":"Control when a request will retry, and how long it will wait between tries — req_retry","title":"Control when a request will retry, and how long it will wait between tries — req_retry","text":"req_retry() alters req_perform() automatically retry case failure. activate , must specify either total number requests make max_tries total amount time spend max_seconds. req_perform() retry error \"transient\", .e. HTTP error can resolved waiting. default, 429 503 statuses treated transient, API wrapping transient status codes (conveys transient-ness property response), can override default is_transient. Additionally, set retry_on_failure = TRUE, request retry either HTTP request HTTP response complete successfully leading error curl, lower-level library httr2 uses perform HTTP request. occurs, example, wifi . bad idea immediately retry request, req_perform() wait little trying : response contains Retry-header, httr2 wait amount time specifies. API wrapping conveys information different header (property response) can override default behaviour retry_after. Otherwise, httr2 use \"truncated exponential backoff full jitter\", .e. wait random amount time one second 2 ^ tries seconds, capped 60 seconds. words, waits runif(1, 1, 2) seconds first failure, runif(1, 1, 4) second, runif(1, 1, 8) third, . prefer different strategy, can override default backoff.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_retry.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Control when a request will retry, and how long it will wait between tries — req_retry","text":"","code":"req_retry( req, max_tries = NULL, max_seconds = NULL, retry_on_failure = FALSE, is_transient = NULL, backoff = NULL, after = NULL )"},{"path":"https://httr2.r-lib.org/dev/reference/req_retry.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Control when a request will retry, and how long it will wait between tries — req_retry","text":"req httr2 request object. max_tries, max_seconds Cap maximum number attempts max_tries total elapsed time first request max_seconds. neither option supplied (default), req_perform() retry. max_tries total number attempts make, always greater one.` retry_on_failure Treat low-level failures transient errors, can retried. is_transient predicate function takes single argument (response) returns TRUE FALSE specifying whether response represents transient error. backoff function takes single argument (number failed attempts far) returns number seconds wait. function takes single argument (response) returns either number seconds wait NULL, indicates precise wait time available backoff strategy used instead..","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_retry.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Control when a request will retry, and how long it will wait between tries — req_retry","text":"modified HTTP request.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_retry.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Control when a request will retry, and how long it will wait between tries — req_retry","text":"","code":"# google APIs assume that a 500 is also a transient error request(\"http://google.com\") |> req_retry(is_transient = \\(resp) resp_status(resp) %in% c(429, 500, 503)) #> <httr2_request> #> GET http://google.com #> Body: empty #> Policies: #> • retry_on_failure: FALSE #> • retry_is_transient: a function # use a constant 10s delay after every failure request(\"http://example.com\") |> req_retry(backoff = ~10) #> <httr2_request> #> GET http://example.com #> Body: empty #> Policies: #> • retry_on_failure: FALSE #> • retry_backoff: a <rlang_lambda_function> object # When rate-limited, GitHub's API returns a 403 with # `X-RateLimit-Remaining: 0` and an Unix time stored in the # `X-RateLimit-Reset` header. This takes a bit more work to handle: github_is_transient <- function(resp) { resp_status(resp) == 403 && identical(resp_header(resp, \"X-RateLimit-Remaining\"), \"0\") } github_after <- function(resp) { time <- as.numeric(resp_header(resp, \"X-RateLimit-Reset\")) time - unclass(Sys.time()) } request(\"http://api.github.com\") |> req_retry( is_transient = github_is_transient, after = github_after ) #> <httr2_request> #> GET http://api.github.com #> Body: empty #> Policies: #> • retry_on_failure: FALSE #> • retry_is_transient: a function #> • retry_after: a function"},{"path":"https://httr2.r-lib.org/dev/reference/req_template.html","id":null,"dir":"Reference","previous_headings":"","what":"Set request method/path from a template — req_template","title":"Set request method/path from a template — req_template","text":"Many APIs document methods lightweight template mechanism looks like GET /user/{user} POST /organisation/:org. function makes easy copy paste snippets retrieve template variables either function arguments current environment. req_template() append existing path can set base url initial request(). means generally want avoid multiple req_template() calls request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_template.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Set request method/path from a template — req_template","text":"","code":"req_template(req, template, ..., .env = parent.frame())"},{"path":"https://httr2.r-lib.org/dev/reference/req_template.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Set request method/path from a template — req_template","text":"req httr2 request object. template template string consists optional HTTP method path containing variables labelled like either :foo {foo}. ... Template variables. .env Environment look template variables found .... Expert use .","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_template.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Set request method/path from a template — req_template","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_template.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Set request method/path from a template — req_template","text":"","code":"httpbin <- request(example_url()) # You can supply template parameters in `...` httpbin |> req_template(\"GET /bytes/{n}\", n = 100) #> <httr2_request> #> GET http://127.0.0.1:36861/bytes/100 #> Body: empty # or you retrieve from the current environment n <- 200 httpbin |> req_template(\"GET /bytes/{n}\") #> <httr2_request> #> GET http://127.0.0.1:36861/bytes/200 #> Body: empty # Existing path is preserved: httpbin_test <- request(example_url()) |> req_url_path(\"/test\") name <- \"id\" value <- \"a3fWa\" httpbin_test |> req_template(\"GET /set/{name}/{value}\") #> <httr2_request> #> GET http://127.0.0.1:36861/test/set/id/a3fWa #> Body: empty"},{"path":"https://httr2.r-lib.org/dev/reference/req_throttle.html","id":null,"dir":"Reference","previous_headings":"","what":"Rate limit a request by automatically adding a delay — req_throttle","title":"Rate limit a request by automatically adding a delay — req_throttle","text":"Use req_throttle() ensure repeated calls req_perform() never exceed specified rate.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_throttle.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Rate limit a request by automatically adding a delay — req_throttle","text":"","code":"req_throttle(req, rate, realm = NULL)"},{"path":"https://httr2.r-lib.org/dev/reference/req_throttle.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Rate limit a request by automatically adding a delay — req_throttle","text":"req httr2 request object. rate Maximum rate, .e. maximum number requests per second. Usually easiest expressed fraction, number_of_requests / number_of_seconds, e.g. 15 requests per minute 15 / 60. realm string uniquely identifies throttle pool use (throttling limits always apply per pool). supplied, defaults hostname request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_throttle.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Rate limit a request by automatically adding a delay — req_throttle","text":"modified HTTP request.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_throttle.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Rate limit a request by automatically adding a delay — req_throttle","text":"","code":"# Ensure we never send more than 30 requests a minute req <- request(example_url()) |> req_throttle(rate = 30 / 60) resp <- req_perform(req) throttle_status() #> realm last_request #> 1 127.0.0.1 2024-10-23 22:10:51 resp <- req_perform(req) #> Waiting 2s for throttling delay ■■■■■■■■■■■■■■■ #> Waiting 2s for throttling delay ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ throttle_status() #> realm last_request #> 1 127.0.0.1 2024-10-23 22:10:53"},{"path":"https://httr2.r-lib.org/dev/reference/req_timeout.html","id":null,"dir":"Reference","previous_headings":"","what":"Set time limit for a request — req_timeout","title":"Set time limit for a request — req_timeout","text":"error thrown request complete time limit.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_timeout.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Set time limit for a request — req_timeout","text":"","code":"req_timeout(req, seconds)"},{"path":"https://httr2.r-lib.org/dev/reference/req_timeout.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Set time limit for a request — req_timeout","text":"req httr2 request object. seconds Maximum number seconds wait","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_timeout.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Set time limit for a request — req_timeout","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_timeout.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Set time limit for a request — req_timeout","text":"","code":"# Give up after at most 10 seconds request(\"http://example.com\") |> req_timeout(10) #> <httr2_request> #> GET http://example.com #> Body: empty #> Options: #> • timeout_ms: 10000 #> • connecttimeout: 0"},{"path":"https://httr2.r-lib.org/dev/reference/req_url.html","id":null,"dir":"Reference","previous_headings":"","what":"Modify request URL — req_url","title":"Modify request URL — req_url","text":"req_url() replaces entire url req_url_query() modifies components query req_url_path() modifies path req_url_path_append() adds path","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_url.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Modify request URL — req_url","text":"","code":"req_url(req, url) req_url_query(.req, ..., .multi = c(\"error\", \"comma\", \"pipe\", \"explode\")) req_url_path(req, ...) req_url_path_append(req, ...)"},{"path":"https://httr2.r-lib.org/dev/reference/req_url.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Modify request URL — req_url","text":"req, .req httr2 request object. url New URL; completely replaces existing. ... req_url_query(): <dynamic-dots> Name-value pairs define query parameters. value must either atomic vector NULL (removes corresponding parameters). want opt escaping, wrap strings (). req_url_path() req_url_path_append(): sequence path components combined /. .multi Controls happens element ... vector containing multiple values: \"error\", default, throws error. \"comma\", separates values ,, e.g. ?x=1,2. \"pipe\", separates values |, e.g. ?x=1|2. \"explode\", turns element parameter, e.g. ?x=1&x=2. none functions work, can alternatively supply function takes character vector returns string.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_url.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Modify request URL — req_url","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_url.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Modify request URL — req_url","text":"","code":"req <- request(\"http://example.com\") # Change url components req |> req_url_path_append(\"a\") |> req_url_path_append(\"b\") |> req_url_path_append(\"search.html\") |> req_url_query(q = \"the cool ice\") #> <httr2_request> #> GET http://example.com/a/b/search.html?q=the%20cool%20ice #> Body: empty # Change complete url req |> req_url(\"http://google.com\") #> <httr2_request> #> GET http://google.com #> Body: empty # Use .multi to control what happens with vector parameters: req |> req_url_query(id = 100:105, .multi = \"comma\") #> <httr2_request> #> GET http://example.com?id=100,101,102,103,104,105 #> Body: empty req |> req_url_query(id = 100:105, .multi = \"explode\") #> <httr2_request> #> GET http://example.com?id=100&id=101&id=102&id=103&id=104&id=105 #> Body: empty # If you have query parameters in a list, use !!! params <- list(a = \"1\", b = \"2\") req |> req_url_query(!!!params, c = \"3\") #> <httr2_request> #> GET http://example.com?a=1&b=2&c=3 #> Body: empty"},{"path":"https://httr2.r-lib.org/dev/reference/req_user_agent.html","id":null,"dir":"Reference","previous_headings":"","what":"Set user-agent for a request — req_user_agent","title":"Set user-agent for a request — req_user_agent","text":"overrides default user-agent set httr2 includes version numbers httr2, curl package, libcurl.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_user_agent.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Set user-agent for a request — req_user_agent","text":"","code":"req_user_agent(req, string = NULL)"},{"path":"https://httr2.r-lib.org/dev/reference/req_user_agent.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Set user-agent for a request — req_user_agent","text":"req httr2 request object. string String sent User-Agent header. NULL, user default.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_user_agent.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Set user-agent for a request — req_user_agent","text":"modified HTTP request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_user_agent.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Set user-agent for a request — req_user_agent","text":"","code":"# Default user-agent: request(\"http://example.com\") |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> request(\"http://example.com\") |> req_user_agent(\"MyString\") |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: MyString #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #> # If you're wrapping in an API in a package, it's polite to set the # user agent to identify your package. request(\"http://example.com\") |> req_user_agent(\"MyPackage (http://mypackage.com)\") |> req_dry_run() #> GET / HTTP/1.1 #> Host: example.com #> User-Agent: MyPackage (http://mypackage.com) #> Accept: */* #> Accept-Encoding: deflate, gzip, br, zstd #>"},{"path":"https://httr2.r-lib.org/dev/reference/req_verbose.html","id":null,"dir":"Reference","previous_headings":"","what":"Show extra output when request is performed — req_verbose","title":"Show extra output when request is performed — req_verbose","text":"req_verbose() uses following prefixes distinguish different components HTTP requests responses: * informative curl messages -> request headers >> request body <- response headers << response body","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_verbose.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Show extra output when request is performed — req_verbose","text":"","code":"req_verbose( req, header_req = TRUE, header_resp = TRUE, body_req = FALSE, body_resp = FALSE, info = FALSE, redact_headers = TRUE )"},{"path":"https://httr2.r-lib.org/dev/reference/req_verbose.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Show extra output when request is performed — req_verbose","text":"req httr2 request object. header_req, header_resp Show request/response headers? body_req, body_resp request/response bodies? response body compressed, show number bytes received \"chunk\". info Show informational text curl? mainly useful debugging https auth problems, disabled default. redact_headers Redact confidential data headers? Currently redacts contents Authorization header prevent accidentally leaking credentials debugging/reprexing.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/req_verbose.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Show extra output when request is performed — req_verbose","text":"modified HTTP request.","code":""},{"path":[]},{"path":"https://httr2.r-lib.org/dev/reference/req_verbose.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Show extra output when request is performed — req_verbose","text":"","code":"# Use `req_verbose()` to see the headers that are sent back and forth when # making a request resp <- request(\"https://httr2.r-lib.org\") |> req_verbose() |> req_perform() #> -> GET / HTTP/2 #> -> Host: httr2.r-lib.org #> -> user-agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> -> accept: */* #> -> accept-encoding: deflate, gzip, br, zstd #> -> #> <- HTTP/2 200 #> <- server: GitHub.com #> <- content-type: text/html; charset=utf-8 #> <- last-modified: Wed, 23 Oct 2024 18:14:33 GMT #> <- access-control-allow-origin: * #> <- etag: W/\"67193d09-4983\" #> <- expires: Wed, 23 Oct 2024 22:20:36 GMT #> <- cache-control: max-age=600 #> <- content-encoding: gzip #> <- x-proxy-cache: MISS #> <- x-github-request-id: 97CB:344448:46EAD9:50CD81:67197452 #> <- accept-ranges: bytes #> <- date: Wed, 23 Oct 2024 22:10:54 GMT #> <- via: 1.1 varnish #> <- age: 19 #> <- x-served-by: cache-chi-kigq8000144-CHI #> <- x-cache: HIT #> <- x-cache-hits: 1 #> <- x-timer: S1729721455.757211,VS0,VE2 #> <- vary: Accept-Encoding #> <- x-fastly-request-id: df6ed6484805901140ed47f3a96478b834849625 #> <- content-length: 4636 #> <- # Or use one of the convenient shortcuts: resp <- request(\"https://httr2.r-lib.org\") |> req_perform(verbosity = 1) #> -> GET / HTTP/2 #> -> Host: httr2.r-lib.org #> -> user-agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> -> accept: */* #> -> accept-encoding: deflate, gzip, br, zstd #> -> #> <- HTTP/2 200 #> <- server: GitHub.com #> <- content-type: text/html; charset=utf-8 #> <- last-modified: Wed, 23 Oct 2024 18:14:33 GMT #> <- access-control-allow-origin: * #> <- etag: W/\"67193d09-4983\" #> <- expires: Wed, 23 Oct 2024 22:20:36 GMT #> <- cache-control: max-age=600 #> <- content-encoding: gzip #> <- x-proxy-cache: MISS #> <- x-github-request-id: 97CB:344448:46EAD9:50CD81:67197452 #> <- accept-ranges: bytes #> <- date: Wed, 23 Oct 2024 22:10:54 GMT #> <- via: 1.1 varnish #> <- age: 19 #> <- x-served-by: cache-chi-kigq8000144-CHI #> <- x-cache: HIT #> <- x-cache-hits: 2 #> <- x-timer: S1729721455.769820,VS0,VE0 #> <- vary: Accept-Encoding #> <- x-fastly-request-id: 373195e189b1d5ab3755cd0498a0350712e279fb #> <- content-length: 4636 #> <-"},{"path":"https://httr2.r-lib.org/dev/reference/request.html","id":null,"dir":"Reference","previous_headings":"","what":"Create a new HTTP request — request","title":"Create a new HTTP request — request","text":"three steps needed perform HTTP request httr2: Create request object request(url) (function). Define behaviour req_ functions, e.g.: req_headers() set header values. req_url_path() friends modify url. req_body_json() friends add body. req_auth_basic() perform basic HTTP authentication. req_oauth_auth_code() use OAuth auth code flow. Perform request fetch response req_perform().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/request.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Create a new HTTP request — request","text":"","code":"request(base_url)"},{"path":"https://httr2.r-lib.org/dev/reference/request.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Create a new HTTP request — request","text":"base_url Base URL request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/request.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Create a new HTTP request — request","text":"HTTP request: S3 list class httr2_request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/request.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Create a new HTTP request — request","text":"","code":"request(\"http://r-project.org\") #> <httr2_request> #> GET http://r-project.org #> Body: empty"},{"path":"https://httr2.r-lib.org/dev/reference/resp_body_raw.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract body from response — resp_body_raw","title":"Extract body from response — resp_body_raw","text":"resp_body_raw() returns raw bytes. resp_body_string() returns UTF-8 string. resp_body_json() returns parsed JSON. resp_body_html() returns parsed HTML. resp_body_xml() returns parsed XML. resp_has_body() returns TRUE response body. resp_body_json() resp_body_xml() check content-type header correct; server returns incorrect type can suppress check check_type = FALSE. two functions also cache parsed object second subsequent calls low-cost.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_body_raw.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract body from response — resp_body_raw","text":"","code":"resp_body_raw(resp) resp_has_body(resp) resp_body_string(resp, encoding = NULL) resp_body_json(resp, check_type = TRUE, simplifyVector = FALSE, ...) resp_body_html(resp, check_type = TRUE, ...) resp_body_xml(resp, check_type = TRUE, ...)"},{"path":"https://httr2.r-lib.org/dev/reference/resp_body_raw.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract body from response — resp_body_raw","text":"resp httr2 response object, created req_perform(). encoding Character encoding body text. specified, use encoding specified content-type, falling back UTF-8 warning found. resulting string always re-encoded UTF-8. check_type Check response expected content type? Set FALSE suppress automated check simplifyVector JSON arrays containing primitives (.e. booleans, numbers, strings) caused atomic vectors? ... arguments passed jsonlite::fromJSON() xml2::read_xml() respectively.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_body_raw.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract body from response — resp_body_raw","text":"resp_body_raw() returns raw vector. resp_body_string() returns string. resp_body_json() returns NULL, atomic vector, list. resp_body_html() resp_body_xml() return xml2::xml_document","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_body_raw.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract body from response — resp_body_raw","text":"","code":"resp <- request(\"https://httr2.r-lib.org\") |> req_perform() resp #> <httr2_response> #> GET https://httr2.r-lib.org/ #> Status: 200 OK #> Content-Type: text/html #> Body: In memory (18819 bytes) resp |> resp_has_body() #> [1] TRUE resp |> resp_body_raw() #> [1] 3c 21 44 4f 43 54 59 50 45 20 68 74 6d 6c 3e 0a 3c 21 2d 2d 20 47 #> [23] 65 6e 65 72 61 74 65 64 20 62 79 20 70 6b 67 64 6f 77 6e 3a 20 64 #> [45] 6f 20 6e 6f 74 20 65 64 69 74 20 62 79 20 68 61 6e 64 20 2d 2d 3e #> [67] 3c 68 74 6d 6c 20 6c 61 6e 67 3d 22 65 6e 22 3e 0a 3c 68 65 61 64 #> [89] 3e 0a 3c 6d 65 74 61 20 68 74 74 70 2d 65 71 75 69 76 3d 22 43 6f #> [111] 6e 74 65 6e 74 2d 54 79 70 65 22 20 63 6f 6e 74 65 6e 74 3d 22 74 #> [133] 65 78 74 2f 68 74 6d 6c 3b 20 63 68 61 72 73 65 74 3d 55 54 46 2d #> [155] 38 22 3e 0a 3c 6d 65 74 61 20 63 68 61 72 73 65 74 3d 22 75 74 66 #> [177] 2d 38 22 3e 0a 3c 6d 65 74 61 20 68 74 74 70 2d 65 71 75 69 76 3d #> [199] 22 58 2d 55 41 2d 43 6f 6d 70 61 74 69 62 6c 65 22 20 63 6f 6e 74 #> [221] 65 6e 74 3d 22 49 45 3d 65 64 67 65 22 3e 0a 3c 6d 65 74 61 20 6e #> [243] 61 6d 65 3d 22 76 69 65 77 70 6f 72 74 22 20 63 6f 6e 74 65 6e 74 #> [265] 3d 22 77 69 64 74 68 3d 64 65 76 69 63 65 2d 77 69 64 74 68 2c 20 #> [287] 69 6e 69 74 69 61 6c 2d 73 63 61 6c 65 3d 31 2c 20 73 68 72 69 6e #> [309] 6b 2d 74 6f 2d 66 69 74 3d 6e 6f 22 3e 0a 3c 74 69 74 6c 65 3e 50 #> [331] 65 72 66 6f 72 6d 20 48 54 54 50 20 52 65 71 75 65 73 74 73 20 61 #> [353] 6e 64 20 50 72 6f 63 65 73 73 20 74 68 65 20 52 65 73 70 6f 6e 73 #> [375] 65 73 20 e2 80 a2 20 68 74 74 72 32 3c 2f 74 69 74 6c 65 3e 0a 3c #> [397] 21 2d 2d 20 66 61 76 69 63 6f 6e 73 20 2d 2d 3e 3c 6c 69 6e 6b 20 #> [419] 72 65 6c 3d 22 69 63 6f 6e 22 20 74 79 70 65 3d 22 69 6d 61 67 65 #> [441] 2f 70 6e 67 22 20 73 69 7a 65 73 3d 22 31 36 78 31 36 22 20 68 72 #> [463] 65 66 3d 22 66 61 76 69 63 6f 6e 2d 31 36 78 31 36 2e 70 6e 67 22 #> [485] 3e 0a 3c 6c 69 6e 6b 20 72 65 6c 3d 22 69 63 6f 6e 22 20 74 79 70 #> [507] 65 3d 22 69 6d 61 67 65 2f 70 6e 67 22 20 73 69 7a 65 73 3d 22 33 #> [529] 32 78 33 32 22 20 68 72 65 66 3d 22 66 61 76 69 63 6f 6e 2d 33 32 #> [551] 78 33 32 2e 70 6e 67 22 3e 0a 3c 6c 69 6e 6b 20 72 65 6c 3d 22 61 #> [573] 70 70 6c 65 2d 74 6f 75 63 68 2d 69 63 6f 6e 22 20 74 79 70 65 3d #> [595] 22 69 6d 61 67 65 2f 70 6e 67 22 20 73 69 7a 65 73 3d 22 31 38 30 #> [617] 78 31 38 30 22 20 68 72 65 66 3d 22 61 70 70 6c 65 2d 74 6f 75 63 #> [639] 68 2d 69 63 6f 6e 2e 70 6e 67 22 3e 0a 3c 6c 69 6e 6b 20 72 65 6c #> [661] 3d 22 61 70 70 6c 65 2d 74 6f 75 63 68 2d 69 63 6f 6e 22 20 74 79 #> [683] 70 65 3d 22 69 6d 61 67 65 2f 70 6e 67 22 20 73 69 7a 65 73 3d 22 #> [705] 31 32 30 78 31 32 30 22 20 68 72 65 66 3d 22 61 70 70 6c 65 2d 74 #> [727] 6f 75 63 68 2d 69 63 6f 6e 2d 31 32 30 78 31 32 30 2e 70 6e 67 22 #> [749] 3e 0a 3c 6c 69 6e 6b 20 72 65 6c 3d 22 61 70 70 6c 65 2d 74 6f 75 #> [771] 63 68 2d 69 63 6f 6e 22 20 74 79 70 65 3d 22 69 6d 61 67 65 2f 70 #> [793] 6e 67 22 20 73 69 7a 65 73 3d 22 37 36 78 37 36 22 20 68 72 65 66 #> [815] 3d 22 61 70 70 6c 65 2d 74 6f 75 63 68 2d 69 63 6f 6e 2d 37 36 78 #> [837] 37 36 2e 70 6e 67 22 3e 0a 3c 6c 69 6e 6b 20 72 65 6c 3d 22 61 70 #> [859] 70 6c 65 2d 74 6f 75 63 68 2d 69 63 6f 6e 22 20 74 79 70 65 3d 22 #> [881] 69 6d 61 67 65 2f 70 6e 67 22 20 73 69 7a 65 73 3d 22 36 30 78 36 #> [903] 30 22 20 68 72 65 66 3d 22 61 70 70 6c 65 2d 74 6f 75 63 68 2d 69 #> [925] 63 6f 6e 2d 36 30 78 36 30 2e 70 6e 67 22 3e 0a 3c 73 63 72 69 70 #> [947] 74 20 73 72 63 3d 22 64 65 70 73 2f 6a 71 75 65 72 79 2d 33 2e 36 #> [969] 2e 30 2f 6a 71 75 65 72 79 2d 33 2e 36 2e 30 2e 6d 69 6e 2e 6a 73 #> [991] 22 3e 3c 2f 73 63 72 69 70 74 3e 3c 6d 65 74 61 20 6e 61 6d 65 3d #> [1013] 22 76 69 65 77 70 6f 72 74 22 20 63 6f 6e 74 65 6e 74 3d 22 77 69 #> [1035] 64 74 68 3d 64 65 76 69 63 65 2d 77 69 64 74 68 2c 20 69 6e 69 74 #> [1057] 69 61 6c 2d 73 63 61 6c 65 3d 31 2c 20 73 68 72 69 6e 6b 2d 74 6f #> [1079] 2d 66 69 74 3d 6e 6f 22 3e 0a 3c 6c 69 6e 6b 20 68 72 65 66 3d 22 #> [1101] 64 65 70 73 2f 62 6f 6f 74 73 74 72 61 70 2d 35 2e 33 2e 31 2f 62 #> [1123] 6f 6f 74 73 74 72 61 70 2e 6d 69 6e 2e 63 73 73 22 20 72 65 6c 3d #> [1145] 22 73 74 79 6c 65 73 68 65 65 74 22 3e 0a 3c 73 63 72 69 70 74 20 #> [1167] 73 72 63 3d 22 64 65 70 73 2f 62 6f 6f 74 73 74 72 61 70 2d 35 2e #> [1189] 33 2e 31 2f 62 6f 6f 74 73 74 72 61 70 2e 62 75 6e 64 6c 65 2e 6d #> [1211] 69 6e 2e 6a 73 22 3e 3c 2f 73 63 72 69 70 74 3e 3c 6c 69 6e 6b 20 #> [1233] 68 72 65 66 3d 22 64 65 70 73 2f 53 6f 75 72 63 65 5f 53 61 6e 73 #> [1255] 5f 50 72 6f 2d 30 2e 34 2e 39 2f 66 6f 6e 74 2e 63 73 73 22 20 72 #> [1277] 65 6c 3d 22 73 74 79 6c 65 73 68 65 65 74 22 3e 0a 3c 6c 69 6e 6b #> [1299] 20 68 72 65 66 3d 22 64 65 70 73 2f 53 6f 75 72 63 65 5f 43 6f 64 #> [1321] 65 5f 50 72 6f 2d 30 2e 34 2e 39 2f 66 6f 6e 74 2e 63 73 73 22 20 #> [1343] 72 65 6c 3d 22 73 74 79 6c 65 73 68 65 65 74 22 3e 0a 3c 6c 69 6e #> [1365] 6b 20 68 72 65 66 3d 22 64 65 70 73 2f 66 6f 6e 74 2d 61 77 65 73 #> [1387] 6f 6d 65 2d 36 2e 34 2e 32 2f 63 73 73 2f 61 6c 6c 2e 6d 69 6e 2e #> [1409] 63 73 73 22 20 72 65 6c 3d 22 73 74 79 6c 65 73 68 65 65 74 22 3e #> [1431] 0a 3c 6c 69 6e 6b 20 68 72 65 66 3d 22 64 65 70 73 2f 66 6f 6e 74 #> [1453] 2d 61 77 65 73 6f 6d 65 2d 36 2e 34 2e 32 2f 63 73 73 2f 76 34 2d #> [1475] 73 68 69 6d 73 2e 6d 69 6e 2e 63 73 73 22 20 72 65 6c 3d 22 73 74 #> [1497] 79 6c 65 73 68 65 65 74 22 3e 0a 3c 73 63 72 69 70 74 20 73 72 63 #> [1519] 3d 22 64 65 70 73 2f 68 65 61 64 72 6f 6f 6d 2d 30 2e 31 31 2e 30 #> [1541] 2f 68 65 61 64 72 6f 6f 6d 2e 6d 69 6e 2e 6a 73 22 3e 3c 2f 73 63 #> [1563] 72 69 70 74 3e 3c 73 63 72 69 70 74 20 73 72 63 3d 22 64 65 70 73 #> [1585] 2f 68 65 61 64 72 6f 6f 6d 2d 30 2e 31 31 2e 30 2f 6a 51 75 65 72 #> [1607] 79 2e 68 65 61 64 72 6f 6f 6d 2e 6d 69 6e 2e 6a 73 22 3e 3c 2f 73 #> [1629] 63 72 69 70 74 3e 3c 73 63 72 69 70 74 20 73 72 63 3d 22 64 65 70 #> [1651] 73 2f 62 6f 6f 74 73 74 72 61 70 2d 74 6f 63 2d 31 2e 30 2e 31 2f #> [1673] 62 6f 6f 74 73 74 72 61 70 2d 74 6f 63 2e 6d 69 6e 2e 6a 73 22 3e #> [1695] 3c 2f 73 63 72 69 70 74 3e 3c 73 63 72 69 70 74 20 73 72 63 3d 22 #> [1717] 64 65 70 73 2f 63 6c 69 70 62 6f 61 72 64 2e 6a 73 2d 32 2e 30 2e #> [1739] 31 31 2f 63 6c 69 70 62 6f 61 72 64 2e 6d 69 6e 2e 6a 73 22 3e 3c #> [1761] 2f 73 63 72 69 70 74 3e 3c 73 63 72 69 70 74 20 73 72 63 3d 22 64 #> [1783] 65 70 73 2f 73 65 61 72 63 68 2d 31 2e 30 2e 30 2f 61 75 74 6f 63 #> [1805] 6f 6d 70 6c 65 74 65 2e 6a 71 75 65 72 79 2e 6d 69 6e 2e 6a 73 22 #> [1827] 3e 3c 2f 73 63 72 69 70 74 3e 3c 73 63 72 69 70 74 20 73 72 63 3d #> [1849] 22 64 65 70 73 2f 73 65 61 72 63 68 2d 31 2e 30 2e 30 2f 66 75 73 #> [1871] 65 2e 6d 69 6e 2e 6a 73 22 3e 3c 2f 73 63 72 69 70 74 3e 3c 73 63 #> [1893] 72 69 70 74 20 73 72 63 3d 22 64 65 70 73 2f 73 65 61 72 63 68 2d #> [1915] 31 2e 30 2e 30 2f 6d 61 72 6b 2e 6d 69 6e 2e 6a 73 22 3e 3c 2f 73 #> [1937] 63 72 69 70 74 3e 3c 21 2d 2d 20 70 6b 67 64 6f 77 6e 20 2d 2d 3e #> [1959] 3c 73 63 72 69 70 74 20 73 72 63 3d 22 70 6b 67 64 6f 77 6e 2e 6a #> [1981] 73 22 3e 3c 2f 73 63 72 69 70 74 3e 3c 6d 65 74 61 20 70 72 6f 70 #> [2003] 65 72 74 79 3d 22 6f 67 3a 74 69 74 6c 65 22 20 63 6f 6e 74 65 6e #> [2025] 74 3d 22 50 65 72 66 6f 72 6d 20 48 54 54 50 20 52 65 71 75 65 73 #> [2047] 74 73 20 61 6e 64 20 50 72 6f 63 65 73 73 20 74 68 65 20 52 65 73 #> [2069] 70 6f 6e 73 65 73 22 3e 0a 3c 6d 65 74 61 20 6e 61 6d 65 3d 22 64 #> [2091] 65 73 63 72 69 70 74 69 6f 6e 22 20 63 6f 6e 74 65 6e 74 3d 22 54 #> [2113] 6f 6f 6c 73 20 66 6f 72 20 63 72 65 61 74 69 6e 67 20 61 6e 64 20 #> [2135] 6d 6f 64 69 66 79 69 6e 67 20 48 54 54 50 20 72 65 71 75 65 73 74 #> [2157] 73 2c 20 74 68 65 6e 20 70 65 72 66 6f 72 6d 69 6e 67 20 74 68 65 #> [2179] 6d 20 61 6e 64 20 70 72 6f 63 65 73 73 69 6e 67 20 74 68 65 20 72 #> [2201] 65 73 75 6c 74 73 2e 20 68 74 74 72 32 20 69 73 20 61 20 6d 6f 64 #> [2223] 65 72 6e 20 72 65 2d 69 6d 61 67 69 6e 69 6e 67 20 6f 66 20 68 74 #> [2245] 74 72 20 74 68 61 74 20 75 73 65 73 20 61 20 70 69 70 65 2d 62 61 #> [2267] 73 65 64 20 69 6e 74 65 72 66 61 63 65 20 61 6e 64 20 73 6f 6c 76 #> [2289] 65 73 20 6d 6f 72 65 20 6f 66 20 74 68 65 20 70 72 6f 62 6c 65 6d #> [2311] 73 20 74 68 61 74 20 41 50 49 20 77 72 61 70 70 69 6e 67 20 70 61 #> [2333] 63 6b 61 67 65 73 20 66 61 63 65 2e 22 3e 0a 3c 6d 65 74 61 20 70 #> [2355] 72 6f 70 65 72 74 79 3d 22 6f 67 3a 64 65 73 63 72 69 70 74 69 6f #> [2377] 6e 22 20 63 6f 6e 74 65 6e 74 3d 22 54 6f 6f 6c 73 20 66 6f 72 20 #> [2399] 63 72 65 61 74 69 6e 67 20 61 6e 64 20 6d 6f 64 69 66 79 69 6e 67 #> [2421] 20 48 54 54 50 20 72 65 71 75 65 73 74 73 2c 20 74 68 65 6e 20 70 #> [2443] 65 72 66 6f 72 6d 69 6e 67 20 74 68 65 6d 20 61 6e 64 20 70 72 6f #> [2465] 63 65 73 73 69 6e 67 20 74 68 65 20 72 65 73 75 6c 74 73 2e 20 68 #> [2487] 74 74 72 32 20 69 73 20 61 20 6d 6f 64 65 72 6e 20 72 65 2d 69 6d #> [2509] 61 67 69 6e 69 6e 67 20 6f 66 20 68 74 74 72 20 74 68 61 74 20 75 #> [2531] 73 65 73 20 61 20 70 69 70 65 2d 62 61 73 65 64 20 69 6e 74 65 72 #> [2553] 66 61 63 65 20 61 6e 64 20 73 6f 6c 76 65 73 20 6d 6f 72 65 20 6f #> [2575] 66 20 74 68 65 20 70 72 6f 62 6c 65 6d 73 20 74 68 61 74 20 41 50 #> [2597] 49 20 77 72 61 70 70 69 6e 67 20 70 61 63 6b 61 67 65 73 20 66 61 #> [2619] 63 65 2e 22 3e 0a 3c 6d 65 74 61 20 70 72 6f 70 65 72 74 79 3d 22 #> [2641] 6f 67 3a 69 6d 61 67 65 22 20 63 6f 6e 74 65 6e 74 3d 22 68 74 74 #> [2663] 70 73 3a 2f 2f 68 74 74 72 32 2e 72 2d 6c 69 62 2e 6f 72 67 2f 6c #> [2685] 6f 67 6f 2e 70 6e 67 22 3e 0a 3c 73 63 72 69 70 74 20 64 65 66 65 #> [2707] 72 20 64 61 74 61 2d 64 6f 6d 61 69 6e 3d 22 68 74 74 72 32 2e 72 #> [2729] 2d 6c 69 62 2e 6f 72 67 2c 61 6c 6c 2e 74 69 64 79 76 65 72 73 65 #> [2751] 2e 6f 72 67 22 20 73 72 63 3d 22 68 74 74 70 73 3a 2f 2f 70 6c 61 #> [2773] 75 73 69 62 6c 65 2e 69 6f 2f 6a 73 2f 70 6c 61 75 73 69 62 6c 65 #> [2795] 2e 6a 73 22 3e 3c 2f 73 63 72 69 70 74 3e 0a 3c 2f 68 65 61 64 3e #> [2817] 0a 3c 62 6f 64 79 3e 0a 20 20 20 20 3c 61 20 68 72 65 66 3d 22 23 #> [2839] 63 6f 6e 74 61 69 6e 65 72 22 20 63 6c 61 73 73 3d 22 76 69 73 75 #> [2861] 61 6c 6c 79 2d 68 69 64 64 65 6e 2d 66 6f 63 75 73 61 62 6c 65 22 #> [2883] 3e 53 6b 69 70 20 74 6f 20 63 6f 6e 74 65 6e 74 3c 2f 61 3e 0a 0a #> [2905] 0a 20 20 20 20 3c 6e 61 76 20 63 6c 61 73 73 3d 22 6e 61 76 62 61 #> [2927] 72 20 6e 61 76 62 61 72 2d 65 78 70 61 6e 64 2d 6c 67 20 66 69 78 #> [2949] 65 64 2d 74 6f 70 20 62 67 2d 6e 6f 6e 65 22 20 64 61 74 61 2d 62 #> [2971] 73 2d 74 68 65 6d 65 3d 22 6c 69 67 68 74 22 20 61 72 69 61 2d 6c #> [2993] 61 62 65 6c 3d 22 53 69 74 65 20 6e 61 76 69 67 61 74 69 6f 6e 22 #> [3015] 3e 3c 64 69 76 20 63 6c 61 73 73 3d 22 63 6f 6e 74 61 69 6e 65 72 #> [3037] 22 3e 0a 0a 20 20 20 20 3c 61 20 63 6c 61 73 73 3d 22 6e 61 76 62 #> [3059] 61 72 2d 62 72 61 6e 64 20 6d 65 2d 32 22 20 68 72 65 66 3d 22 69 #> [3081] 6e 64 65 78 2e 68 74 6d 6c 22 3e 68 74 74 72 32 3c 2f 61 3e 0a 0a #> [3103] 20 20 20 20 3c 73 6d 61 6c 6c 20 63 6c 61 73 73 3d 22 6e 61 76 2d #> [3125] 74 65 78 74 20 74 65 78 74 2d 6d 75 74 65 64 20 6d 65 2d 61 75 74 #> [3147] 6f 22 20 64 61 74 61 2d 62 73 2d 74 6f 67 67 6c 65 3d 22 74 6f 6f #> [3169] 6c 74 69 70 22 20 64 61 74 61 2d 62 73 2d 70 6c 61 63 65 6d 65 6e #> [3191] 74 3d 22 62 6f 74 74 6f 6d 22 20 74 69 74 6c 65 3d 22 52 65 6c 65 #> [3213] 61 73 65 64 20 76 65 72 73 69 6f 6e 22 3e 31 2e 30 2e 35 3c 2f 73 #> [3235] 6d 61 6c 6c 3e 0a 0a 0a 20 20 20 20 3c 62 75 74 74 6f 6e 20 63 6c #> [3257] 61 73 73 3d 22 6e 61 76 62 61 72 2d 74 6f 67 67 6c 65 72 22 20 74 #> [3279] 79 70 65 3d 22 62 75 74 74 6f 6e 22 20 64 61 74 61 2d 62 73 2d 74 #> [3301] 6f 67 67 6c 65 3d 22 63 6f 6c 6c 61 70 73 65 22 20 64 61 74 61 2d #> [3323] 62 73 2d 74 61 72 67 65 74 3d 22 23 6e 61 76 62 61 72 22 20 61 72 #> [3345] 69 61 2d 63 6f 6e 74 72 6f 6c 73 3d 22 6e 61 76 62 61 72 22 20 61 #> [3367] 72 69 61 2d 65 78 70 61 6e 64 65 64 3d 22 66 61 6c 73 65 22 20 61 #> [3389] 72 69 61 2d 6c 61 62 65 6c 3d 22 54 6f 67 67 6c 65 20 6e 61 76 69 #> [3411] 67 61 74 69 6f 6e 22 3e 0a 20 20 20 20 20 20 3c 73 70 61 6e 20 63 #> [3433] 6c 61 73 73 3d 22 6e 61 76 62 61 72 2d 74 6f 67 67 6c 65 72 2d 69 #> [3455] 63 6f 6e 22 3e 3c 2f 73 70 61 6e 3e 0a 20 20 20 20 3c 2f 62 75 74 #> [3477] 74 6f 6e 3e 0a 0a 20 20 20 20 3c 64 69 76 20 69 64 3d 22 6e 61 76 #> [3499] 62 61 72 22 20 63 6c 61 73 73 3d 22 63 6f 6c 6c 61 70 73 65 20 6e #> [3521] 61 76 62 61 72 2d 63 6f 6c 6c 61 70 73 65 20 6d 73 2d 33 22 3e 0a #> [3543] 20 20 20 20 20 20 3c 75 6c 20 63 6c 61 73 73 3d 22 6e 61 76 62 61 #> [3565] 72 2d 6e 61 76 20 6d 65 2d 61 75 74 6f 22 3e 0a 3c 6c 69 20 63 6c #> [3587] 61 73 73 3d 22 6e 61 76 2d 69 74 65 6d 22 3e 3c 61 20 63 6c 61 73 #> [3609] 73 3d 22 6e 61 76 2d 6c 69 6e 6b 22 20 68 72 65 66 3d 22 61 72 74 #> [3631] 69 63 6c 65 73 2f 68 74 74 72 32 2e 68 74 6d 6c 22 3e 47 65 74 20 #> [3653] 73 74 61 72 74 65 64 3c 2f 61 3e 3c 2f 6c 69 3e 0a 3c 6c 69 20 63 #> [3675] 6c 61 73 73 3d 22 6e 61 76 2d 69 74 65 6d 22 3e 3c 61 20 63 6c 61 #> [3697] 73 73 3d 22 6e 61 76 2d 6c 69 6e 6b 22 20 68 72 65 66 3d 22 72 65 #> [3719] 66 65 72 65 6e 63 65 2f 69 6e 64 65 78 2e 68 74 6d 6c 22 3e 52 65 #> [3741] 66 65 72 65 6e 63 65 3c 2f 61 3e 3c 2f 6c 69 3e 0a 3c 6c 69 20 63 #> [3763] 6c 61 73 73 3d 22 6e 61 76 2d 69 74 65 6d 20 64 72 6f 70 64 6f 77 #> [3785] 6e 22 3e 0a 20 20 3c 62 75 74 74 6f 6e 20 63 6c 61 73 73 3d 22 6e #> [3807] 61 76 2d 6c 69 6e 6b 20 64 72 6f 70 64 6f 77 6e 2d 74 6f 67 67 6c #> [3829] 65 22 20 74 79 70 65 3d 22 62 75 74 74 6f 6e 22 20 69 64 3d 22 64 #> [3851] 72 6f 70 64 6f 77 6e 2d 61 72 74 69 63 6c 65 73 22 20 64 61 74 61 #> [3873] 2d 62 73 2d 74 6f 67 67 6c 65 3d 22 64 72 6f 70 64 6f 77 6e 22 20 #> [3895] 61 72 69 61 2d 65 78 70 61 6e 64 65 64 3d 22 66 61 6c 73 65 22 20 #> [3917] 61 72 69 61 2d 68 61 73 70 6f 70 75 70 3d 22 74 72 75 65 22 3e 41 #> [3939] 72 74 69 63 6c 65 73 3c 2f 62 75 74 74 6f 6e 3e 0a 20 20 3c 75 6c #> [3961] 20 63 6c 61 73 73 3d 22 64 72 6f 70 64 6f 77 6e 2d 6d 65 6e 75 22 #> [3983] 20 61 72 69 61 2d 6c 61 62 65 6c 6c 65 64 62 79 3d 22 64 72 6f 70 #> [4005] 64 6f 77 6e 2d 61 72 74 69 63 6c 65 73 22 3e 0a 3c 6c 69 3e 3c 61 #> [4027] 20 63 6c 61 73 73 3d 22 64 72 6f 70 64 6f 77 6e 2d 69 74 65 6d 22 #> [4049] 20 68 72 65 66 3d 22 61 72 74 69 63 6c 65 73 2f 77 72 61 70 70 69 #> [4071] 6e 67 2d 61 70 69 73 2e 68 74 6d 6c 22 3e 57 72 61 70 70 69 6e 67 #> [4093] 20 41 50 49 73 3c 2f 61 3e 3c 2f 6c 69 3e 0a 20 20 20 20 3c 6c 69 #> [4115] 3e 3c 61 20 63 6c 61 73 73 3d 22 64 72 6f 70 64 6f 77 6e 2d 69 74 #> [4137] 65 6d 22 20 68 72 65 66 3d 22 61 72 74 69 63 6c 65 73 2f 6f 61 75 #> [4159] 74 68 2e 68 74 6d 6c 22 3e 4f 41 75 74 68 3c 2f 61 3e 3c 2f 6c 69 #> [4181] 3e 0a 20 20 3c 2f 75 6c 3e 0a 3c 2f 6c 69 3e 0a 3c 6c 69 20 63 6c #> [4203] 61 73 73 3d 22 6e 61 76 2d 69 74 65 6d 20 64 72 6f 70 64 6f 77 6e #> [4225] 22 3e 0a 20 20 3c 62 75 74 74 6f 6e 20 63 6c 61 73 73 3d 22 6e 61 #> [4247] 76 2d 6c 69 6e 6b 20 64 72 6f 70 64 6f 77 6e 2d 74 6f 67 67 6c 65 #> [4269] 22 20 74 79 70 65 3d 22 62 75 74 74 6f 6e 22 20 69 64 3d 22 64 72 #> [4291] 6f 70 64 6f 77 6e 2d 6e 65 77 73 22 20 64 61 74 61 2d 62 73 2d 74 #> [4313] 6f 67 67 6c 65 3d 22 64 72 6f 70 64 6f 77 6e 22 20 61 72 69 61 2d #> [4335] 65 78 70 61 6e 64 65 64 3d 22 66 61 6c 73 65 22 20 61 72 69 61 2d #> [4357] 68 61 73 70 6f 70 75 70 3d 22 74 72 75 65 22 3e 4e 65 77 73 3c 2f #> [4379] 62 75 74 74 6f 6e 3e 0a 20 20 3c 75 6c 20 63 6c 61 73 73 3d 22 64 #> [4401] 72 6f 70 64 6f 77 6e 2d 6d 65 6e 75 22 20 61 72 69 61 2d 6c 61 62 #> [4423] 65 6c 6c 65 64 62 79 3d 22 64 72 6f 70 64 6f 77 6e 2d 6e 65 77 73 #> [4445] 22 3e 0a 3c 6c 69 3e 3c 68 36 20 63 6c 61 73 73 3d 22 64 72 6f 70 #> [4467] 64 6f 77 6e 2d 68 65 61 64 65 72 22 20 64 61 74 61 2d 74 6f 63 2d #> [4489] 73 6b 69 70 3e 52 65 6c 65 61 73 65 73 3c 2f 68 36 3e 3c 2f 6c 69 #> [4511] 3e 0a 20 20 20 20 3c 6c 69 3e 3c 61 20 63 6c 61 73 73 3d 22 65 78 #> [4533] 74 65 72 6e 61 6c 2d 6c 69 6e 6b 20 64 72 6f 70 64 6f 77 6e 2d 69 #> [4555] 74 65 6d 22 20 68 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 77 77 77 #> [4577] 2e 74 69 64 79 76 65 72 73 65 2e 6f 72 67 2f 62 6c 6f 67 2f 32 30 #> [4599] 32 33 2f 31 31 2f 68 74 74 72 32 2d 31 2d 30 2d 30 2f 22 3e 68 74 #> [4621] 74 72 32 20 31 2e 30 2e 30 3c 2f 61 3e 3c 2f 6c 69 3e 0a 20 20 20 #> [4643] 20 3c 6c 69 3e 3c 68 72 20 63 6c 61 73 73 3d 22 64 72 6f 70 64 6f #> [4665] 77 6e 2d 64 69 76 69 64 65 72 22 3e 3c 2f 6c 69 3e 0a 20 20 20 20 #> [4687] 3c 6c 69 3e 3c 61 20 63 6c 61 73 73 3d 22 64 72 6f 70 64 6f 77 6e #> [4709] 2d 69 74 65 6d 22 20 68 72 65 66 3d 22 6e 65 77 73 2f 69 6e 64 65 #> [4731] 78 2e 68 74 6d 6c 22 3e 43 68 61 6e 67 65 6c 6f 67 3c 2f 61 3e 3c #> [4753] 2f 6c 69 3e 0a 20 20 3c 2f 75 6c 3e 0a 3c 2f 6c 69 3e 0a 20 20 20 #> [4775] 20 20 20 3c 2f 75 6c 3e 0a 3c 75 6c 20 63 6c 61 73 73 3d 22 6e 61 #> [4797] 76 62 61 72 2d 6e 61 76 22 3e 0a 3c 6c 69 20 63 6c 61 73 73 3d 22 #> [4819] 6e 61 76 2d 69 74 65 6d 22 3e 3c 66 6f 72 6d 20 63 6c 61 73 73 3d #> [4841] 22 66 6f 72 6d 2d 69 6e 6c 69 6e 65 22 20 72 6f 6c 65 3d 22 73 65 #> [4863] 61 72 63 68 22 3e 0a 20 3c 69 6e 70 75 74 20 63 6c 61 73 73 3d 22 #> [4885] 66 6f 72 6d 2d 63 6f 6e 74 72 6f 6c 22 20 74 79 70 65 3d 22 73 65 #> [4907] 61 72 63 68 22 20 6e 61 6d 65 3d 22 73 65 61 72 63 68 2d 69 6e 70 #> [4929] 75 74 22 20 69 64 3d 22 73 65 61 72 63 68 2d 69 6e 70 75 74 22 20 #> [4951] 61 75 74 6f 63 6f 6d 70 6c 65 74 65 3d 22 6f 66 66 22 20 61 72 69 #> [4973] 61 2d 6c 61 62 65 6c 3d 22 53 65 61 72 63 68 20 73 69 74 65 22 20 #> [4995] 70 6c 61 63 65 68 6f 6c 64 65 72 3d 22 53 65 61 72 63 68 20 66 6f #> [5017] 72 22 20 64 61 74 61 2d 73 65 61 72 63 68 2d 69 6e 64 65 78 3d 22 #> [5039] 73 65 61 72 63 68 2e 6a 73 6f 6e 22 3e 0a 3c 2f 66 6f 72 6d 3e 3c #> [5061] 2f 6c 69 3e 0a 3c 6c 69 20 63 6c 61 73 73 3d 22 6e 61 76 2d 69 74 #> [5083] 65 6d 22 3e 3c 61 20 63 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 6c #> [5105] 2d 6c 69 6e 6b 20 6e 61 76 2d 6c 69 6e 6b 22 20 68 72 65 66 3d 22 #> [5127] 68 74 74 70 73 3a 2f 2f 67 69 74 68 75 62 2e 63 6f 6d 2f 72 2d 6c #> [5149] 69 62 2f 68 74 74 72 32 2f 22 20 61 72 69 61 2d 6c 61 62 65 6c 3d #> [5171] 22 47 69 74 48 75 62 22 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 #> [5193] 66 61 20 66 61 62 20 66 61 2d 67 69 74 68 75 62 20 66 61 2d 6c 67 #> [5215] 22 3e 3c 2f 73 70 61 6e 3e 3c 2f 61 3e 3c 2f 6c 69 3e 0a 20 20 20 #> [5237] 20 20 20 3c 2f 75 6c 3e 0a 3c 2f 64 69 76 3e 0a 0a 0a 20 20 3c 2f #> [5259] 64 69 76 3e 0a 3c 2f 6e 61 76 3e 3c 64 69 76 20 63 6c 61 73 73 3d #> [5281] 22 63 6f 6e 74 61 69 6e 65 72 20 74 65 6d 70 6c 61 74 65 2d 68 6f #> [5303] 6d 65 22 20 69 64 3d 22 63 6f 6e 74 61 69 6e 65 72 22 3e 0a 3c 64 #> [5325] 69 76 20 63 6c 61 73 73 3d 22 72 6f 77 22 3e 0a 20 20 3c 6d 61 69 #> [5347] 6e 20 69 64 3d 22 6d 61 69 6e 22 20 63 6c 61 73 73 3d 22 63 6f 6c #> [5369] 2d 6d 64 2d 39 22 3e 3c 64 69 76 20 63 6c 61 73 73 3d 22 73 65 63 #> [5391] 74 69 6f 6e 20 6c 65 76 65 6c 31 22 3e 0a 3c 64 69 76 20 63 6c 61 #> [5413] 73 73 3d 22 70 61 67 65 2d 68 65 61 64 65 72 22 3e 0a 3c 69 6d 67 #> [5435] 20 73 72 63 3d 22 6c 6f 67 6f 2e 70 6e 67 22 20 63 6c 61 73 73 3d #> [5457] 22 6c 6f 67 6f 22 20 61 6c 74 3d 22 22 3e 3c 68 31 20 69 64 3d 22 #> [5479] 68 74 74 72 32 2d 22 3e 68 74 74 72 32 20 0a 3c 61 20 63 6c 61 73 #> [5501] 73 3d 22 61 6e 63 68 6f 72 22 20 61 72 69 61 2d 6c 61 62 65 6c 3d #> [5523] 22 61 6e 63 68 6f 72 22 20 68 72 65 66 3d 22 23 68 74 74 72 32 2d #> [5545] 22 3e 3c 2f 61 3e 0a 3c 2f 68 31 3e 0a 3c 2f 64 69 76 3e 0a 3c 21 #> [5567] 2d 2d 20 62 61 64 67 65 73 3a 20 73 74 61 72 74 20 2d 2d 3e 0a 0a #> [5589] 3c 70 3e 68 74 74 72 32 20 28 70 72 6f 6e 6f 75 6e 63 65 64 20 68 #> [5611] 69 74 74 65 72 32 29 20 69 73 20 61 20 67 72 6f 75 6e 64 2d 75 70 #> [5633] 20 72 65 77 72 69 74 65 20 6f 66 20 3c 61 20 68 72 65 66 3d 22 68 #> [5655] 74 74 70 73 3a 2f 2f 68 74 74 72 2e 72 2d 6c 69 62 2e 6f 72 67 22 #> [5677] 20 63 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 #> [5699] 3e 68 74 74 72 3c 2f 61 3e 20 74 68 61 74 20 70 72 6f 76 69 64 65 #> [5721] 73 20 61 20 70 69 70 65 61 62 6c 65 20 41 50 49 20 77 69 74 68 20 #> [5743] 61 6e 20 65 78 70 6c 69 63 69 74 20 72 65 71 75 65 73 74 20 6f 62 #> [5765] 6a 65 63 74 20 74 68 61 74 20 73 6f 6c 76 65 73 20 6d 6f 72 65 20 #> [5787] 70 72 6f 62 6c 65 6d 73 20 66 65 6c 74 20 62 79 20 70 61 63 6b 61 #> [5809] 67 65 73 20 74 68 61 74 20 77 72 61 70 20 41 50 49 73 20 28 65 2e #> [5831] 67 2e c2 a0 62 75 69 6c 74 2d 69 6e 20 72 61 74 65 2d 6c 69 6d 69 #> [5853] 74 69 6e 67 2c 20 72 65 74 72 69 65 73 2c 20 4f 41 75 74 68 2c 20 #> [5875] 73 65 63 75 72 65 20 73 65 63 72 65 74 73 2c 20 61 6e 64 20 6d 6f #> [5897] 72 65 29 2e 3c 2f 70 3e 0a 3c 64 69 76 20 63 6c 61 73 73 3d 22 73 #> [5919] 65 63 74 69 6f 6e 20 6c 65 76 65 6c 32 22 3e 0a 3c 68 32 20 69 64 #> [5941] 3d 22 69 6e 73 74 61 6c 6c 61 74 69 6f 6e 22 3e 49 6e 73 74 61 6c #> [5963] 6c 61 74 69 6f 6e 3c 61 20 63 6c 61 73 73 3d 22 61 6e 63 68 6f 72 #> [5985] 22 20 61 72 69 61 2d 6c 61 62 65 6c 3d 22 61 6e 63 68 6f 72 22 20 #> [6007] 68 72 65 66 3d 22 23 69 6e 73 74 61 6c 6c 61 74 69 6f 6e 22 3e 3c #> [6029] 2f 61 3e 0a 3c 2f 68 32 3e 0a 3c 70 3e 59 6f 75 20 63 61 6e 20 69 #> [6051] 6e 73 74 61 6c 6c 20 68 74 74 72 32 20 66 72 6f 6d 20 43 52 41 4e #> [6073] 20 77 69 74 68 3a 3c 2f 70 3e 0a 3c 64 69 76 20 63 6c 61 73 73 3d #> [6095] 22 73 6f 75 72 63 65 43 6f 64 65 22 20 69 64 3d 22 63 62 31 22 3e #> [6117] 3c 70 72 65 20 63 6c 61 73 73 3d 22 64 6f 77 6e 6c 69 74 20 73 6f #> [6139] 75 72 63 65 43 6f 64 65 20 72 22 3e 0a 3c 63 6f 64 65 20 63 6c 61 #> [6161] 73 73 3d 22 73 6f 75 72 63 65 43 6f 64 65 20 52 22 3e 3c 73 70 61 #> [6183] 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 66 75 22 3e 3c 61 20 #> [6205] 68 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 72 64 72 72 2e 69 6f 2f #> [6227] 72 2f 75 74 69 6c 73 2f 69 6e 73 74 61 6c 6c 2e 70 61 63 6b 61 67 #> [6249] 65 73 2e 68 74 6d 6c 22 20 63 6c 61 73 73 3d 22 65 78 74 65 72 6e #> [6271] 61 6c 2d 6c 69 6e 6b 22 3e 69 6e 73 74 61 6c 6c 2e 70 61 63 6b 61 #> [6293] 67 65 73 3c 2f 61 3e 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c #> [6315] 61 73 73 3d 22 6f 70 22 3e 28 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e #> [6337] 20 63 6c 61 73 73 3d 22 73 74 22 3e 22 68 74 74 72 32 22 3c 2f 73 #> [6359] 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 29 #> [6381] 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 3c 2f 63 6f 64 65 3e 3c #> [6403] 2f 70 72 65 3e 3c 2f 64 69 76 3e 0a 3c 2f 64 69 76 3e 0a 3c 64 69 #> [6425] 76 20 63 6c 61 73 73 3d 22 73 65 63 74 69 6f 6e 20 6c 65 76 65 6c #> [6447] 32 22 3e 0a 3c 68 32 20 69 64 3d 22 75 73 61 67 65 22 3e 55 73 61 #> [6469] 67 65 3c 61 20 63 6c 61 73 73 3d 22 61 6e 63 68 6f 72 22 20 61 72 #> [6491] 69 61 2d 6c 61 62 65 6c 3d 22 61 6e 63 68 6f 72 22 20 68 72 65 66 #> [6513] 3d 22 23 75 73 61 67 65 22 3e 3c 2f 61 3e 0a 3c 2f 68 32 3e 0a 3c #> [6535] 70 3e 54 6f 20 75 73 65 20 68 74 74 72 32 2c 20 73 74 61 72 74 20 #> [6557] 62 79 20 63 72 65 61 74 69 6e 67 20 61 20 3c 73 74 72 6f 6e 67 3e #> [6579] 72 65 71 75 65 73 74 3c 2f 73 74 72 6f 6e 67 3e 3a 3c 2f 70 3e 0a #> [6601] 3c 64 69 76 20 63 6c 61 73 73 3d 22 73 6f 75 72 63 65 43 6f 64 65 #> [6623] 22 20 69 64 3d 22 63 62 32 22 3e 3c 70 72 65 20 63 6c 61 73 73 3d #> [6645] 22 64 6f 77 6e 6c 69 74 20 73 6f 75 72 63 65 43 6f 64 65 20 72 22 #> [6667] 3e 0a 3c 63 6f 64 65 20 63 6c 61 73 73 3d 22 73 6f 75 72 63 65 43 #> [6689] 6f 64 65 20 52 22 3e 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 #> [6711] 73 73 3d 22 6b 77 22 3e 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 #> [6733] 3a 2f 2f 72 64 72 72 2e 69 6f 2f 72 2f 62 61 73 65 2f 6c 69 62 72 #> [6755] 61 72 79 2e 68 74 6d 6c 22 20 63 6c 61 73 73 3d 22 65 78 74 65 72 #> [6777] 6e 61 6c 2d 6c 69 6e 6b 22 3e 6c 69 62 72 61 72 79 3c 2f 61 3e 3c #> [6799] 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 #> [6821] 3e 28 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 #> [6843] 76 61 22 3e 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 68 #> [6865] 74 74 72 32 2e 72 2d 6c 69 62 2e 6f 72 67 22 3e 68 74 74 72 32 3c #> [6887] 2f 61 3e 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d #> [6909] 22 6f 70 22 3e 29 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c #> [6931] 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 #> [6953] 61 6e 20 63 6c 61 73 73 3d 22 76 61 22 3e 72 65 71 3c 2f 73 70 61 #> [6975] 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 26 6c #> [6997] 74 3b 2d 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 #> [7019] 3d 22 66 75 22 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e #> [7041] 63 65 2f 72 65 71 75 65 73 74 2e 68 74 6d 6c 22 3e 72 65 71 75 65 #> [7063] 73 74 3c 2f 61 3e 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 #> [7085] 73 73 3d 22 6f 70 22 3e 28 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 #> [7107] 63 6c 61 73 73 3d 22 73 74 22 3e 22 68 74 74 70 73 3a 2f 2f 72 2d #> [7129] 70 72 6f 6a 65 63 74 2e 6f 72 67 22 3c 2f 73 70 61 6e 3e 3c 73 70 #> [7151] 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 29 3c 2f 73 70 61 6e 3e #> [7173] 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c #> [7195] 61 73 73 3d 22 76 61 22 3e 72 65 71 3c 2f 73 70 61 6e 3e 3c 2f 73 #> [7217] 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 #> [7239] 3d 22 63 6f 22 3e 23 26 67 74 3b 20 26 6c 74 3b 68 74 74 72 32 5f #> [7261] 72 65 71 75 65 73 74 26 67 74 3b 3c 2f 73 70 61 6e 3e 3c 2f 73 70 #> [7283] 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d #> [7305] 22 63 6f 22 3e 23 26 67 74 3b 20 47 45 54 20 68 74 74 70 73 3a 2f #> [7327] 2f 72 2d 70 72 6f 6a 65 63 74 2e 6f 72 67 3c 2f 73 70 61 6e 3e 3c #> [7349] 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 #> [7371] 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 42 6f 64 79 3a 20 65 6d #> [7393] 70 74 79 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 3c 2f 63 6f 64 #> [7415] 65 3e 3c 2f 70 72 65 3e 3c 2f 64 69 76 3e 0a 3c 70 3e 59 6f 75 20 #> [7437] 63 61 6e 20 74 61 69 6c 6f 72 20 74 68 69 73 20 72 65 71 75 65 73 #> [7459] 74 20 77 69 74 68 20 74 68 65 20 3c 63 6f 64 65 3e 72 65 71 5f 3c #> [7481] 2f 63 6f 64 65 3e 20 66 61 6d 69 6c 79 20 6f 66 20 66 75 6e 63 74 #> [7503] 69 6f 6e 73 3a 3c 2f 70 3e 0a 3c 64 69 76 20 63 6c 61 73 73 3d 22 #> [7525] 73 6f 75 72 63 65 43 6f 64 65 22 20 69 64 3d 22 63 62 33 22 3e 3c #> [7547] 70 72 65 20 63 6c 61 73 73 3d 22 64 6f 77 6e 6c 69 74 20 73 6f 75 #> [7569] 72 63 65 43 6f 64 65 20 72 22 3e 0a 3c 63 6f 64 65 20 63 6c 61 73 #> [7591] 73 3d 22 73 6f 75 72 63 65 43 6f 64 65 20 52 22 3e 3c 73 70 61 6e #> [7613] 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 20 41 64 #> [7635] 64 20 63 75 73 74 6f 6d 20 68 65 61 64 65 72 73 3c 2f 73 70 61 6e #> [7657] 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 #> [7679] 6c 61 73 73 3d 22 76 61 22 3e 72 65 71 3c 2f 73 70 61 6e 3e 20 3c #> [7701] 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 7c 26 67 74 3b 3c #> [7723] 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 66 75 #> [7745] 22 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 2f 72 #> [7767] 65 71 5f 68 65 61 64 65 72 73 2e 68 74 6d 6c 22 3e 72 65 71 5f 68 #> [7789] 65 61 64 65 72 73 3c 2f 61 3e 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e #> [7811] 20 63 6c 61 73 73 3d 22 6f 70 22 3e 28 3c 2f 73 70 61 6e 3e 3c 73 #> [7833] 70 61 6e 20 63 6c 61 73 73 3d 22 73 74 22 3e 22 41 63 63 65 70 74 #> [7855] 22 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 #> [7877] 6f 70 22 3e 3d 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 #> [7899] 73 73 3d 22 73 74 22 3e 22 61 70 70 6c 69 63 61 74 69 6f 6e 2f 6a #> [7921] 73 6f 6e 22 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 #> [7943] 3d 22 6f 70 22 3e 29 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a #> [7965] 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 #> [7987] 3e 23 26 67 74 3b 20 26 6c 74 3b 68 74 74 72 32 5f 72 65 71 75 65 #> [8009] 73 74 26 67 74 3b 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c #> [8031] 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e #> [8053] 23 26 67 74 3b 20 47 45 54 20 68 74 74 70 73 3a 2f 2f 72 2d 70 72 #> [8075] 6f 6a 65 63 74 2e 6f 72 67 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e #> [8097] 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 #> [8119] 6f 22 3e 23 26 67 74 3b 20 48 65 61 64 65 72 73 3a 3c 2f 73 70 61 #> [8141] 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 #> [8163] 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 e2 80 a2 20 41 #> [8185] 63 63 65 70 74 3a 20 27 61 70 70 6c 69 63 61 74 69 6f 6e 2f 6a 73 #> [8207] 6f 6e 27 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 #> [8229] 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 #> [8251] 74 3b 20 42 6f 64 79 3a 20 65 6d 70 74 79 3c 2f 73 70 61 6e 3e 3c #> [8273] 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c #> [8295] 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e #> [8317] 23 20 41 64 64 20 61 20 62 6f 64 79 2c 20 74 75 72 6e 69 6e 67 20 #> [8339] 69 74 20 69 6e 74 6f 20 61 20 50 4f 53 54 3c 2f 73 70 61 6e 3e 3c #> [8361] 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 #> [8383] 73 73 3d 22 76 61 22 3e 72 65 71 3c 2f 73 70 61 6e 3e 20 3c 73 70 #> [8405] 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 7c 26 67 74 3b 3c 2f 73 #> [8427] 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 66 75 22 3e #> [8449] 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 2f 72 65 71 #> [8471] 5f 62 6f 64 79 2e 68 74 6d 6c 22 3e 72 65 71 5f 62 6f 64 79 5f 6a #> [8493] 73 6f 6e 3c 2f 61 3e 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c #> [8515] 61 73 73 3d 22 6f 70 22 3e 28 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e #> [8537] 20 63 6c 61 73 73 3d 22 66 75 22 3e 3c 61 20 68 72 65 66 3d 22 68 #> [8559] 74 74 70 73 3a 2f 2f 72 64 72 72 2e 69 6f 2f 72 2f 62 61 73 65 2f #> [8581] 6c 69 73 74 2e 68 74 6d 6c 22 20 63 6c 61 73 73 3d 22 65 78 74 65 #> [8603] 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 6c 69 73 74 3c 2f 61 3e 3c 2f 73 #> [8625] 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 28 #> [8647] 3c 2f 73 70 61 6e 3e 78 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 #> [8669] 6f 70 22 3e 3d 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 #> [8691] 73 73 3d 22 66 6c 22 3e 31 3c 2f 73 70 61 6e 3e 2c 20 79 20 3c 73 #> [8713] 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 3d 3c 2f 73 70 61 6e #> [8735] 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 66 6c 22 3e 32 3c 2f #> [8757] 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e #> [8779] 29 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f #> [8801] 70 22 3e 29 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 #> [8823] 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 #> [8845] 67 74 3b 20 26 6c 74 3b 68 74 74 72 32 5f 72 65 71 75 65 73 74 26 #> [8867] 67 74 3b 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 #> [8889] 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 #> [8911] 74 3b 20 50 4f 53 54 20 68 74 74 70 73 3a 2f 2f 72 2d 70 72 6f 6a #> [8933] 65 63 74 2e 6f 72 67 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a #> [8955] 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 #> [8977] 3e 23 26 67 74 3b 20 42 6f 64 79 3a 20 6a 73 6f 6e 20 65 6e 63 6f #> [8999] 64 65 64 20 64 61 74 61 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e #> [9021] 0a 3c 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c #> [9043] 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 20 4d 6f 64 69 #> [9065] 66 79 20 74 68 65 20 70 61 74 68 20 69 6e 20 74 68 65 20 75 72 6c #> [9087] 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c #> [9109] 73 70 61 6e 20 63 6c 61 73 73 3d 22 76 61 22 3e 72 65 71 3c 2f 73 #> [9131] 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e #> [9153] 7c 26 67 74 3b 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 #> [9175] 73 73 3d 22 66 75 22 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 #> [9197] 65 6e 63 65 2f 72 65 71 5f 75 72 6c 2e 68 74 6d 6c 22 3e 72 65 71 #> [9219] 5f 75 72 6c 5f 70 61 74 68 3c 2f 61 3e 3c 2f 73 70 61 6e 3e 3c 73 #> [9241] 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 28 3c 2f 73 70 61 6e #> [9263] 3e 70 61 74 68 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 #> [9285] 3e 3d 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d #> [9307] 22 73 74 22 3e 22 70 61 74 68 2f 74 6f 2f 6d 79 2f 66 69 6c 65 22 #> [9329] 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 #> [9351] 22 3e 29 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 #> [9373] 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 #> [9395] 74 3b 20 26 6c 74 3b 68 74 74 72 32 5f 72 65 71 75 65 73 74 26 67 #> [9417] 74 3b 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e #> [9439] 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 #> [9461] 3b 20 47 45 54 20 68 74 74 70 73 3a 2f 2f 72 2d 70 72 6f 6a 65 63 #> [9483] 74 2e 6f 72 67 2f 70 61 74 68 2f 74 6f 2f 6d 79 2f 66 69 6c 65 3c #> [9505] 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 #> [9527] 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 42 #> [9549] 6f 64 79 3a 20 65 6d 70 74 79 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 #> [9571] 6e 3e 0a 3c 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e #> [9593] 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 20 41 75 #> [9615] 74 6f 6d 61 74 69 63 61 6c 6c 79 20 72 65 74 72 79 20 69 66 20 74 #> [9637] 68 65 20 72 65 71 75 65 73 74 20 66 61 69 6c 73 3c 2f 73 70 61 6e #> [9659] 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 #> [9681] 6c 61 73 73 3d 22 76 61 22 3e 72 65 71 3c 2f 73 70 61 6e 3e 20 3c #> [9703] 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 7c 26 67 74 3b 3c #> [9725] 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 66 75 #> [9747] 22 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 2f 72 #> [9769] 65 71 5f 72 65 74 72 79 2e 68 74 6d 6c 22 3e 72 65 71 5f 72 65 74 #> [9791] 72 79 3c 2f 61 3e 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 #> [9813] 73 73 3d 22 6f 70 22 3e 28 3c 2f 73 70 61 6e 3e 6d 61 78 5f 74 72 #> [9835] 69 65 73 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 3d #> [9857] 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 66 #> [9879] 6c 22 3e 35 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 #> [9901] 3d 22 6f 70 22 3e 29 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a #> [9923] 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 #> [9945] 3e 23 26 67 74 3b 20 26 6c 74 3b 68 74 74 72 32 5f 72 65 71 75 65 #> [9967] 73 74 26 67 74 3b 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c #> [9989] 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e #> [10011] 23 26 67 74 3b 20 47 45 54 20 68 74 74 70 73 3a 2f 2f 72 2d 70 72 #> [10033] 6f 6a 65 63 74 2e 6f 72 67 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e #> [10055] 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 #> [10077] 6f 22 3e 23 26 67 74 3b 20 42 6f 64 79 3a 20 65 6d 70 74 79 3c 2f #> [10099] 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 #> [10121] 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 50 6f #> [10143] 6c 69 63 69 65 73 3a 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a #> [10165] 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 #> [10187] 3e 23 26 67 74 3b 20 e2 80 a2 20 72 65 74 72 79 5f 6d 61 78 5f 74 #> [10209] 72 69 65 73 3a 20 35 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a #> [10231] 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 #> [10253] 3e 23 26 67 74 3b 20 e2 80 a2 20 72 65 74 72 79 5f 6f 6e 5f 66 61 #> [10275] 69 6c 75 72 65 3a 20 46 41 4c 53 45 3c 2f 73 70 61 6e 3e 3c 2f 73 #> [10297] 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 #> [10319] 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 20 #> [10341] 43 68 61 6e 67 65 20 74 68 65 20 48 54 54 50 20 6d 65 74 68 6f 64 #> [10363] 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c #> [10385] 73 70 61 6e 20 63 6c 61 73 73 3d 22 76 61 22 3e 72 65 71 3c 2f 73 #> [10407] 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e #> [10429] 7c 26 67 74 3b 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 #> [10451] 73 73 3d 22 66 75 22 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 #> [10473] 65 6e 63 65 2f 72 65 71 5f 6d 65 74 68 6f 64 2e 68 74 6d 6c 22 3e #> [10495] 72 65 71 5f 6d 65 74 68 6f 64 3c 2f 61 3e 3c 2f 73 70 61 6e 3e 3c #> [10517] 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 28 3c 2f 73 70 61 #> [10539] 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 73 74 22 3e 22 50 41 #> [10561] 54 43 48 22 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 #> [10583] 3d 22 6f 70 22 3e 29 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a #> [10605] 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 #> [10627] 3e 23 26 67 74 3b 20 26 6c 74 3b 68 74 74 72 32 5f 72 65 71 75 65 #> [10649] 73 74 26 67 74 3b 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c #> [10671] 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e #> [10693] 23 26 67 74 3b 20 50 41 54 43 48 20 68 74 74 70 73 3a 2f 2f 72 2d #> [10715] 70 72 6f 6a 65 63 74 2e 6f 72 67 3c 2f 73 70 61 6e 3e 3c 2f 73 70 #> [10737] 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d #> [10759] 22 63 6f 22 3e 23 26 67 74 3b 20 42 6f 64 79 3a 20 65 6d 70 74 79 #> [10781] 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 3c 2f 63 6f 64 65 3e 3c #> [10803] 2f 70 72 65 3e 3c 2f 64 69 76 3e 0a 3c 70 3e 41 6e 64 20 73 65 65 #> [10825] 20 65 78 61 63 74 6c 79 20 77 68 61 74 20 68 74 74 72 32 20 77 69 #> [10847] 6c 6c 20 73 65 6e 64 20 74 6f 20 74 68 65 20 73 65 72 76 65 72 20 #> [10869] 77 69 74 68 20 3c 63 6f 64 65 3e 3c 61 20 68 72 65 66 3d 22 72 65 #> [10891] 66 65 72 65 6e 63 65 2f 72 65 71 5f 64 72 79 5f 72 75 6e 2e 68 74 #> [10913] 6d 6c 22 3e 72 65 71 5f 64 72 79 5f 72 75 6e 28 29 3c 2f 61 3e 3c #> [10935] 2f 63 6f 64 65 3e 3a 3c 2f 70 3e 0a 3c 64 69 76 20 63 6c 61 73 73 #> [10957] 3d 22 73 6f 75 72 63 65 43 6f 64 65 22 20 69 64 3d 22 63 62 34 22 #> [10979] 3e 3c 70 72 65 20 63 6c 61 73 73 3d 22 64 6f 77 6e 6c 69 74 20 73 #> [11001] 6f 75 72 63 65 43 6f 64 65 20 72 22 3e 0a 3c 63 6f 64 65 20 63 6c #> [11023] 61 73 73 3d 22 73 6f 75 72 63 65 43 6f 64 65 20 52 22 3e 3c 73 70 #> [11045] 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 76 61 22 3e 72 65 #> [11067] 71 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 #> [11089] 6f 70 22 3e 7c 26 67 74 3b 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e #> [11111] 20 63 6c 61 73 73 3d 22 66 75 22 3e 3c 61 20 68 72 65 66 3d 22 72 #> [11133] 65 66 65 72 65 6e 63 65 2f 72 65 71 5f 64 72 79 5f 72 75 6e 2e 68 #> [11155] 74 6d 6c 22 3e 72 65 71 5f 64 72 79 5f 72 75 6e 3c 2f 61 3e 3c 2f #> [11177] 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e #> [11199] 28 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f #> [11221] 70 22 3e 29 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 #> [11243] 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 #> [11265] 67 74 3b 20 47 45 54 20 2f 20 48 54 54 50 2f 31 2e 31 3c 2f 73 70 #> [11287] 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e #> [11309] 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 48 6f 73 74 #> [11331] 3a 20 72 2d 70 72 6f 6a 65 63 74 2e 6f 72 67 3c 2f 73 70 61 6e 3e #> [11353] 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c #> [11375] 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 55 73 65 72 2d 41 67 #> [11397] 65 6e 74 3a 20 68 74 74 72 32 2f 31 2e 30 2e 33 2e 39 30 30 30 20 #> [11419] 72 2d 63 75 72 6c 2f 35 2e 32 2e 32 20 6c 69 62 63 75 72 6c 2f 38 #> [11441] 2e 36 2e 30 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 #> [11463] 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 #> [11485] 67 74 3b 20 41 63 63 65 70 74 3a 20 2a 2f 2a 3c 2f 73 70 61 6e 3e #> [11507] 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c #> [11529] 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 41 63 63 65 70 74 2d #> [11551] 45 6e 63 6f 64 69 6e 67 3a 20 64 65 66 6c 61 74 65 2c 20 67 7a 69 #> [11573] 70 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 3c 2f 63 6f 64 65 3e #> [11595] 3c 2f 70 72 65 3e 3c 2f 64 69 76 3e 0a 3c 70 3e 55 73 65 20 3c 63 #> [11617] 6f 64 65 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 #> [11639] 2f 72 65 71 5f 70 65 72 66 6f 72 6d 2e 68 74 6d 6c 22 3e 72 65 71 #> [11661] 5f 70 65 72 66 6f 72 6d 28 29 3c 2f 61 3e 3c 2f 63 6f 64 65 3e 20 #> [11683] 74 6f 20 70 65 72 66 6f 72 6d 20 74 68 65 20 72 65 71 75 65 73 74 #> [11705] 2c 20 72 65 74 72 69 65 76 69 6e 67 20 61 20 3c 73 74 72 6f 6e 67 #> [11727] 3e 72 65 73 70 6f 6e 73 65 3c 2f 73 74 72 6f 6e 67 3e 3a 3c 2f 70 #> [11749] 3e 0a 3c 64 69 76 20 63 6c 61 73 73 3d 22 73 6f 75 72 63 65 43 6f #> [11771] 64 65 22 20 69 64 3d 22 63 62 35 22 3e 3c 70 72 65 20 63 6c 61 73 #> [11793] 73 3d 22 64 6f 77 6e 6c 69 74 20 73 6f 75 72 63 65 43 6f 64 65 20 #> [11815] 72 22 3e 0a 3c 63 6f 64 65 20 63 6c 61 73 73 3d 22 73 6f 75 72 63 #> [11837] 65 43 6f 64 65 20 52 22 3e 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 #> [11859] 6c 61 73 73 3d 22 76 61 22 3e 72 65 73 70 3c 2f 73 70 61 6e 3e 20 #> [11881] 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 26 6c 74 3b 2d #> [11903] 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 66 #> [11925] 75 22 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 2f #> [11947] 72 65 71 5f 70 65 72 66 6f 72 6d 2e 68 74 6d 6c 22 3e 72 65 71 5f #> [11969] 70 65 72 66 6f 72 6d 3c 2f 61 3e 3c 2f 73 70 61 6e 3e 3c 73 70 61 #> [11991] 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 28 3c 2f 73 70 61 6e 3e 3c #> [12013] 73 70 61 6e 20 63 6c 61 73 73 3d 22 76 61 22 3e 72 65 71 3c 2f 73 #> [12035] 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 29 #> [12057] 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c #> [12079] 73 70 61 6e 20 63 6c 61 73 73 3d 22 76 61 22 3e 72 65 73 70 3c 2f #> [12101] 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 #> [12123] 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 26 6c #> [12145] 74 3b 68 74 74 72 32 5f 72 65 73 70 6f 6e 73 65 26 67 74 3b 3c 2f #> [12167] 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 #> [12189] 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 47 45 #> [12211] 54 20 68 74 74 70 73 3a 2f 2f 77 77 77 2e 72 2d 70 72 6f 6a 65 63 #> [12233] 74 2e 6f 72 67 2f 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c #> [12255] 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e #> [12277] 23 26 67 74 3b 20 53 74 61 74 75 73 3a 20 32 30 30 20 4f 4b 3c 2f #> [12299] 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 #> [12321] 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 43 6f #> [12343] 6e 74 65 6e 74 2d 54 79 70 65 3a 20 74 65 78 74 2f 68 74 6d 6c 3c #> [12365] 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 #> [12387] 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 42 #> [12409] 6f 64 79 3a 20 49 6e 20 6d 65 6d 6f 72 79 20 28 36 39 35 31 20 62 #> [12431] 79 74 65 73 29 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 3c 2f 63 #> [12453] 6f 64 65 3e 3c 2f 70 72 65 3e 3c 2f 64 69 76 3e 0a 3c 70 3e 54 68 #> [12475] 65 20 3c 63 6f 64 65 3e 72 65 73 70 5f 3c 2f 63 6f 64 65 3e 20 66 #> [12497] 75 6e 63 74 69 6f 6e 73 20 68 65 6c 70 20 79 6f 75 20 65 78 74 72 #> [12519] 61 63 74 20 76 61 72 69 6f 75 73 20 75 73 65 66 75 6c 20 63 6f 6d #> [12541] 70 6f 6e 65 6e 74 73 20 6f 66 20 74 68 65 20 72 65 73 70 6f 6e 73 #> [12563] 65 3a 3c 2f 70 3e 0a 3c 64 69 76 20 63 6c 61 73 73 3d 22 73 6f 75 #> [12585] 72 63 65 43 6f 64 65 22 20 69 64 3d 22 63 62 36 22 3e 3c 70 72 65 #> [12607] 20 63 6c 61 73 73 3d 22 64 6f 77 6e 6c 69 74 20 73 6f 75 72 63 65 #> [12629] 43 6f 64 65 20 72 22 3e 0a 3c 63 6f 64 65 20 63 6c 61 73 73 3d 22 #> [12651] 73 6f 75 72 63 65 43 6f 64 65 20 52 22 3e 3c 73 70 61 6e 3e 3c 73 #> [12673] 70 61 6e 20 63 6c 61 73 73 3d 22 76 61 22 3e 72 65 73 70 3c 2f 73 #> [12695] 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e #> [12717] 7c 26 67 74 3b 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 #> [12739] 73 73 3d 22 66 75 22 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 #> [12761] 65 6e 63 65 2f 72 65 73 70 5f 63 6f 6e 74 65 6e 74 5f 74 79 70 65 #> [12783] 2e 68 74 6d 6c 22 3e 72 65 73 70 5f 63 6f 6e 74 65 6e 74 5f 74 79 #> [12805] 70 65 3c 2f 61 3e 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 #> [12827] 73 73 3d 22 6f 70 22 3e 28 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 #> [12849] 63 6c 61 73 73 3d 22 6f 70 22 3e 29 3c 2f 73 70 61 6e 3e 3c 2f 73 #> [12871] 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 #> [12893] 3d 22 63 6f 22 3e 23 26 67 74 3b 20 5b 31 5d 20 22 74 65 78 74 2f #> [12915] 68 74 6d 6c 22 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 #> [12937] 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 76 61 22 3e 72 #> [12959] 65 73 70 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 #> [12981] 3d 22 6f 70 22 3e 7c 26 67 74 3b 3c 2f 73 70 61 6e 3e 20 3c 73 70 #> [13003] 61 6e 20 63 6c 61 73 73 3d 22 66 75 22 3e 3c 61 20 68 72 65 66 3d #> [13025] 22 72 65 66 65 72 65 6e 63 65 2f 72 65 73 70 5f 73 74 61 74 75 73 #> [13047] 2e 68 74 6d 6c 22 3e 72 65 73 70 5f 73 74 61 74 75 73 5f 64 65 73 #> [13069] 63 3c 2f 61 3e 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 #> [13091] 73 3d 22 6f 70 22 3e 28 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 #> [13113] 6c 61 73 73 3d 22 6f 70 22 3e 29 3c 2f 73 70 61 6e 3e 3c 2f 73 70 #> [13135] 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d #> [13157] 22 63 6f 22 3e 23 26 67 74 3b 20 5b 31 5d 20 22 4f 4b 22 3c 2f 73 #> [13179] 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 #> [13201] 6e 20 63 6c 61 73 73 3d 22 76 61 22 3e 72 65 73 70 3c 2f 73 70 61 #> [13223] 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 7c 26 #> [13245] 67 74 3b 3c 2f 73 70 61 6e 3e 20 3c 73 70 61 6e 20 63 6c 61 73 73 #> [13267] 3d 22 66 75 22 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e #> [13289] 63 65 2f 72 65 73 70 5f 62 6f 64 79 5f 72 61 77 2e 68 74 6d 6c 22 #> [13311] 3e 72 65 73 70 5f 62 6f 64 79 5f 68 74 6d 6c 3c 2f 61 3e 3c 2f 73 #> [13333] 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 22 3e 28 #> [13355] 3c 2f 73 70 61 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6f 70 #> [13377] 22 3e 29 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 #> [13399] 6e 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 #> [13421] 74 3b 20 7b 68 74 6d 6c 5f 64 6f 63 75 6d 65 6e 74 7d 3c 2f 73 70 #> [13443] 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e #> [13465] 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 26 6c 74 3b #> [13487] 68 74 6d 6c 20 6c 61 6e 67 3d 22 65 6e 22 26 67 74 3b 3c 2f 73 70 #> [13509] 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 61 6e #> [13531] 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 5b 31 5d 20 #> [13553] 26 6c 74 3b 68 65 61 64 26 67 74 3b 5c 6e 26 6c 74 3b 6d 65 74 61 #> [13575] 20 68 74 74 70 2d 65 71 75 69 76 3d 22 43 6f 6e 74 65 6e 74 2d 54 #> [13597] 79 70 65 22 20 63 6f 6e 74 65 6e 74 3d 22 74 65 78 74 2f 68 74 6d #> [13619] 6c 3b 20 63 68 61 72 73 65 74 3d 55 54 46 2d 38 20 2e 2e 2e 3c 2f #> [13641] 73 70 61 6e 3e 3c 2f 73 70 61 6e 3e 0a 3c 73 70 61 6e 3e 3c 73 70 #> [13663] 61 6e 20 63 6c 61 73 73 3d 22 63 6f 22 3e 23 26 67 74 3b 20 5b 32 #> [13685] 5d 20 26 6c 74 3b 62 6f 64 79 26 67 74 3b 5c 6e 20 20 20 20 26 6c #> [13707] 74 3b 64 69 76 20 63 6c 61 73 73 3d 22 63 6f 6e 74 61 69 6e 65 72 #> [13729] 20 70 61 67 65 22 26 67 74 3b 5c 6e 20 20 20 20 20 20 26 6c 74 3b #> [13751] 64 69 76 20 63 6c 61 73 73 3d 22 72 6f 77 22 26 67 74 3b 5c 6e 20 #> [13773] 20 20 20 20 20 20 2e 2e 2e 3c 2f 73 70 61 6e 3e 3c 2f 73 70 61 6e #> [13795] 3e 3c 2f 63 6f 64 65 3e 3c 2f 70 72 65 3e 3c 2f 64 69 76 3e 0a 3c #> [13817] 2f 64 69 76 3e 0a 3c 64 69 76 20 63 6c 61 73 73 3d 22 73 65 63 74 #> [13839] 69 6f 6e 20 6c 65 76 65 6c 32 22 3e 0a 3c 68 32 20 69 64 3d 22 6d #> [13861] 61 6a 6f 72 2d 64 69 66 66 65 72 65 6e 63 65 73 2d 74 6f 2d 68 74 #> [13883] 74 72 22 3e 4d 61 6a 6f 72 20 64 69 66 66 65 72 65 6e 63 65 73 20 #> [13905] 74 6f 20 68 74 74 72 3c 61 20 63 6c 61 73 73 3d 22 61 6e 63 68 6f #> [13927] 72 22 20 61 72 69 61 2d 6c 61 62 65 6c 3d 22 61 6e 63 68 6f 72 22 #> [13949] 20 68 72 65 66 3d 22 23 6d 61 6a 6f 72 2d 64 69 66 66 65 72 65 6e #> [13971] 63 65 73 2d 74 6f 2d 68 74 74 72 22 3e 3c 2f 61 3e 0a 3c 2f 68 32 #> [13993] 3e 0a 3c 75 6c 3e 0a 3c 6c 69 3e 3c 70 3e 59 6f 75 20 63 61 6e 20 #> [14015] 6e 6f 77 20 63 72 65 61 74 65 20 61 6e 64 20 6d 6f 64 69 66 79 20 #> [14037] 61 20 72 65 71 75 65 73 74 20 77 69 74 68 6f 75 74 20 70 65 72 66 #> [14059] 6f 72 6d 69 6e 67 20 69 74 2e 20 54 68 69 73 20 6d 65 61 6e 73 20 #> [14081] 74 68 61 74 20 74 68 65 72 65 e2 80 99 73 20 6e 6f 77 20 61 20 73 #> [14103] 69 6e 67 6c 65 20 66 75 6e 63 74 69 6f 6e 20 74 6f 20 70 65 72 66 #> [14125] 6f 72 6d 20 74 68 65 20 72 65 71 75 65 73 74 20 61 6e 64 20 66 65 #> [14147] 74 63 68 20 74 68 65 20 72 65 73 75 6c 74 3a 20 3c 63 6f 64 65 3e #> [14169] 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 2f 72 65 71 #> [14191] 5f 70 65 72 66 6f 72 6d 2e 68 74 6d 6c 22 3e 72 65 71 5f 70 65 72 #> [14213] 66 6f 72 6d 28 29 3c 2f 61 3e 3c 2f 63 6f 64 65 3e 2e 20 3c 63 6f #> [14235] 64 65 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 2f #> [14257] 72 65 71 5f 70 65 72 66 6f 72 6d 2e 68 74 6d 6c 22 3e 72 65 71 5f #> [14279] 70 65 72 66 6f 72 6d 28 29 3c 2f 61 3e 3c 2f 63 6f 64 65 3e 20 72 #> [14301] 65 70 6c 61 63 65 73 20 3c 63 6f 64 65 3e 3c 61 20 68 72 65 66 3d #> [14323] 22 68 74 74 70 73 3a 2f 2f 68 74 74 72 2e 72 2d 6c 69 62 2e 6f 72 #> [14345] 67 2f 72 65 66 65 72 65 6e 63 65 2f 47 45 54 2e 68 74 6d 6c 22 20 #> [14367] 63 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e #> [14389] 68 74 74 72 3a 3a 47 45 54 28 29 3c 2f 61 3e 3c 2f 63 6f 64 65 3e #> [14411] 2c 20 3c 63 6f 64 65 3e 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 #> [14433] 3a 2f 2f 68 74 74 72 2e 72 2d 6c 69 62 2e 6f 72 67 2f 72 65 66 65 #> [14455] 72 65 6e 63 65 2f 50 4f 53 54 2e 68 74 6d 6c 22 20 63 6c 61 73 73 #> [14477] 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 68 74 74 72 3a #> [14499] 3a 50 4f 53 54 28 29 3c 2f 61 3e 3c 2f 63 6f 64 65 3e 2c 20 3c 63 #> [14521] 6f 64 65 3e 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 68 #> [14543] 74 74 72 2e 72 2d 6c 69 62 2e 6f 72 67 2f 72 65 66 65 72 65 6e 63 #> [14565] 65 2f 44 45 4c 45 54 45 2e 68 74 6d 6c 22 20 63 6c 61 73 73 3d 22 #> [14587] 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 68 74 74 72 3a 3a 44 #> [14609] 45 4c 45 54 45 28 29 3c 2f 61 3e 3c 2f 63 6f 64 65 3e 2c 20 61 6e #> [14631] 64 20 6d 6f 72 65 2e 3c 2f 70 3e 3c 2f 6c 69 3e 0a 3c 6c 69 3e 3c #> [14653] 70 3e 48 54 54 50 20 65 72 72 6f 72 73 20 61 72 65 20 61 75 74 6f #> [14675] 6d 61 74 69 63 61 6c 6c 79 20 63 6f 6e 76 65 72 74 65 64 20 69 6e #> [14697] 74 6f 20 52 20 65 72 72 6f 72 73 2e 20 55 73 65 20 3c 63 6f 64 65 #> [14719] 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 2f 72 65 #> [14741] 71 5f 65 72 72 6f 72 2e 68 74 6d 6c 22 3e 72 65 71 5f 65 72 72 6f #> [14763] 72 28 29 3c 2f 61 3e 3c 2f 63 6f 64 65 3e 20 74 6f 20 6f 76 65 72 #> [14785] 72 69 64 65 20 74 68 65 20 64 65 66 61 75 6c 74 73 20 28 77 68 69 #> [14807] 63 68 20 74 75 72 6e 20 61 6c 6c 20 34 78 78 20 61 6e 64 20 35 78 #> [14829] 78 20 72 65 73 70 6f 6e 73 65 73 20 69 6e 74 6f 20 65 72 72 6f 72 #> [14851] 73 29 20 6f 72 20 74 6f 20 61 64 64 20 61 64 64 69 74 69 6f 6e 61 #> [14873] 6c 20 64 65 74 61 69 6c 73 20 74 6f 20 74 68 65 20 65 72 72 6f 72 #> [14895] 20 6d 65 73 73 61 67 65 2e 3c 2f 70 3e 3c 2f 6c 69 3e 0a 3c 6c 69 #> [14917] 3e 3c 70 3e 59 6f 75 20 63 61 6e 20 61 75 74 6f 6d 61 74 69 63 61 #> [14939] 6c 6c 79 20 72 65 74 72 79 20 69 66 20 74 68 65 20 72 65 71 75 65 #> [14961] 73 74 20 66 61 69 6c 73 20 6f 72 20 65 6e 63 6f 75 6e 74 65 72 73 #> [14983] 20 61 20 74 72 61 6e 73 69 65 6e 74 20 48 54 54 50 20 65 72 72 6f #> [15005] 72 20 28 65 2e 67 2e c2 a0 61 20 34 32 39 20 72 61 74 65 20 6c 69 #> [15027] 6d 69 74 20 72 65 71 75 65 73 74 29 2e 20 3c 63 6f 64 65 3e 3c 61 #> [15049] 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 2f 72 65 71 5f 72 #> [15071] 65 74 72 79 2e 68 74 6d 6c 22 3e 72 65 71 5f 72 65 74 72 79 28 29 #> [15093] 3c 2f 61 3e 3c 2f 63 6f 64 65 3e 20 64 65 66 69 6e 65 73 20 74 68 #> [15115] 65 20 6d 61 78 69 6d 75 6d 20 6e 75 6d 62 65 72 20 6f 66 20 72 65 #> [15137] 74 72 69 65 73 2c 20 77 68 69 63 68 20 65 72 72 6f 72 73 20 61 72 #> [15159] 65 20 74 72 61 6e 73 69 65 6e 74 2c 20 61 6e 64 20 68 6f 77 20 6c #> [15181] 6f 6e 67 20 74 6f 20 77 61 69 74 20 62 65 74 77 65 65 6e 20 74 72 #> [15203] 69 65 73 2e 3c 2f 70 3e 3c 2f 6c 69 3e 0a 3c 6c 69 3e 3c 70 3e 4f #> [15225] 41 75 74 68 20 73 75 70 70 6f 72 74 20 68 61 73 20 62 65 65 6e 20 #> [15247] 74 6f 74 61 6c 6c 79 20 6f 76 65 72 68 61 75 6c 65 64 20 74 6f 20 #> [15269] 64 69 72 65 63 74 6c 79 20 73 75 70 70 6f 72 74 20 6d 61 6e 79 20 #> [15291] 6d 6f 72 65 20 66 6c 6f 77 73 20 61 6e 64 20 74 6f 20 6d 61 6b 65 #> [15313] 20 69 74 20 6d 75 63 68 20 65 61 73 69 65 72 20 74 6f 20 62 6f 74 #> [15335] 68 20 63 75 73 74 6f 6d 69 73 65 20 74 68 65 20 62 75 69 6c 74 2d #> [15357] 69 6e 20 66 6c 6f 77 73 20 61 6e 64 20 74 6f 20 63 72 65 61 74 65 #> [15379] 20 79 6f 75 72 20 6f 77 6e 2e 3c 2f 70 3e 3c 2f 6c 69 3e 0a 3c 6c #> [15401] 69 3e 3c 70 3e 59 6f 75 20 63 61 6e 20 6d 61 6e 61 67 65 20 73 65 #> [15423] 63 72 65 74 73 20 28 6f 66 74 65 6e 20 6e 65 65 64 65 64 20 66 6f #> [15445] 72 20 74 65 73 74 69 6e 67 29 20 77 69 74 68 20 3c 63 6f 64 65 3e #> [15467] 3c 61 20 68 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 2f 73 65 63 #> [15489] 72 65 74 73 2e 68 74 6d 6c 22 3e 73 65 63 72 65 74 5f 65 6e 63 72 #> [15511] 79 70 74 28 29 3c 2f 61 3e 3c 2f 63 6f 64 65 3e 20 61 6e 64 20 66 #> [15533] 72 69 65 6e 64 73 2e 20 59 6f 75 20 63 61 6e 20 6f 62 66 75 73 63 #> [15555] 61 74 65 20 6d 69 6c 64 6c 79 20 63 6f 6e 66 69 64 65 6e 74 69 61 #> [15577] 6c 20 64 61 74 61 20 77 69 74 68 20 3c 63 6f 64 65 3e 3c 61 20 68 #> [15599] 72 65 66 3d 22 72 65 66 65 72 65 6e 63 65 2f 6f 62 66 75 73 63 61 #> [15621] 74 65 2e 68 74 6d 6c 22 3e 6f 62 66 75 73 63 61 74 65 28 29 3c 2f #> [15643] 61 3e 3c 2f 63 6f 64 65 3e 2c 20 70 72 65 76 65 6e 74 69 6e 67 20 #> [15665] 69 74 20 66 72 6f 6d 20 62 65 69 6e 67 20 73 63 72 61 70 65 64 20 #> [15687] 66 72 6f 6d 20 70 75 62 6c 69 73 68 65 64 20 63 6f 64 65 2e 3c 2f #> [15709] 70 3e 3c 2f 6c 69 3e 0a 3c 6c 69 3e 3c 70 3e 59 6f 75 20 63 61 6e #> [15731] 20 61 75 74 6f 6d 61 74 69 63 61 6c 6c 79 20 63 61 63 68 65 20 61 #> [15753] 6c 6c 20 63 61 63 68 65 61 62 6c 65 20 72 65 73 75 6c 74 73 20 77 #> [15775] 69 74 68 20 3c 63 6f 64 65 3e 3c 61 20 68 72 65 66 3d 22 72 65 66 #> [15797] 65 72 65 6e 63 65 2f 72 65 71 5f 63 61 63 68 65 2e 68 74 6d 6c 22 #> [15819] 3e 72 65 71 5f 63 61 63 68 65 28 29 3c 2f 61 3e 3c 2f 63 6f 64 65 #> [15841] 3e 2e 20 52 65 6c 61 74 69 76 65 6c 79 20 66 65 77 20 41 50 49 20 #> [15863] 72 65 73 70 6f 6e 73 65 73 20 61 72 65 20 63 61 63 68 65 61 62 6c #> [15885] 65 2c 20 62 75 74 20 77 68 65 6e 20 74 68 65 79 20 61 72 65 20 69 #> [15907] 74 20 74 79 70 69 63 61 6c 6c 79 20 6d 61 6b 65 73 20 61 20 62 69 #> [15929] 67 20 64 69 66 66 65 72 65 6e 63 65 2e 3c 2f 70 3e 3c 2f 6c 69 3e #> [15951] 0a 3c 2f 75 6c 3e 0a 3c 2f 64 69 76 3e 0a 3c 64 69 76 20 63 6c 61 #> [15973] 73 73 3d 22 73 65 63 74 69 6f 6e 20 6c 65 76 65 6c 32 22 3e 0a 3c #> [15995] 68 32 20 69 64 3d 22 61 63 6b 6e 6f 77 6c 65 64 67 65 6d 65 6e 74 #> [16017] 73 22 3e 41 63 6b 6e 6f 77 6c 65 64 67 65 6d 65 6e 74 73 3c 61 20 #> [16039] 63 6c 61 73 73 3d 22 61 6e 63 68 6f 72 22 20 61 72 69 61 2d 6c 61 #> [16061] 62 65 6c 3d 22 61 6e 63 68 6f 72 22 20 68 72 65 66 3d 22 23 61 63 #> [16083] 6b 6e 6f 77 6c 65 64 67 65 6d 65 6e 74 73 22 3e 3c 2f 61 3e 0a 3c #> [16105] 2f 68 32 3e 0a 3c 70 3e 68 74 74 72 32 20 77 6f 75 6c 64 6e e2 80 #> [16127] 99 74 20 62 65 20 70 6f 73 73 69 62 6c 65 20 77 69 74 68 6f 75 74 #> [16149] 20 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 6a 65 72 6f #> [16171] 65 6e 2e 63 72 61 6e 2e 64 65 76 2f 63 75 72 6c 2f 22 20 63 6c 61 #> [16193] 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 63 75 72 #> [16215] 6c 3c 2f 61 3e 2c 20 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 3a #> [16237] 2f 2f 67 69 74 68 75 62 2e 63 6f 6d 2f 6a 65 72 6f 65 6e 2f 6f 70 #> [16259] 65 6e 73 73 6c 2f 22 20 63 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 #> [16281] 6c 2d 6c 69 6e 6b 22 3e 6f 70 65 6e 73 73 6c 3c 2f 61 3e 2c 20 3c #> [16303] 61 20 68 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 6a 65 72 6f 65 6e #> [16325] 2e 63 72 61 6e 2e 64 65 76 2f 6a 73 6f 6e 6c 69 74 65 2f 22 20 63 #> [16347] 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 6a #> [16369] 73 6f 6e 6c 69 74 65 3c 2f 61 3e 2c 20 61 6e 64 20 3c 61 20 68 72 #> [16391] 65 66 3d 22 68 74 74 70 73 3a 2f 2f 67 69 74 68 75 62 2e 63 6f 6d #> [16413] 2f 72 2d 6c 69 62 2f 6a 6f 73 65 2f 22 20 63 6c 61 73 73 3d 22 65 #> [16435] 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 6a 6f 73 65 3c 2f 61 3e #> [16457] 2c 20 77 68 69 63 68 20 61 72 65 20 61 6c 6c 20 6d 61 69 6e 74 61 #> [16479] 69 6e 65 64 20 62 79 20 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 #> [16501] 3a 2f 2f 67 69 74 68 75 62 2e 63 6f 6d 2f 6a 65 72 6f 65 6e 22 20 #> [16523] 63 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e #> [16545] 4a 65 72 6f 65 6e 20 4f 6f 6d 73 3c 2f 61 3e 2e 20 41 20 62 69 67 #> [16567] 20 74 68 61 6e 6b 73 20 61 6c 73 6f 20 67 6f 20 74 6f 20 3c 61 20 #> [16589] 68 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 6a 65 6e 6e 79 62 72 79 #> [16611] 61 6e 2e 6f 72 67 22 20 63 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 #> [16633] 6c 2d 6c 69 6e 6b 22 3e 4a 65 6e 6e 79 20 42 72 79 61 6e 3c 2f 61 #> [16655] 3e 20 61 6e 64 20 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 3a 2f #> [16677] 2f 77 77 77 2e 63 72 61 69 67 63 69 74 72 6f 2e 6f 72 67 22 20 63 #> [16699] 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 43 #> [16721] 72 61 69 67 20 43 69 74 72 6f 3c 2f 61 3e 20 77 68 6f 20 68 61 76 #> [16743] 65 20 67 69 76 65 6e 20 6d 65 20 6d 75 63 68 20 75 73 65 66 75 6c #> [16765] 20 66 65 65 64 62 61 63 6b 20 6f 6e 20 62 6f 74 68 20 74 68 65 20 #> [16787] 64 65 73 69 67 6e 20 6f 66 20 74 68 65 20 69 6e 74 65 72 6e 61 6c #> [16809] 73 20 61 6e 64 20 74 68 65 20 75 73 65 72 20 66 61 63 69 6e 67 20 #> [16831] 41 50 49 2e 3c 2f 70 3e 0a 3c 2f 64 69 76 3e 0a 3c 2f 64 69 76 3e #> [16853] 0a 20 20 3c 2f 6d 61 69 6e 3e 3c 61 73 69 64 65 20 63 6c 61 73 73 #> [16875] 3d 22 63 6f 6c 2d 6d 64 2d 33 22 3e 3c 64 69 76 20 63 6c 61 73 73 #> [16897] 3d 22 6c 69 6e 6b 73 22 3e 0a 3c 68 32 20 64 61 74 61 2d 74 6f 63 #> [16919] 2d 73 6b 69 70 3e 4c 69 6e 6b 73 3c 2f 68 32 3e 0a 3c 75 6c 20 63 #> [16941] 6c 61 73 73 3d 22 6c 69 73 74 2d 75 6e 73 74 79 6c 65 64 22 3e 0a #> [16963] 3c 6c 69 3e 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 63 #> [16985] 6c 6f 75 64 2e 72 2d 70 72 6f 6a 65 63 74 2e 6f 72 67 2f 70 61 63 #> [17007] 6b 61 67 65 3d 68 74 74 72 32 22 20 63 6c 61 73 73 3d 22 65 78 74 #> [17029] 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 56 69 65 77 20 6f 6e 20 43 52 #> [17051] 41 4e 3c 2f 61 3e 3c 2f 6c 69 3e 0a 3c 6c 69 3e 3c 61 20 68 72 65 #> [17073] 66 3d 22 68 74 74 70 73 3a 2f 2f 67 69 74 68 75 62 2e 63 6f 6d 2f #> [17095] 72 2d 6c 69 62 2f 68 74 74 72 32 2f 22 20 63 6c 61 73 73 3d 22 65 #> [17117] 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 42 72 6f 77 73 65 20 73 #> [17139] 6f 75 72 63 65 20 63 6f 64 65 3c 2f 61 3e 3c 2f 6c 69 3e 0a 3c 6c #> [17161] 69 3e 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 67 69 74 #> [17183] 68 75 62 2e 63 6f 6d 2f 72 2d 6c 69 62 2f 68 74 74 72 32 2f 69 73 #> [17205] 73 75 65 73 22 20 63 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d #> [17227] 6c 69 6e 6b 22 3e 52 65 70 6f 72 74 20 61 20 62 75 67 3c 2f 61 3e #> [17249] 3c 2f 6c 69 3e 0a 3c 2f 75 6c 3e 0a 3c 2f 64 69 76 3e 0a 0a 3c 64 #> [17271] 69 76 20 63 6c 61 73 73 3d 22 6c 69 63 65 6e 73 65 22 3e 0a 3c 68 #> [17293] 32 20 64 61 74 61 2d 74 6f 63 2d 73 6b 69 70 3e 4c 69 63 65 6e 73 #> [17315] 65 3c 2f 68 32 3e 0a 3c 75 6c 20 63 6c 61 73 73 3d 22 6c 69 73 74 #> [17337] 2d 75 6e 73 74 79 6c 65 64 22 3e 0a 3c 6c 69 3e 3c 61 20 68 72 65 #> [17359] 66 3d 22 4c 49 43 45 4e 53 45 2e 68 74 6d 6c 22 3e 46 75 6c 6c 20 #> [17381] 6c 69 63 65 6e 73 65 3c 2f 61 3e 3c 2f 6c 69 3e 0a 3c 6c 69 3e 3c #> [17403] 73 6d 61 6c 6c 3e 3c 61 20 68 72 65 66 3d 22 68 74 74 70 73 3a 2f #> [17425] 2f 6f 70 65 6e 73 6f 75 72 63 65 2e 6f 72 67 2f 6c 69 63 65 6e 73 #> [17447] 65 73 2f 6d 69 74 2d 6c 69 63 65 6e 73 65 2e 70 68 70 22 20 63 6c #> [17469] 61 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 4d 49 #> [17491] 54 3c 2f 61 3e 20 2b 20 66 69 6c 65 20 3c 61 20 68 72 65 66 3d 22 #> [17513] 4c 49 43 45 4e 53 45 2d 74 65 78 74 2e 68 74 6d 6c 22 3e 4c 49 43 #> [17535] 45 4e 53 45 3c 2f 61 3e 3c 2f 73 6d 61 6c 6c 3e 3c 2f 6c 69 3e 0a #> [17557] 3c 2f 75 6c 3e 0a 3c 2f 64 69 76 3e 0a 0a 0a 3c 64 69 76 20 63 6c #> [17579] 61 73 73 3d 22 63 69 74 61 74 69 6f 6e 22 3e 0a 3c 68 32 20 64 61 #> [17601] 74 61 2d 74 6f 63 2d 73 6b 69 70 3e 43 69 74 61 74 69 6f 6e 3c 2f #> [17623] 68 32 3e 0a 3c 75 6c 20 63 6c 61 73 73 3d 22 6c 69 73 74 2d 75 6e #> [17645] 73 74 79 6c 65 64 22 3e 0a 3c 6c 69 3e 3c 61 20 68 72 65 66 3d 22 #> [17667] 61 75 74 68 6f 72 73 2e 68 74 6d 6c 23 63 69 74 61 74 69 6f 6e 22 #> [17689] 3e 43 69 74 69 6e 67 20 68 74 74 72 32 3c 2f 61 3e 3c 2f 6c 69 3e #> [17711] 0a 3c 2f 75 6c 3e 0a 3c 2f 64 69 76 3e 0a 0a 3c 64 69 76 20 63 6c #> [17733] 61 73 73 3d 22 64 65 76 65 6c 6f 70 65 72 73 22 3e 0a 3c 68 32 20 #> [17755] 64 61 74 61 2d 74 6f 63 2d 73 6b 69 70 3e 44 65 76 65 6c 6f 70 65 #> [17777] 72 73 3c 2f 68 32 3e 0a 3c 75 6c 20 63 6c 61 73 73 3d 22 6c 69 73 #> [17799] 74 2d 75 6e 73 74 79 6c 65 64 22 3e 0a 3c 6c 69 3e 0a 3c 61 20 68 #> [17821] 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 68 61 64 6c 65 79 2e 6e 7a #> [17843] 22 20 63 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b #> [17865] 22 3e 48 61 64 6c 65 79 20 57 69 63 6b 68 61 6d 3c 2f 61 3e 20 3c #> [17887] 62 72 3e 3c 73 6d 61 6c 6c 20 63 6c 61 73 73 3d 22 72 6f 6c 65 73 #> [17909] 22 3e 20 41 75 74 68 6f 72 2c 20 6d 61 69 6e 74 61 69 6e 65 72 20 #> [17931] 3c 2f 73 6d 61 6c 6c 3e 20 20 3c 2f 6c 69 3e 0a 3c 6c 69 3e 0a 3c #> [17953] 61 20 68 72 65 66 3d 22 68 74 74 70 73 3a 2f 2f 77 77 77 2e 70 6f #> [17975] 73 69 74 2e 63 6f 22 20 63 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 #> [17997] 6c 2d 6c 69 6e 6b 22 3e 3c 69 6d 67 20 73 72 63 3d 22 68 74 74 70 #> [18019] 73 3a 2f 2f 77 77 77 2e 74 69 64 79 76 65 72 73 65 2e 6f 72 67 2f #> [18041] 70 6f 73 69 74 2d 6c 6f 67 6f 2e 73 76 67 22 20 61 6c 74 3d 22 50 #> [18063] 6f 73 69 74 22 20 68 65 69 67 68 74 3d 22 31 36 22 20 77 69 64 74 #> [18085] 68 3d 22 36 32 22 20 73 74 79 6c 65 3d 22 6d 61 72 67 69 6e 2d 62 #> [18107] 6f 74 74 6f 6d 3a 20 33 70 78 3b 22 3e 3c 2f 61 3e 20 3c 62 72 3e #> [18129] 3c 73 6d 61 6c 6c 20 63 6c 61 73 73 3d 22 72 6f 6c 65 73 22 3e 20 #> [18151] 43 6f 70 79 72 69 67 68 74 20 68 6f 6c 64 65 72 2c 20 66 75 6e 64 #> [18173] 65 72 20 3c 2f 73 6d 61 6c 6c 3e 20 20 3c 2f 6c 69 3e 0a 3c 6c 69 #> [18195] 3e 3c 61 20 68 72 65 66 3d 22 61 75 74 68 6f 72 73 2e 68 74 6d 6c #> [18217] 22 3e 4d 6f 72 65 20 61 62 6f 75 74 20 61 75 74 68 6f 72 73 2e 2e #> [18239] 2e 3c 2f 61 3e 3c 2f 6c 69 3e 0a 3c 2f 75 6c 3e 0a 3c 2f 64 69 76 #> [18261] 3e 0a 0a 0a 0a 20 20 3c 2f 61 73 69 64 65 3e 0a 3c 2f 64 69 76 3e #> [18283] 0a 0a 0a 20 20 20 3c 2f 64 69 76 3e 0a 20 20 3c 66 6f 6f 74 65 72 #> [18305] 3e 3c 64 69 76 20 63 6c 61 73 73 3d 22 63 6f 6e 74 61 69 6e 65 72 #> [18327] 22 3e 0a 20 20 3c 64 69 76 20 63 6c 61 73 73 3d 22 70 6b 67 64 6f #> [18349] 77 6e 2d 66 6f 6f 74 65 72 2d 6c 65 66 74 22 3e 0a 20 20 3c 70 3e #> [18371] 44 65 76 65 6c 6f 70 65 64 20 62 79 20 3c 61 20 68 72 65 66 3d 22 #> [18393] 68 74 74 70 73 3a 2f 2f 68 61 64 6c 65 79 2e 6e 7a 22 20 63 6c 61 #> [18415] 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 6e 6b 22 3e 48 61 64 #> [18437] 6c 65 79 20 57 69 63 6b 68 61 6d 3c 2f 61 3e 2c 20 3c 61 20 68 72 #> [18459] 65 66 3d 22 68 74 74 70 73 3a 2f 2f 77 77 77 2e 70 6f 73 69 74 2e #> [18481] 63 6f 22 20 63 6c 61 73 73 3d 22 65 78 74 65 72 6e 61 6c 2d 6c 69 #> [18503] 6e 6b 22 3e 3c 69 6d 67 20 73 72 63 3d 22 68 74 74 70 73 3a 2f 2f #> [18525] 77 77 77 2e 74 69 64 79 76 65 72 73 65 2e 6f 72 67 2f 70 6f 73 69 #> [18547] 74 2d 6c 6f 67 6f 2e 73 76 67 22 20 61 6c 74 3d 22 50 6f 73 69 74 #> [18569] 22 20 68 65 69 67 68 74 3d 22 31 36 22 20 77 69 64 74 68 3d 22 36 #> [18591] 32 22 20 73 74 79 6c 65 3d 22 6d 61 72 67 69 6e 2d 62 6f 74 74 6f #> [18613] 6d 3a 20 33 70 78 3b 22 3e 3c 2f 61 3e 2e 3c 2f 70 3e 0a 3c 2f 64 #> [18635] 69 76 3e 0a 0a 3c 64 69 76 20 63 6c 61 73 73 3d 22 70 6b 67 64 6f #> [18657] 77 6e 2d 66 6f 6f 74 65 72 2d 72 69 67 68 74 22 3e 0a 20 20 3c 70 #> [18679] 3e 53 69 74 65 20 62 75 69 6c 74 20 77 69 74 68 20 3c 61 20 68 72 #> [18701] 65 66 3d 22 68 74 74 70 73 3a 2f 2f 70 6b 67 64 6f 77 6e 2e 72 2d #> [18723] 6c 69 62 2e 6f 72 67 2f 22 20 63 6c 61 73 73 3d 22 65 78 74 65 72 #> [18745] 6e 61 6c 2d 6c 69 6e 6b 22 3e 70 6b 67 64 6f 77 6e 3c 2f 61 3e 20 #> [18767] 32 2e 31 2e 31 2e 3c 2f 70 3e 0a 3c 2f 64 69 76 3e 0a 0a 20 20 3c #> [18789] 2f 64 69 76 3e 3c 2f 66 6f 6f 74 65 72 3e 0a 3c 2f 62 6f 64 79 3e #> [18811] 0a 3c 2f 68 74 6d 6c 3e 0a resp |> resp_body_string() #> [1] \"<!DOCTYPE html>\\n<!-- Generated by pkgdown: do not edit by hand --><html lang=\\\"en\\\">\\n<head>\\n<meta http-equiv=\\\"Content-Type\\\" content=\\\"text/html; charset=UTF-8\\\">\\n<meta charset=\\\"utf-8\\\">\\n<meta http-equiv=\\\"X-UA-Compatible\\\" content=\\\"IE=edge\\\">\\n<meta name=\\\"viewport\\\" content=\\\"width=device-width, initial-scale=1, shrink-to-fit=no\\\">\\n<title>Perform HTTP Requests and Process the Responses • httr2<\/title>\\n<!-- favicons --><link rel=\\\"icon\\\" type=\\\"image/png\\\" sizes=\\\"16x16\\\" href=\\\"favicon-16x16.png\\\">\\n<link rel=\\\"icon\\\" type=\\\"image/png\\\" sizes=\\\"32x32\\\" href=\\\"favicon-32x32.png\\\">\\n<link rel=\\\"apple-touch-icon\\\" type=\\\"image/png\\\" sizes=\\\"180x180\\\" href=\\\"apple-touch-icon.png\\\">\\n<link rel=\\\"apple-touch-icon\\\" type=\\\"image/png\\\" sizes=\\\"120x120\\\" href=\\\"apple-touch-icon-120x120.png\\\">\\n<link rel=\\\"apple-touch-icon\\\" type=\\\"image/png\\\" sizes=\\\"76x76\\\" href=\\\"apple-touch-icon-76x76.png\\\">\\n<link rel=\\\"apple-touch-icon\\\" type=\\\"image/png\\\" sizes=\\\"60x60\\\" href=\\\"apple-touch-icon-60x60.png\\\">\\n<script src=\\\"deps/jquery-3.6.0/jquery-3.6.0.min.js\\\"><\/script><meta name=\\\"viewport\\\" content=\\\"width=device-width, initial-scale=1, shrink-to-fit=no\\\">\\n<link href=\\\"deps/bootstrap-5.3.1/bootstrap.min.css\\\" rel=\\\"stylesheet\\\">\\n<script src=\\\"deps/bootstrap-5.3.1/bootstrap.bundle.min.js\\\"><\/script><link href=\\\"deps/Source_Sans_Pro-0.4.9/font.css\\\" rel=\\\"stylesheet\\\">\\n<link href=\\\"deps/Source_Code_Pro-0.4.9/font.css\\\" rel=\\\"stylesheet\\\">\\n<link href=\\\"deps/font-awesome-6.4.2/css/all.min.css\\\" rel=\\\"stylesheet\\\">\\n<link href=\\\"deps/font-awesome-6.4.2/css/v4-shims.min.css\\\" rel=\\\"stylesheet\\\">\\n<script src=\\\"deps/headroom-0.11.0/headroom.min.js\\\"><\/script><script src=\\\"deps/headroom-0.11.0/jQuery.headroom.min.js\\\"><\/script><script src=\\\"deps/bootstrap-toc-1.0.1/bootstrap-toc.min.js\\\"><\/script><script src=\\\"deps/clipboard.js-2.0.11/clipboard.min.js\\\"><\/script><script src=\\\"deps/search-1.0.0/autocomplete.jquery.min.js\\\"><\/script><script src=\\\"deps/search-1.0.0/fuse.min.js\\\"><\/script><script src=\\\"deps/search-1.0.0/mark.min.js\\\"><\/script><!-- pkgdown --><script src=\\\"pkgdown.js\\\"><\/script><meta property=\\\"og:title\\\" content=\\\"Perform HTTP Requests and Process the Responses\\\">\\n<meta name=\\\"description\\\" content=\\\"Tools for creating and modifying HTTP requests, then performing them and processing the results. httr2 is a modern re-imagining of httr that uses a pipe-based interface and solves more of the problems that API wrapping packages face.\\\">\\n<meta property=\\\"og:description\\\" content=\\\"Tools for creating and modifying HTTP requests, then performing them and processing the results. httr2 is a modern re-imagining of httr that uses a pipe-based interface and solves more of the problems that API wrapping packages face.\\\">\\n<meta property=\\\"og:image\\\" content=\\\"https://httr2.r-lib.org/logo.png\\\">\\n<script defer data-domain=\\\"httr2.r-lib.org,all.tidyverse.org\\\" src=\\\"https://plausible.io/js/plausible.js\\\"><\/script>\\n<\/head>\\n<body>\\n <a href=\\\"#container\\\" class=\\\"visually-hidden-focusable\\\">Skip to content<\/a>\\n\\n\\n <nav class=\\\"navbar navbar-expand-lg fixed-top bg-none\\\" data-bs-theme=\\\"light\\\" aria-label=\\\"Site navigation\\\"><div class=\\\"container\\\">\\n\\n <a class=\\\"navbar-brand me-2\\\" href=\\\"index.html\\\">httr2<\/a>\\n\\n <small class=\\\"nav-text text-muted me-auto\\\" data-bs-toggle=\\\"tooltip\\\" data-bs-placement=\\\"bottom\\\" title=\\\"Released version\\\">1.0.5<\/small>\\n\\n\\n <button class=\\\"navbar-toggler\\\" type=\\\"button\\\" data-bs-toggle=\\\"collapse\\\" data-bs-target=\\\"#navbar\\\" aria-controls=\\\"navbar\\\" aria-expanded=\\\"false\\\" aria-label=\\\"Toggle navigation\\\">\\n <span class=\\\"navbar-toggler-icon\\\"><\/span>\\n <\/button>\\n\\n <div id=\\\"navbar\\\" class=\\\"collapse navbar-collapse ms-3\\\">\\n <ul class=\\\"navbar-nav me-auto\\\">\\n<li class=\\\"nav-item\\\"><a class=\\\"nav-link\\\" href=\\\"articles/httr2.html\\\">Get started<\/a><\/li>\\n<li class=\\\"nav-item\\\"><a class=\\\"nav-link\\\" href=\\\"reference/index.html\\\">Reference<\/a><\/li>\\n<li class=\\\"nav-item dropdown\\\">\\n <button class=\\\"nav-link dropdown-toggle\\\" type=\\\"button\\\" id=\\\"dropdown-articles\\\" data-bs-toggle=\\\"dropdown\\\" aria-expanded=\\\"false\\\" aria-haspopup=\\\"true\\\">Articles<\/button>\\n <ul class=\\\"dropdown-menu\\\" aria-labelledby=\\\"dropdown-articles\\\">\\n<li><a class=\\\"dropdown-item\\\" href=\\\"articles/wrapping-apis.html\\\">Wrapping APIs<\/a><\/li>\\n <li><a class=\\\"dropdown-item\\\" href=\\\"articles/oauth.html\\\">OAuth<\/a><\/li>\\n <\/ul>\\n<\/li>\\n<li class=\\\"nav-item dropdown\\\">\\n <button class=\\\"nav-link dropdown-toggle\\\" type=\\\"button\\\" id=\\\"dropdown-news\\\" data-bs-toggle=\\\"dropdown\\\" aria-expanded=\\\"false\\\" aria-haspopup=\\\"true\\\">News<\/button>\\n <ul class=\\\"dropdown-menu\\\" aria-labelledby=\\\"dropdown-news\\\">\\n<li><h6 class=\\\"dropdown-header\\\" data-toc-skip>Releases<\/h6><\/li>\\n <li><a class=\\\"external-link dropdown-item\\\" href=\\\"https://www.tidyverse.org/blog/2023/11/httr2-1-0-0/\\\">httr2 1.0.0<\/a><\/li>\\n <li><hr class=\\\"dropdown-divider\\\"><\/li>\\n <li><a class=\\\"dropdown-item\\\" href=\\\"news/index.html\\\">Changelog<\/a><\/li>\\n <\/ul>\\n<\/li>\\n <\/ul>\\n<ul class=\\\"navbar-nav\\\">\\n<li class=\\\"nav-item\\\"><form class=\\\"form-inline\\\" role=\\\"search\\\">\\n <input class=\\\"form-control\\\" type=\\\"search\\\" name=\\\"search-input\\\" id=\\\"search-input\\\" autocomplete=\\\"off\\\" aria-label=\\\"Search site\\\" placeholder=\\\"Search for\\\" data-search-index=\\\"search.json\\\">\\n<\/form><\/li>\\n<li class=\\\"nav-item\\\"><a class=\\\"external-link nav-link\\\" href=\\\"https://github.com/r-lib/httr2/\\\" aria-label=\\\"GitHub\\\"><span class=\\\"fa fab fa-github fa-lg\\\"><\/span><\/a><\/li>\\n <\/ul>\\n<\/div>\\n\\n\\n <\/div>\\n<\/nav><div class=\\\"container template-home\\\" id=\\\"container\\\">\\n<div class=\\\"row\\\">\\n <main id=\\\"main\\\" class=\\\"col-md-9\\\"><div class=\\\"section level1\\\">\\n<div class=\\\"page-header\\\">\\n<img src=\\\"logo.png\\\" class=\\\"logo\\\" alt=\\\"\\\"><h1 id=\\\"httr2-\\\">httr2 \\n<a class=\\\"anchor\\\" aria-label=\\\"anchor\\\" href=\\\"#httr2-\\\"><\/a>\\n<\/h1>\\n<\/div>\\n<!-- badges: start -->\\n\\n<p>httr2 (pronounced hitter2) is a ground-up rewrite of <a href=\\\"https://httr.r-lib.org\\\" class=\\\"external-link\\\">httr<\/a> that provides a pipeable API with an explicit request object that solves more problems felt by packages that wrap APIs (e.g. built-in rate-limiting, retries, OAuth, secure secrets, and more).<\/p>\\n<div class=\\\"section level2\\\">\\n<h2 id=\\\"installation\\\">Installation<a class=\\\"anchor\\\" aria-label=\\\"anchor\\\" href=\\\"#installation\\\"><\/a>\\n<\/h2>\\n<p>You can install httr2 from CRAN with:<\/p>\\n<div class=\\\"sourceCode\\\" id=\\\"cb1\\\"><pre class=\\\"downlit sourceCode r\\\">\\n<code class=\\\"sourceCode R\\\"><span><span class=\\\"fu\\\"><a href=\\\"https://rdrr.io/r/utils/install.packages.html\\\" class=\\\"external-link\\\">install.packages<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"st\\\">\\\"httr2\\\"<\/span><span class=\\\"op\\\">)<\/span><\/span><\/code><\/pre><\/div>\\n<\/div>\\n<div class=\\\"section level2\\\">\\n<h2 id=\\\"usage\\\">Usage<a class=\\\"anchor\\\" aria-label=\\\"anchor\\\" href=\\\"#usage\\\"><\/a>\\n<\/h2>\\n<p>To use httr2, start by creating a <strong>request<\/strong>:<\/p>\\n<div class=\\\"sourceCode\\\" id=\\\"cb2\\\"><pre class=\\\"downlit sourceCode r\\\">\\n<code class=\\\"sourceCode R\\\"><span><span class=\\\"kw\\\"><a href=\\\"https://rdrr.io/r/base/library.html\\\" class=\\\"external-link\\\">library<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"va\\\"><a href=\\\"https://httr2.r-lib.org\\\">httr2<\/a><\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><\/span>\\n<span><span class=\\\"va\\\">req<\/span> <span class=\\\"op\\\"><-<\/span> <span class=\\\"fu\\\"><a href=\\\"reference/request.html\\\">request<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"st\\\">\\\"https://r-project.org\\\"<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"va\\\">req<\/span><\/span>\\n<span><span class=\\\"co\\\">#> <httr2_request><\/span><\/span>\\n<span><span class=\\\"co\\\">#> GET https://r-project.org<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Body: empty<\/span><\/span><\/code><\/pre><\/div>\\n<p>You can tailor this request with the <code>req_<\/code> family of functions:<\/p>\\n<div class=\\\"sourceCode\\\" id=\\\"cb3\\\"><pre class=\\\"downlit sourceCode r\\\">\\n<code class=\\\"sourceCode R\\\"><span><span class=\\\"co\\\"># Add custom headers<\/span><\/span>\\n<span><span class=\\\"va\\\">req<\/span> <span class=\\\"op\\\">|><\/span> <span class=\\\"fu\\\"><a href=\\\"reference/req_headers.html\\\">req_headers<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"st\\\">\\\"Accept\\\"<\/span> <span class=\\\"op\\\">=<\/span> <span class=\\\"st\\\">\\\"application/json\\\"<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"co\\\">#> <httr2_request><\/span><\/span>\\n<span><span class=\\\"co\\\">#> GET https://r-project.org<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Headers:<\/span><\/span>\\n<span><span class=\\\"co\\\">#> • Accept: 'application/json'<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Body: empty<\/span><\/span>\\n<span><\/span>\\n<span><span class=\\\"co\\\"># Add a body, turning it into a POST<\/span><\/span>\\n<span><span class=\\\"va\\\">req<\/span> <span class=\\\"op\\\">|><\/span> <span class=\\\"fu\\\"><a href=\\\"reference/req_body.html\\\">req_body_json<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"fu\\\"><a href=\\\"https://rdrr.io/r/base/list.html\\\" class=\\\"external-link\\\">list<\/a><\/span><span class=\\\"op\\\">(<\/span>x <span class=\\\"op\\\">=<\/span> <span class=\\\"fl\\\">1<\/span>, y <span class=\\\"op\\\">=<\/span> <span class=\\\"fl\\\">2<\/span><span class=\\\"op\\\">)<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"co\\\">#> <httr2_request><\/span><\/span>\\n<span><span class=\\\"co\\\">#> POST https://r-project.org<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Body: json encoded data<\/span><\/span>\\n<span><\/span>\\n<span><span class=\\\"co\\\"># Modify the path in the url<\/span><\/span>\\n<span><span class=\\\"va\\\">req<\/span> <span class=\\\"op\\\">|><\/span> <span class=\\\"fu\\\"><a href=\\\"reference/req_url.html\\\">req_url_path<\/a><\/span><span class=\\\"op\\\">(<\/span>path <span class=\\\"op\\\">=<\/span> <span class=\\\"st\\\">\\\"path/to/my/file\\\"<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"co\\\">#> <httr2_request><\/span><\/span>\\n<span><span class=\\\"co\\\">#> GET https://r-project.org/path/to/my/file<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Body: empty<\/span><\/span>\\n<span><\/span>\\n<span><span class=\\\"co\\\"># Automatically retry if the request fails<\/span><\/span>\\n<span><span class=\\\"va\\\">req<\/span> <span class=\\\"op\\\">|><\/span> <span class=\\\"fu\\\"><a href=\\\"reference/req_retry.html\\\">req_retry<\/a><\/span><span class=\\\"op\\\">(<\/span>max_tries <span class=\\\"op\\\">=<\/span> <span class=\\\"fl\\\">5<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"co\\\">#> <httr2_request><\/span><\/span>\\n<span><span class=\\\"co\\\">#> GET https://r-project.org<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Body: empty<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Policies:<\/span><\/span>\\n<span><span class=\\\"co\\\">#> • retry_max_tries: 5<\/span><\/span>\\n<span><span class=\\\"co\\\">#> • retry_on_failure: FALSE<\/span><\/span>\\n<span><\/span>\\n<span><span class=\\\"co\\\"># Change the HTTP method<\/span><\/span>\\n<span><span class=\\\"va\\\">req<\/span> <span class=\\\"op\\\">|><\/span> <span class=\\\"fu\\\"><a href=\\\"reference/req_method.html\\\">req_method<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"st\\\">\\\"PATCH\\\"<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"co\\\">#> <httr2_request><\/span><\/span>\\n<span><span class=\\\"co\\\">#> PATCH https://r-project.org<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Body: empty<\/span><\/span><\/code><\/pre><\/div>\\n<p>And see exactly what httr2 will send to the server with <code><a href=\\\"reference/req_dry_run.html\\\">req_dry_run()<\/a><\/code>:<\/p>\\n<div class=\\\"sourceCode\\\" id=\\\"cb4\\\"><pre class=\\\"downlit sourceCode r\\\">\\n<code class=\\\"sourceCode R\\\"><span><span class=\\\"va\\\">req<\/span> <span class=\\\"op\\\">|><\/span> <span class=\\\"fu\\\"><a href=\\\"reference/req_dry_run.html\\\">req_dry_run<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"co\\\">#> GET / HTTP/1.1<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Host: r-project.org<\/span><\/span>\\n<span><span class=\\\"co\\\">#> User-Agent: httr2/1.0.3.9000 r-curl/5.2.2 libcurl/8.6.0<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Accept: */*<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Accept-Encoding: deflate, gzip<\/span><\/span><\/code><\/pre><\/div>\\n<p>Use <code><a href=\\\"reference/req_perform.html\\\">req_perform()<\/a><\/code> to perform the request, retrieving a <strong>response<\/strong>:<\/p>\\n<div class=\\\"sourceCode\\\" id=\\\"cb5\\\"><pre class=\\\"downlit sourceCode r\\\">\\n<code class=\\\"sourceCode R\\\"><span><span class=\\\"va\\\">resp<\/span> <span class=\\\"op\\\"><-<\/span> <span class=\\\"fu\\\"><a href=\\\"reference/req_perform.html\\\">req_perform<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"va\\\">req<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"va\\\">resp<\/span><\/span>\\n<span><span class=\\\"co\\\">#> <httr2_response><\/span><\/span>\\n<span><span class=\\\"co\\\">#> GET https://www.r-project.org/<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Status: 200 OK<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Content-Type: text/html<\/span><\/span>\\n<span><span class=\\\"co\\\">#> Body: In memory (6951 bytes)<\/span><\/span><\/code><\/pre><\/div>\\n<p>The <code>resp_<\/code> functions help you extract various useful components of the response:<\/p>\\n<div class=\\\"sourceCode\\\" id=\\\"cb6\\\"><pre class=\\\"downlit sourceCode r\\\">\\n<code class=\\\"sourceCode R\\\"><span><span class=\\\"va\\\">resp<\/span> <span class=\\\"op\\\">|><\/span> <span class=\\\"fu\\\"><a href=\\\"reference/resp_content_type.html\\\">resp_content_type<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"co\\\">#> [1] \\\"text/html\\\"<\/span><\/span>\\n<span><span class=\\\"va\\\">resp<\/span> <span class=\\\"op\\\">|><\/span> <span class=\\\"fu\\\"><a href=\\\"reference/resp_status.html\\\">resp_status_desc<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"co\\\">#> [1] \\\"OK\\\"<\/span><\/span>\\n<span><span class=\\\"va\\\">resp<\/span> <span class=\\\"op\\\">|><\/span> <span class=\\\"fu\\\"><a href=\\\"reference/resp_body_raw.html\\\">resp_body_html<\/a><\/span><span class=\\\"op\\\">(<\/span><span class=\\\"op\\\">)<\/span><\/span>\\n<span><span class=\\\"co\\\">#> {html_document}<\/span><\/span>\\n<span><span class=\\\"co\\\">#> <html lang=\\\"en\\\"><\/span><\/span>\\n<span><span class=\\\"co\\\">#> [1] <head>\\\\n<meta http-equiv=\\\"Content-Type\\\" content=\\\"text/html; charset=UTF-8 ...<\/span><\/span>\\n<span><span class=\\\"co\\\">#> [2] <body>\\\\n <div class=\\\"container page\\\">\\\\n <div class=\\\"row\\\">\\\\n ...<\/span><\/span><\/code><\/pre><\/div>\\n<\/div>\\n<div class=\\\"section level2\\\">\\n<h2 id=\\\"major-differences-to-httr\\\">Major differences to httr<a class=\\\"anchor\\\" aria-label=\\\"anchor\\\" href=\\\"#major-differences-to-httr\\\"><\/a>\\n<\/h2>\\n<ul>\\n<li><p>You can now create and modify a request without performing it. This means that there’s now a single function to perform the request and fetch the result: <code><a href=\\\"reference/req_perform.html\\\">req_perform()<\/a><\/code>. <code><a href=\\\"reference/req_perform.html\\\">req_perform()<\/a><\/code> replaces <code><a href=\\\"https://httr.r-lib.org/reference/GET.html\\\" class=\\\"external-link\\\">httr::GET()<\/a><\/code>, <code><a href=\\\"https://httr.r-lib.org/reference/POST.html\\\" class=\\\"external-link\\\">httr::POST()<\/a><\/code>, <code><a href=\\\"https://httr.r-lib.org/reference/DELETE.html\\\" class=\\\"external-link\\\">httr::DELETE()<\/a><\/code>, and more.<\/p><\/li>\\n<li><p>HTTP errors are automatically converted into R errors. Use <code><a href=\\\"reference/req_error.html\\\">req_error()<\/a><\/code> to override the defaults (which turn all 4xx and 5xx responses into errors) or to add additional details to the error message.<\/p><\/li>\\n<li><p>You can automatically retry if the request fails or encounters a transient HTTP error (e.g. a 429 rate limit request). <code><a href=\\\"reference/req_retry.html\\\">req_retry()<\/a><\/code> defines the maximum number of retries, which errors are transient, and how long to wait between tries.<\/p><\/li>\\n<li><p>OAuth support has been totally overhauled to directly support many more flows and to make it much easier to both customise the built-in flows and to create your own.<\/p><\/li>\\n<li><p>You can manage secrets (often needed for testing) with <code><a href=\\\"reference/secrets.html\\\">secret_encrypt()<\/a><\/code> and friends. You can obfuscate mildly confidential data with <code><a href=\\\"reference/obfuscate.html\\\">obfuscate()<\/a><\/code>, preventing it from being scraped from published code.<\/p><\/li>\\n<li><p>You can automatically cache all cacheable results with <code><a href=\\\"reference/req_cache.html\\\">req_cache()<\/a><\/code>. Relatively few API responses are cacheable, but when they are it typically makes a big difference.<\/p><\/li>\\n<\/ul>\\n<\/div>\\n<div class=\\\"section level2\\\">\\n<h2 id=\\\"acknowledgements\\\">Acknowledgements<a class=\\\"anchor\\\" aria-label=\\\"anchor\\\" href=\\\"#acknowledgements\\\"><\/a>\\n<\/h2>\\n<p>httr2 wouldn’t be possible without <a href=\\\"https://jeroen.cran.dev/curl/\\\" class=\\\"external-link\\\">curl<\/a>, <a href=\\\"https://github.com/jeroen/openssl/\\\" class=\\\"external-link\\\">openssl<\/a>, <a href=\\\"https://jeroen.cran.dev/jsonlite/\\\" class=\\\"external-link\\\">jsonlite<\/a>, and <a href=\\\"https://github.com/r-lib/jose/\\\" class=\\\"external-link\\\">jose<\/a>, which are all maintained by <a href=\\\"https://github.com/jeroen\\\" class=\\\"external-link\\\">Jeroen Ooms<\/a>. A big thanks also go to <a href=\\\"https://jennybryan.org\\\" class=\\\"external-link\\\">Jenny Bryan<\/a> and <a href=\\\"https://www.craigcitro.org\\\" class=\\\"external-link\\\">Craig Citro<\/a> who have given me much useful feedback on both the design of the internals and the user facing API.<\/p>\\n<\/div>\\n<\/div>\\n <\/main><aside class=\\\"col-md-3\\\"><div class=\\\"links\\\">\\n<h2 data-toc-skip>Links<\/h2>\\n<ul class=\\\"list-unstyled\\\">\\n<li><a href=\\\"https://cloud.r-project.org/package=httr2\\\" class=\\\"external-link\\\">View on CRAN<\/a><\/li>\\n<li><a href=\\\"https://github.com/r-lib/httr2/\\\" class=\\\"external-link\\\">Browse source code<\/a><\/li>\\n<li><a href=\\\"https://github.com/r-lib/httr2/issues\\\" class=\\\"external-link\\\">Report a bug<\/a><\/li>\\n<\/ul>\\n<\/div>\\n\\n<div class=\\\"license\\\">\\n<h2 data-toc-skip>License<\/h2>\\n<ul class=\\\"list-unstyled\\\">\\n<li><a href=\\\"LICENSE.html\\\">Full license<\/a><\/li>\\n<li><small><a href=\\\"https://opensource.org/licenses/mit-license.php\\\" class=\\\"external-link\\\">MIT<\/a> + file <a href=\\\"LICENSE-text.html\\\">LICENSE<\/a><\/small><\/li>\\n<\/ul>\\n<\/div>\\n\\n\\n<div class=\\\"citation\\\">\\n<h2 data-toc-skip>Citation<\/h2>\\n<ul class=\\\"list-unstyled\\\">\\n<li><a href=\\\"authors.html#citation\\\">Citing httr2<\/a><\/li>\\n<\/ul>\\n<\/div>\\n\\n<div class=\\\"developers\\\">\\n<h2 data-toc-skip>Developers<\/h2>\\n<ul class=\\\"list-unstyled\\\">\\n<li>\\n<a href=\\\"https://hadley.nz\\\" class=\\\"external-link\\\">Hadley Wickham<\/a> <br><small class=\\\"roles\\\"> Author, maintainer <\/small> <\/li>\\n<li>\\n<a href=\\\"https://www.posit.co\\\" class=\\\"external-link\\\"><img src=\\\"https://www.tidyverse.org/posit-logo.svg\\\" alt=\\\"Posit\\\" height=\\\"16\\\" width=\\\"62\\\" style=\\\"margin-bottom: 3px;\\\"><\/a> <br><small class=\\\"roles\\\"> Copyright holder, funder <\/small> <\/li>\\n<li><a href=\\\"authors.html\\\">More about authors...<\/a><\/li>\\n<\/ul>\\n<\/div>\\n\\n\\n\\n <\/aside>\\n<\/div>\\n\\n\\n <\/div>\\n <footer><div class=\\\"container\\\">\\n <div class=\\\"pkgdown-footer-left\\\">\\n <p>Developed by <a href=\\\"https://hadley.nz\\\" class=\\\"external-link\\\">Hadley Wickham<\/a>, <a href=\\\"https://www.posit.co\\\" class=\\\"external-link\\\"><img src=\\\"https://www.tidyverse.org/posit-logo.svg\\\" alt=\\\"Posit\\\" height=\\\"16\\\" width=\\\"62\\\" style=\\\"margin-bottom: 3px;\\\"><\/a>.<\/p>\\n<\/div>\\n\\n<div class=\\\"pkgdown-footer-right\\\">\\n <p>Site built with <a href=\\\"https://pkgdown.r-lib.org/\\\" class=\\\"external-link\\\">pkgdown<\/a> 2.1.1.<\/p>\\n<\/div>\\n\\n <\/div><\/footer>\\n<\/body>\\n<\/html>\\n\" if (requireNamespace(\"xml2\", quietly = TRUE)) { resp |> resp_body_html() } #> {html_document} #> <html lang=\"en\"> #> [1] <head>\\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset ... #> [2] <body>\\n <a href=\"#container\" class=\"visually-hidden-focusable\"> ..."},{"path":"https://httr2.r-lib.org/dev/reference/resp_check_content_type.html","id":null,"dir":"Reference","previous_headings":"","what":"Check the content type of a response — resp_check_content_type","title":"Check the content type of a response — resp_check_content_type","text":"different content type expected often leads error parsing response body. function checks content type response expected fails otherwise.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_check_content_type.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Check the content type of a response — resp_check_content_type","text":"","code":"resp_check_content_type( resp, valid_types = NULL, valid_suffix = NULL, check_type = TRUE, call = caller_env() )"},{"path":"https://httr2.r-lib.org/dev/reference/resp_check_content_type.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Check the content type of a response — resp_check_content_type","text":"resp httr2 response object, created req_perform(). valid_types character vector valid MIME types. specified type/subtype. valid_suffix string given \"structured media type\" suffix. check_type type actually checked? Provided convenience using function inside resp_body_* helpers. call execution environment currently running function, e.g. caller_env(). function mentioned error messages source error. See call argument abort() information.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_check_content_type.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Check the content type of a response — resp_check_content_type","text":"Called side-effect; erroring response expected content type.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_check_content_type.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Check the content type of a response — resp_check_content_type","text":"","code":"resp <- response(headers = list(`content-type` = \"application/json\")) resp_check_content_type(resp, \"application/json\") try(resp_check_content_type(resp, \"application/xml\")) #> Error in eval(expr, envir) : #> Unexpected content type \"application/json\". #> • Expecting type \"application/xml\" # `types` can also specify multiple valid types resp_check_content_type(resp, c(\"application/xml\", \"application/json\"))"},{"path":"https://httr2.r-lib.org/dev/reference/resp_content_type.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract response content type and encoding — resp_content_type","title":"Extract response content type and encoding — resp_content_type","text":"resp_content_type() returns just type subtype Content-Type header. Content-Type provided; returns NA. Used resp_body_json(), resp_body_html(), resp_body_xml(). resp_encoding() returns likely character encoding text types, parsed charset parameter Content-Type header. header found, valid, charset parameter found, returns UTF-8. Used resp_body_string().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_content_type.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract response content type and encoding — resp_content_type","text":"","code":"resp_content_type(resp) resp_encoding(resp)"},{"path":"https://httr2.r-lib.org/dev/reference/resp_content_type.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract response content type and encoding — resp_content_type","text":"resp httr2 response object, created req_perform().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_content_type.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract response content type and encoding — resp_content_type","text":"string. content type specified resp_content_type() return character NA; encoding specified, resp_encoding() return \"UTF-8\".","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_content_type.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract response content type and encoding — resp_content_type","text":"","code":"resp <- response(headers = \"Content-type: text/html; charset=utf-8\") resp |> resp_content_type() #> [1] \"text/html\" resp |> resp_encoding() #> [1] \"utf-8\" # No Content-Type header resp <- response() resp |> resp_content_type() #> [1] NA resp |> resp_encoding() #> [1] \"UTF-8\""},{"path":"https://httr2.r-lib.org/dev/reference/resp_date.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract request date from response — resp_date","title":"Extract request date from response — resp_date","text":"responses contain request date Date header; provided server automatically added httr2.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_date.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract request date from response — resp_date","text":"","code":"resp_date(resp)"},{"path":"https://httr2.r-lib.org/dev/reference/resp_date.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract request date from response — resp_date","text":"resp httr2 response object, created req_perform().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_date.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract request date from response — resp_date","text":"POSIXct date-time.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_date.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract request date from response — resp_date","text":"","code":"resp <- response(headers = \"Date: Wed, 01 Jan 2020 09:23:15 UTC\") resp |> resp_date() #> [1] \"2020-01-01 09:23:15 UTC\" # If server doesn't add header (unusual), you get the time the request # was created: resp <- response() resp |> resp_date() #> [1] \"2020-01-01 UTC\""},{"path":"https://httr2.r-lib.org/dev/reference/resp_headers.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract headers from a response — resp_headers","title":"Extract headers from a response — resp_headers","text":"resp_headers() retrieves list headers. resp_header() retrieves single header. resp_header_exists() checks header present.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_headers.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract headers from a response — resp_headers","text":"","code":"resp_headers(resp, filter = NULL) resp_header(resp, header, default = NULL) resp_header_exists(resp, header)"},{"path":"https://httr2.r-lib.org/dev/reference/resp_headers.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract headers from a response — resp_headers","text":"resp httr2 response object, created req_perform(). filter regular expression used filter header names. NULL, default, returns headers. header Header name (case insensitive) default Default value use header exist.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_headers.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract headers from a response — resp_headers","text":"resp_headers() returns list. resp_header() returns string header exists NULL otherwise. resp_header_exists() returns TRUE FALSE.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_headers.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract headers from a response — resp_headers","text":"","code":"resp <- request(\"https://httr2.r-lib.org\") |> req_perform() resp |> resp_headers() #> <httr2_headers> #> server: GitHub.com #> content-type: text/html; charset=utf-8 #> last-modified: Wed, 23 Oct 2024 18:14:33 GMT #> access-control-allow-origin: * #> etag: W/\"67193d09-4983\" #> expires: Wed, 23 Oct 2024 22:20:36 GMT #> cache-control: max-age=600 #> content-encoding: gzip #> x-proxy-cache: MISS #> x-github-request-id: 97CB:344448:46EAD9:50CD81:67197452 #> accept-ranges: bytes #> date: Wed, 23 Oct 2024 22:10:56 GMT #> via: 1.1 varnish #> age: 21 #> x-served-by: cache-chi-kigq8000144-CHI #> x-cache: HIT #> x-cache-hits: 4 #> x-timer: S1729721456.282504,VS0,VE0 #> vary: Accept-Encoding #> x-fastly-request-id: 32b8f7cffaabcc81b513bca3daae79b78f5123b4 #> content-length: 4636 resp |> resp_headers(\"x-\") #> <httr2_headers> #> x-proxy-cache: MISS #> x-github-request-id: 97CB:344448:46EAD9:50CD81:67197452 #> x-served-by: cache-chi-kigq8000144-CHI #> x-cache: HIT #> x-cache-hits: 4 #> x-timer: S1729721456.282504,VS0,VE0 #> x-fastly-request-id: 32b8f7cffaabcc81b513bca3daae79b78f5123b4 resp |> resp_header_exists(\"server\") #> [1] TRUE resp |> resp_header(\"server\") #> [1] \"GitHub.com\" # Headers are case insensitive resp |> resp_header(\"SERVER\") #> [1] \"GitHub.com\" # Returns NULL if header doesn't exist resp |> resp_header(\"this-header-doesnt-exist\") #> NULL"},{"path":"https://httr2.r-lib.org/dev/reference/resp_link_url.html","id":null,"dir":"Reference","previous_headings":"","what":"Parse link URL from a response — resp_link_url","title":"Parse link URL from a response — resp_link_url","text":"Parses URLs Link header defined RFC 8288.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_link_url.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Parse link URL from a response — resp_link_url","text":"","code":"resp_link_url(resp, rel)"},{"path":"https://httr2.r-lib.org/dev/reference/resp_link_url.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Parse link URL from a response — resp_link_url","text":"resp httr2 response object, created req_perform(). rel \"link relation type\" value retrieve URL.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_link_url.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Parse link URL from a response — resp_link_url","text":"Either string providing URL, specified rel exists, NULL .","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_link_url.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Parse link URL from a response — resp_link_url","text":"","code":"# Simulate response from GitHub code search resp <- response(headers = paste0(\"Link: \", '<https://api.github.com/search/code?q=addClass+user%3Amozilla&page=2>; rel=\"next\",', '<https://api.github.com/search/code?q=addClass+user%3Amozilla&page=34>; rel=\"last\"' )) resp_link_url(resp, \"next\") #> [1] \"https://api.github.com/search/code?q=addClass+user%3Amozilla&page=2\" resp_link_url(resp, \"last\") #> [1] \"https://api.github.com/search/code?q=addClass+user%3Amozilla&page=34\" resp_link_url(resp, \"prev\") #> NULL"},{"path":"https://httr2.r-lib.org/dev/reference/resp_raw.html","id":null,"dir":"Reference","previous_headings":"","what":"Show the raw response — resp_raw","title":"Show the raw response — resp_raw","text":"function reconstructs HTTP message httr2 received server. unlikely exactly byte--byte identical (servers compress least body, HTTP/2 can also compress headers), conveys information.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_raw.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Show the raw response — resp_raw","text":"","code":"resp_raw(resp)"},{"path":"https://httr2.r-lib.org/dev/reference/resp_raw.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Show the raw response — resp_raw","text":"resp httr2 response object, created req_perform().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_raw.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Show the raw response — resp_raw","text":"resp (invisibly).","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_raw.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Show the raw response — resp_raw","text":"","code":"resp <- request(example_url()) |> req_url_path(\"/json\") |> req_perform() resp |> resp_raw() #> HTTP/1.1 200 OK #> Connection: close #> Date: Wed, 23 Oct 2024 22:10:56 GMT #> Content-Type: application/json #> Content-Length: 407 #> ETag: \"de760e6d\" #> #> { #> \"firstName\": \"John\", #> \"lastName\": \"Smith\", #> \"isAlive\": true, #> \"age\": 27, #> \"address\": { #> \"streetAddress\": \"21 2nd Street\", #> \"city\": \"New York\", #> \"state\": \"NY\", #> \"postalCode\": \"10021-3100\" #> }, #> \"phoneNumbers\": [ #> { #> \"type\": \"home\", #> \"number\": \"212 555-1234\" #> }, #> { #> \"type\": \"office\", #> \"number\": \"646 555-4567\" #> } #> ], #> \"children\": [], #> \"spouse\": null #> } #>"},{"path":"https://httr2.r-lib.org/dev/reference/resp_retry_after.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract wait time from a response — resp_retry_after","title":"Extract wait time from a response — resp_retry_after","text":"Computes many seconds wait retrying request inspecting Retry-header. parses forms (absolute relative) returns number seconds wait. heading found, return NA.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_retry_after.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract wait time from a response — resp_retry_after","text":"","code":"resp_retry_after(resp)"},{"path":"https://httr2.r-lib.org/dev/reference/resp_retry_after.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract wait time from a response — resp_retry_after","text":"resp httr2 response object, created req_perform().","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_retry_after.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract wait time from a response — resp_retry_after","text":"Scalar double giving number seconds wait retrying request.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_retry_after.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract wait time from a response — resp_retry_after","text":"","code":"resp <- response(headers = \"Retry-After: 30\") resp |> resp_retry_after() #> [1] 30 resp <- response(headers = \"Retry-After: Mon, 20 Sep 2025 21:44:05 UTC\") resp |> resp_retry_after() #> [1] 180567845"},{"path":"https://httr2.r-lib.org/dev/reference/resp_status.html","id":null,"dir":"Reference","previous_headings":"","what":"Extract HTTP status from response — resp_status","title":"Extract HTTP status from response — resp_status","text":"resp_status() retrieves numeric HTTP status code resp_status_desc() retrieves brief textual description. resp_is_error() returns TRUE status code represents error (.e. 4xx 5xx status). resp_check_status() turns HTTPs errors R errors. functions mostly internal use cases ever see 200 response: 1xx handled internally curl. 3xx redirects automatically followed. see deliberately suppressed redirects req |> req_options(followlocation = FALSE). 4xx client 5xx server errors automatically turned R errors. can stop turned R errors req_error(), e.g. req |> req_error(is_error = ~ FALSE).","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_status.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Extract HTTP status from response — resp_status","text":"","code":"resp_status(resp) resp_status_desc(resp) resp_is_error(resp) resp_check_status(resp, info = NULL, error_call = caller_env())"},{"path":"https://httr2.r-lib.org/dev/reference/resp_status.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Extract HTTP status from response — resp_status","text":"resp httr2 response object, created req_perform(). info character vector additional information include error message. Passed rlang::abort(). error_call execution environment currently running function, e.g. caller_env(). function mentioned error messages source error. See call argument abort() information.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_status.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Extract HTTP status from response — resp_status","text":"resp_status() returns scalar integer resp_status_desc() returns string resp_is_error() returns TRUE FALSE resp_check_status() invisibly returns response ok; otherwise throws error class httr2_http_{status}.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_status.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Extract HTTP status from response — resp_status","text":"","code":"# An HTTP status code you're unlikely to see in the wild: resp <- response(418) resp |> resp_is_error() #> [1] TRUE resp |> resp_status() #> [1] 418 resp |> resp_status_desc() #> [1] \"I'm a teapot\""},{"path":"https://httr2.r-lib.org/dev/reference/resp_stream_raw.html","id":null,"dir":"Reference","previous_headings":"","what":"Read a streaming body a chunk at a time — resp_stream_raw","title":"Read a streaming body a chunk at a time — resp_stream_raw","text":"resp_stream_raw() retrieves bytes (raw vectors). resp_stream_lines() retrieves lines text (character vectors). resp_stream_sse() retrieves single server-sent event. resp_stream_aws() retrieves single event AWS stream (.e. mime type `application/vnd.amazon.eventstream“).","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_stream_raw.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Read a streaming body a chunk at a time — resp_stream_raw","text":"","code":"resp_stream_raw(resp, kb = 32) resp_stream_lines(resp, lines = 1, max_size = Inf, warn = TRUE) resp_stream_sse(resp, max_size = Inf) resp_stream_aws(resp, max_size = Inf) # S3 method for class 'httr2_response' close(con, ...)"},{"path":"https://httr2.r-lib.org/dev/reference/resp_stream_raw.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Read a streaming body a chunk at a time — resp_stream_raw","text":"resp, con streaming response created req_perform_connection(). kb many kilobytes (1024 bytes) data read. lines maximum number lines return . max_size maximum number bytes buffer; number bytes exceeded without line/event boundary, error thrown. warn Like readLines(): warn connection ends without final EOL. ... used; included compatibility generic.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_stream_raw.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Read a streaming body a chunk at a time — resp_stream_raw","text":"resp_stream_raw(): raw vector. resp_stream_lines(): character vector. resp_stream_sse(): list components type, data, id resp_stream_aws(): list components headers body. body automatically parsed event contents :content-type header application/json. resp_stream_sse() resp_stream_aws() return NULL signal end stream reached , nonblocking mode, event currently available.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_url.html","id":null,"dir":"Reference","previous_headings":"","what":"Get URL/components from the response — resp_url","title":"Get URL/components from the response — resp_url","text":"resp_url() returns complete url. resp_url_path() returns path component. resp_url_query() returns single query component. resp_url_queries() returns query component named list.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_url.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Get URL/components from the response — resp_url","text":"","code":"resp_url(resp) resp_url_path(resp) resp_url_query(resp, name, default = NULL) resp_url_queries(resp)"},{"path":"https://httr2.r-lib.org/dev/reference/resp_url.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Get URL/components from the response — resp_url","text":"resp httr2 response object, created req_perform(). name Query parameter name. default Default value use query parameter exist.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resp_url.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Get URL/components from the response — resp_url","text":"","code":"resp <- request(example_url()) |> req_url_path(\"/get?hello=world\") |> req_perform() resp |> resp_url() #> [1] \"http://127.0.0.1:36861/get?hello=world\" resp |> resp_url_path() #> [1] \"/get\" resp |> resp_url_queries() #> $hello #> [1] \"world\" #> resp |> resp_url_query(\"hello\") #> [1] \"world\""},{"path":"https://httr2.r-lib.org/dev/reference/response.html","id":null,"dir":"Reference","previous_headings":"","what":"Create a new HTTP response — response","title":"Create a new HTTP response — response","text":"Generally, need call function directly; get real HTTP response calling req_perform() friends. function provided primarily testing, place describe key components response. response() creates generic response; response_json() creates response JSON body, automatically adding correct Content-Type header.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/response.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Create a new HTTP response — response","text":"","code":"response( status_code = 200, url = \"https://example.com\", method = \"GET\", headers = list(), body = raw() ) response_json( status_code = 200, url = \"https://example.com\", method = \"GET\", headers = list(), body = list() )"},{"path":"https://httr2.r-lib.org/dev/reference/response.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Create a new HTTP response — response","text":"status_code HTTP status code. Must single integer. url URL response came ; might URL request redirects. method HTTP method used retrieve response. headers HTTP headers. Can supplied raw character vector parsed using standard rules, named list. body Response, , contained response body. response_json(), R data structure serialize JSON.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/response.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Create a new HTTP response — response","text":"HTTP response: S3 list class httr2_response.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/response.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Create a new HTTP response — response","text":"","code":"response() #> <httr2_response> #> GET https://example.com #> Status: 200 OK #> Body: None response(404, method = \"POST\") #> <httr2_response> #> POST https://example.com #> Status: 404 Not Found #> Body: None response(headers = c(\"Content-Type: text/html\", \"Content-Length: 300\")) #> <httr2_response> #> GET https://example.com #> Status: 200 OK #> Content-Type: text/html #> Body: None"},{"path":"https://httr2.r-lib.org/dev/reference/resps_successes.html","id":null,"dir":"Reference","previous_headings":"","what":"Tools for working with lists of responses — resps_successes","title":"Tools for working with lists of responses — resps_successes","text":"function provide basic toolkit operating lists responses possibly errors, returned req_perform_parallel(), req_perform_sequential() req_perform_iterative(). resps_successes() returns list successful responses. resps_failures() returns list failed responses (.e. errors). resps_requests() returns list requests corresponds request. resps_data() returns data single vector data frame. requires vctrs package installed.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resps_successes.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Tools for working with lists of responses — resps_successes","text":"","code":"resps_successes(resps) resps_failures(resps) resps_requests(resps) resps_data(resps, resp_data)"},{"path":"https://httr2.r-lib.org/dev/reference/resps_successes.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Tools for working with lists of responses — resps_successes","text":"resps list responses (possibly including errors). resp_data function takes response (resp) returns data found inside response vector data frame.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/resps_successes.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Tools for working with lists of responses — resps_successes","text":"","code":"reqs <- list( request(example_url()) |> req_url_path(\"/ip\"), request(example_url()) |> req_url_path(\"/user-agent\"), request(example_url()) |> req_template(\"/status/:status\", status = 404), request(\"INVALID\") ) resps <- req_perform_parallel(reqs, on_error = \"continue\") # find successful responses resps |> resps_successes() #> [[1]] #> <httr2_response> #> GET http://127.0.0.1:36861/ip #> Status: 200 OK #> Content-Type: application/json #> Body: In memory (27 bytes) #> #> [[2]] #> <httr2_response> #> GET http://127.0.0.1:36861/user-agent #> Status: 200 OK #> Content-Type: application/json #> Body: In memory (66 bytes) #> # collect all their data resps |> resps_successes() |> resps_data(\\(resp) resp_body_json(resp)) #> $origin #> [1] \"127.0.0.1\" #> #> $`user-agent` #> [1] \"httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0\" #> # find requests corresponding to failure responses resps |> resps_failures() |> resps_requests() #> [[1]] #> <httr2_request> #> GET http://127.0.0.1:36861/status/404 #> Body: empty #> #> [[2]] #> <httr2_request> #> GET INVALID #> Body: empty #>"},{"path":"https://httr2.r-lib.org/dev/reference/secrets.html","id":null,"dir":"Reference","previous_headings":"","what":"Secret management — secrets","title":"Secret management — secrets","text":"httr2 provides handful functions designed working confidential data. useful testing packages use httr2 often requires confidential data needs available testing, available package users. secret_encrypt() secret_decrypt() work individual strings secret_encrypt_file() encrypts file place secret_decrypt_file() decrypts file temporary location. secret_write_rds() secret_read_rds() work .rds files secret_make_key() generates random string use key. secret_has_key() returns TRUE key available; can use examples vignettes want evaluate CI, CRAN/package users. look key environment variable. used inside testthat, automatically testthat::skip() test env var found. (Outside testthat, error env var found.)","code":""},{"path":"https://httr2.r-lib.org/dev/reference/secrets.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Secret management — secrets","text":"","code":"secret_make_key() secret_encrypt(x, key) secret_decrypt(encrypted, key) secret_write_rds(x, path, key) secret_read_rds(path, key) secret_decrypt_file(path, key, envir = parent.frame()) secret_encrypt_file(path, key) secret_has_key(key)"},{"path":"https://httr2.r-lib.org/dev/reference/secrets.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Secret management — secrets","text":"x Object encrypt. Must string secret_encrypt(). key Encryption key; password allows \"lock\" \"unlock\" secret. easiest way specify name environment variable. Alternatively, already base64url encoded string, can wrap (), can pass raw vector directly. encrypted String decrypt path Path file encrypted file read write. secret_write_rds() secret_read_rds() .rds file. envir decrypted file automatically deleted environment exits. need set argument want pass unencrypted file another function.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/secrets.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Secret management — secrets","text":"secret_decrypt() secret_encrypt() return strings. secret_decrypt_file() returns path temporary file; secret_encrypt_file() encrypts file place. secret_write_rds() returns x invisibly; secret_read_rds() returns saved object. secret_make_key() returns string class AsIs. secret_has_key() returns TRUE FALSE.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/secrets.html","id":"basic-workflow","dir":"Reference","previous_headings":"","what":"Basic workflow","title":"Secret management — secrets","text":"Use secret_make_key() generate password. Make available env var (e.g. {MYPACKAGE}_KEY) adding line .Renviron. Encrypt strings secret_encrypt(), files secret_encrypt_file(), data secret_write_rds(), setting key = \"{MYPACKAGE}_KEY\". tests, decrypt data secret_decrypt(), secret_decrypt_file(), secret_read_rds() match encrypt . push code CI server, already \"work\" functions automatically skip tests {MYPACKAGE}_KEY env var set. make tests actually run, need set env var using whatever tool CI system provides setting env vars. Make sure carefully inspect test output check skips actually gone away.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/secrets.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Secret management — secrets","text":"","code":"key <- secret_make_key() path <- tempfile() secret_write_rds(mtcars, path, key = key) secret_read_rds(path, key) #> mpg cyl disp hp drat wt qsec vs am gear carb #> Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 #> Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 #> Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 #> Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 #> Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 #> Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 #> Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 #> Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 #> Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 #> Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4 #> Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4 #> Merc 450SE 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3 #> Merc 450SL 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3 #> Merc 450SLC 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3 #> Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4 #> Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4 #> Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4 #> Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1 #> Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2 #> Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1 #> Toyota Corona 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1 #> Dodge Challenger 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2 #> AMC Javelin 15.2 8 304.0 150 3.15 3.435 17.30 0 0 3 2 #> Camaro Z28 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4 #> Pontiac Firebird 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2 #> Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1 #> Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2 #> Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2 #> Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4 #> Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6 #> Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8 #> Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2 # While you can manage the key explicitly in a variable, it's much # easier to store in an environment variable. In real life, you should # NEVER use `Sys.setenv()` to create this env var because you will # also store the secret in your `.Rhistory`. Instead add it to your # .Renviron using `usethis::edit_r_environ()` or similar. Sys.setenv(\"MY_KEY\" = key) x <- secret_encrypt(\"This is a secret\", \"MY_KEY\") x #> [1] \"eEsy_KyOO1gCv-928d7NXuA48sPE41dbroIO_31fFI8\" secret_decrypt(x, \"MY_KEY\") #> [1] \"This is a secret\""},{"path":"https://httr2.r-lib.org/dev/reference/signal_total_pages.html","id":null,"dir":"Reference","previous_headings":"","what":"Signal total number pages — signal_total_pages","title":"Signal total number pages — signal_total_pages","text":"called within next_req callback function used req_perform_iterative()","code":""},{"path":"https://httr2.r-lib.org/dev/reference/signal_total_pages.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Signal total number pages — signal_total_pages","text":"","code":"signal_total_pages(n)"},{"path":"https://httr2.r-lib.org/dev/reference/signal_total_pages.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Signal total number pages — signal_total_pages","text":"n Total number pages.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/throttle_status.html","id":null,"dir":"Reference","previous_headings":"","what":"Display internal throttle status — throttle_status","title":"Display internal throttle status — throttle_status","text":"Sometimes useful debugging.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/throttle_status.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Display internal throttle status — throttle_status","text":"","code":"throttle_status()"},{"path":"https://httr2.r-lib.org/dev/reference/throttle_status.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Display internal throttle status — throttle_status","text":"data frame two columns: realm time last_request made.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/url_parse.html","id":null,"dir":"Reference","previous_headings":"","what":"Parse and build URLs — url_parse","title":"Parse and build URLs — url_parse","text":"url_parse() parses URL component pieces; url_build() reverse, converting list pieces string URL. See RFC 3986 details parsing algorithm.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/url_parse.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Parse and build URLs — url_parse","text":"","code":"url_parse(url) url_build(url)"},{"path":"https://httr2.r-lib.org/dev/reference/url_parse.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Parse and build URLs — url_parse","text":"url url_parse() string parse URL; url_build() URL turn back string.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/url_parse.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Parse and build URLs — url_parse","text":"url_build() returns string. url_parse() returns URL: S3 list class httr2_url elements scheme, hostname, port, path, fragment, query, username, password.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/url_parse.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Parse and build URLs — url_parse","text":"","code":"url_parse(\"http://google.com/\") #> <httr2_url> http://google.com/ #> • scheme: http #> • hostname: google.com #> • path: / url_parse(\"http://google.com:80/\") #> <httr2_url> http://google.com:80/ #> • scheme: http #> • hostname: google.com #> • port: 80 #> • path: / url_parse(\"http://google.com:80/?a=1&b=2\") #> <httr2_url> http://google.com:80/?a=1&b=2 #> • scheme: http #> • hostname: google.com #> • port: 80 #> • path: / #> • query: #> • a: 1 #> • b: 2 url_parse(\"http://username@google.com:80/path;test?a=1&b=2#40\") #> <httr2_url> http://username@google.com:80/path;test?a=1&b=2#40 #> • scheme: http #> • hostname: google.com #> • username: username #> • port: 80 #> • path: /path;test #> • query: #> • a: 1 #> • b: 2 #> • fragment: 40 url <- url_parse(\"http://google.com/\") url$port <- 80 url$hostname <- \"example.com\" url$query <- list(a = 1, b = 2, c = 3) url_build(url) #> [1] \"http://example.com:80/?a=1&b=2&c=3\""},{"path":"https://httr2.r-lib.org/dev/reference/with_mocked_responses.html","id":null,"dir":"Reference","previous_headings":"","what":"Temporarily mock requests — with_mocked_responses","title":"Temporarily mock requests — with_mocked_responses","text":"Mocking allows selectively temporarily replace response typically receive request code. primarily used testing.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/with_mocked_responses.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Temporarily mock requests — with_mocked_responses","text":"","code":"with_mocked_responses(mock, code) local_mocked_responses(mock, env = caller_env())"},{"path":"https://httr2.r-lib.org/dev/reference/with_mocked_responses.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Temporarily mock requests — with_mocked_responses","text":"mock function, list, NULL. NULL disables mocking returns httr2 regular operation. list responses returned sequence. responses used , return 503 server errors. maximum flexibility, can supply function takes single argument, req, returns either NULL (want handle request) response (). code Code execute temporary environment. env Environment use scoping changes.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/with_mocked_responses.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Temporarily mock requests — with_mocked_responses","text":"with_mock() returns result evaluating code.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/with_mocked_responses.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Temporarily mock requests — with_mocked_responses","text":"","code":"# This function should perform a response against google.com: google <- function() { request(\"http://google.com\") |> req_perform() } # But I can use a mock to instead return my own made up response: my_mock <- function(req) { response(status_code = 403) } try(with_mock(my_mock, google())) #> Warning: `with_mock()` was deprecated in httr2 1.0.0. #> ℹ Please use `with_mocked_responses()` instead. #> Error in req_perform(request(\"http://google.com\")) : HTTP 403 Forbidden."},{"path":"https://httr2.r-lib.org/dev/reference/with_verbosity.html","id":null,"dir":"Reference","previous_headings":"","what":"Temporarily set verbosity for all requests — with_verbosity","title":"Temporarily set verbosity for all requests — with_verbosity","text":"with_verbosity() useful debugging httr2 code buried deep inside another package allows see exactly sent requested.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/with_verbosity.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Temporarily set verbosity for all requests — with_verbosity","text":"","code":"with_verbosity(code, verbosity = 1)"},{"path":"https://httr2.r-lib.org/dev/reference/with_verbosity.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Temporarily set verbosity for all requests — with_verbosity","text":"code Code execture verbosity much information print? wrapper around req_verbose() uses integer control verbosity: 0: output 1: show headers 2: show headers bodies 3: show headers, bodies, curl status messages. Use with_verbosity() control verbosity requests affect directly.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/with_verbosity.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Temporarily set verbosity for all requests — with_verbosity","text":"result evaluating code.","code":""},{"path":"https://httr2.r-lib.org/dev/reference/with_verbosity.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Temporarily set verbosity for all requests — with_verbosity","text":"","code":"fun <- function() { request(\"https://httr2.r-lib.org\") |> req_perform() } with_verbosity(fun()) #> -> GET / HTTP/2 #> -> Host: httr2.r-lib.org #> -> user-agent: httr2/1.0.5.9000 r-curl/5.2.3 libcurl/7.81.0 #> -> accept: */* #> -> accept-encoding: deflate, gzip, br, zstd #> -> #> <- HTTP/2 200 #> <- server: GitHub.com #> <- content-type: text/html; charset=utf-8 #> <- last-modified: Wed, 23 Oct 2024 18:14:33 GMT #> <- access-control-allow-origin: * #> <- etag: W/\"67193d09-4983\" #> <- expires: Wed, 23 Oct 2024 22:20:36 GMT #> <- cache-control: max-age=600 #> <- content-encoding: gzip #> <- x-proxy-cache: MISS #> <- x-github-request-id: 97CB:344448:46EAD9:50CD81:67197452 #> <- accept-ranges: bytes #> <- date: Wed, 23 Oct 2024 22:10:59 GMT #> <- via: 1.1 varnish #> <- age: 24 #> <- x-served-by: cache-chi-kigq8000144-CHI #> <- x-cache: HIT #> <- x-cache-hits: 5 #> <- x-timer: S1729721460.616774,VS0,VE0 #> <- vary: Accept-Encoding #> <- x-fastly-request-id: cf58bf43c862894d96a084fe00b673e6c23154d8 #> <- content-length: 4636 #> <- #> <httr2_response> #> GET https://httr2.r-lib.org/ #> Status: 200 OK #> Content-Type: text/html #> Body: In memory (18819 bytes)"},{"path":[]},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-105","dir":"Changelog","previous_headings":"","what":"httr2 1.0.5","title":"httr2 1.0.5","text":"CRAN release: 2024-09-26 New resp_stream_aws() retrieve AWS’s special streaming format. thanks https://github.com/lifion/lifion-aws-event-stream/ simple reference implementation. New req_auth_aws_v4() signs request using AWS’s special format (#562, #566). req_perform_parallel() req_perform_promise() now correctly set method body (#549).","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-104","dir":"Changelog","previous_headings":"","what":"httr2 1.0.4","title":"httr2 1.0.4","text":"CRAN release: 2024-09-13 req_body_file() now works files >64kb (#524) longer leaks connection response doesn’t complete succesfully (#534). req_body_*() now give informative error attempt change body type (#451). req_cache() now re-caches response body hasn’t modified headers changed (#442). also works better req_perform() sets path (#442). New req_cookie_set() allows set client side cookies (#369). req_perform() longer displays progress bar sleeping tests. can override behaviour setting option httr2_progress. req_perform_iterative() longer experimental. New req_perform_connection() working streaming data. Unlike req_perform_stream() uses callbacks, req_perform_connection() returns regular response object connection body. Unlike req_perform_stream() supports req_retry() (@jcheng5, #519). req_retry() longer treates low-level HTTP failures way transient errors default. can return previous behaviour retry_on_error = TRUE. resp_body_html() resp_body_xml() now work req_perform() given path (#448). New resp_stream_bytes(), resp_stream_lines(), resp_stream_sse() streaming chunk connection response (#519).","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-103","dir":"Changelog","previous_headings":"","what":"httr2 1.0.3","title":"httr2 1.0.3","text":"CRAN release: 2024-08-22 jwt_encode_hmac() now calls correct underlying function jose::jwt_encode_hmac() correct default size parameter value (@denskh, #508). req_cache() now prunes cache checking given key exists, eliminating occassional error reading invalid RDS file. also longer tests existence later reads cache, avoiding potential race conditions. New req_perform_promise() creates promises::promise request can run background (#501, @gergness). req_perform_parallel() now respects error handling req_error().","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-102","dir":"Changelog","previous_headings":"","what":"httr2 1.0.2","title":"httr2 1.0.2","text":"CRAN release: 2024-07-16 req_body_file() now opens connection request actually needs data. particular, makes work better req_perform_parallel() (#487). req_cache() longer fails rds files somehow corrupted now defaults debug argument httr2_cache_debug option make easier debug caching buried people’s code (#486). req_oauth_password() now asks password (#498). req_perform_parallel() now works correctly req_cache() (#447) now works downloading 0 byte files (#478) req_perform_stream() longer applies callback unsuccessful responses, instead creating regular response. also now sets last_request() last_response() (#479). req_url_query() now allows opt escaping multi-value parameters (#404).","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-101","dir":"Changelog","previous_headings":"","what":"httr2 1.0.1","title":"httr2 1.0.1","text":"CRAN release: 2024-04-01 req_perform_stream() gains round = c(\"byte\", \"line\") argument control stream rounded (#437). req_retry() gives clearer error returns wrong type value (#385). req_template() now works bare : template uses “uri” style (#389). req_timeout() now resets value connecttimeout set curl. ensures can use req_timeout() increase connection timeout past 10s (#395). url_parse() considerably faster thanks performance optimisations discussion @DyfanJones (#429).","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-100","dir":"Changelog","previous_headings":"","what":"httr2 1.0.0","title":"httr2 1.0.0","text":"CRAN release: 2023-11-14","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"function-lifecycle-1-0-0","dir":"Changelog","previous_headings":"","what":"Function lifecycle","title":"httr2 1.0.0","text":"local_mock() with_mock() deprecated favour local_mocked_responses() with_mocked_responses() (#301). multi_req_perform() deprecated favour req_perform_parallel(). req_stream() deprecated favour req_perform_stream() (#314). oauth_flow_auth_code() deprecates host_name port arguments favour using redirect_uri. also deprecates host_ip since seems unlikely changing ever useful. oauth_flow_auth_code_listen() now takes single redirect_uri argument instead separate host_ip port arguments. breaking change don’t expect anyone call function directly (confirmed GitHub search) made change without deprecation. req_body_form() req_body_multipart() now require data ...; longer accept single list compatibility 0.1.0 API.","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"multiple-requests-1-0-0","dir":"Changelog","previous_headings":"","what":"Multiple requests","title":"httr2 1.0.0","text":"New req_perform_sequential() performs known set requests sequentially. interface similar req_perform_parallel() limitations, cost slower (#361). New req_perform_iterative() performs multiple requests, request derived previous response (@mgirlich, #8). req_perform_parallel() replaces multi_req_perform() match new naming scheme (#314). gains progress argument. req_perform_iterative(), req_perform_parallel(), req_perform_sequential() share new error handling strategy. default, errors bubbled , can choose alternative strategy on_error argument (#372). new family functions resps_successes(), resps_failures(), resps_requests() resps_data() make easier work lists responses (#357). Behind scenes, work request now stored response (error) object (#357). resp_body_json() resp_body_xml() now cache parsed values can use repeatedly without worrying performance cost. supports design req_perform_iterative() avoiding need carefully pass around parsed object.","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"oauth-features-1-0-0","dir":"Changelog","previous_headings":"","what":"OAuth features","title":"httr2 1.0.0","text":"new vignette(\"oauth\") gives many details OAuth works use httr2 (#234), OAuth docs overhauled make clear use req_oauth_*(), oauth_*() (#330). using OAuth token refresh token, refresh token expired, httr2 now re-run entire flow get new token (#349). New oauth_cache_path() returns path httr2 uses caching OAuth tokens. Additionally, can now change cache location setting HTTR2_OAUTH_CACHE env var. now obvious user, httr2 now informs user whenever token cached. oauth_flow_auth_code() gains redirect_uri argument rather deriving URL automatically host_name port (#248). uses argument automatically choose strategy use get auth code, either launching temporary web server , new, allowing manually enter details help custom JS/HTML page hosted elsewhere, copying pasting URL ’re redirected (@fh-mthomson, #326). temporary web server now also respects path component redirect_uri, API needs specific path (#149). New oauth_token_cached() allows get OAuth token still taking advantage httr2’s caching auto-renewal features. expert use (#328).","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"other-new-features-1-0-0","dir":"Changelog","previous_headings":"","what":"Other new features","title":"httr2 1.0.0","text":"@mgirlich now httr2 contributor recognition many contributions. req_cache() gains max_n, max_size, max_age arguments automatically prune cache. default, cache stay 1 GB (#207). New req_body_json_modify() allows iteratively modify JSON body request. New req_cookie_preserve() lets use file share cookies across requests (#223). New req_progress() adds progress bar long downloads uploads (#20). New resp_check_content_type() check response content types (#190). resp_body_json() friends give better errors Content-Type header present response (#284). New resp_has_body() returns TRUE FALSE depending whether response body (#205). New resp_url(), resp_url_path(), resp_url_queries() resp_url_query() extract various part response url (#57). req_url_query() gains .multi parameter controls happens supply multiple values vector. default continue error can use .multi = \"comma\" separate commas, \"pipe\" separate |, \"explode\" generate one parameter value (e.g. ?=1&=2) (#350). New secret_encrypt_file() secret_decrypt_file() encrypting decrypting files (#237).","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"minor-improvements-and-bug-fixes-1-0-0","dir":"Changelog","previous_headings":"","what":"Minor improvements and bug fixes","title":"httr2 1.0.0","text":"httr2 examples now run R 4.2 later can use base pipe lambda syntax (#345). OAuth errors containing url now correctly display URL (instead string “uri”). curl_translate() now uses base pipe, produces escapes single quotes raw strings case double quotes can’t used (@mgirlich, #264). gains argument simplify_headers removes common unimportant headers, like Sec-Fetch-Dest sec-ch-ua-mobile (@mgirlich, #256). also parses query components url (@mgirlich, #259) works multiline commands clipboard (@mgirlich, #254). local_mocked_responses() with_mocked_responses() now accept list responses returned sequence. also now correctly trigger errors mocked response represents HTTP failure (#252). oauth_flow_refresh() now warns, errors, refresh_token changes, making little easier use manual workflows (#186). obfuscated() values now display original call printed. req_body_json() gains custom content type argument respects custom content-type set header (@mgirlich, #189). req_cache() now combine headers new response headers cached response. particular, fixes resp_body_json/xml/html() cached responses (@mgirlich, #277). req_perform() now throws error class httr2_failure/httr2_error request fails, error now captures curl error parent. request succeeds, response HTTP error, error now also super class httr2_error. means errors thrown httr2 now inherit httr2_error class. See new docs ?req_error() details. req_perform()’s progress bar can suppressed setting options(httr2_progress = FALSE) (#251). Progress bars displayed waiting time pass now tell ’re waiting (#206). req_oauth_bearer_jwt() now includes claim cache key (#192). req_oauth_device() now takes auth_url parameter making usable (#331, @taerwin). req_url_query() gains .multi parameter controls happens supply multiple values vector. default continue error can use .multi = \"comma\" separate commas, \"pipe\" separate |, \"explode\" generate one parameter value (e.g. ?=1&=2) (#350).","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-023","dir":"Changelog","previous_headings":"","what":"httr2 0.2.3","title":"httr2 0.2.3","text":"CRAN release: 2023-05-08 New example_url() launch local server, making tests examples robust. New throttle_status() make little easier verify ’s happening throttling. req_oauth_refresh() now respects refresh_token caching (@mgirlich, #178). req_perform() now always sleeps request, rather . also gains error_call argument communicates clearly error occurred (@mgirlich, #187). req_url_path() req_url_path_append() can now handle NULL empty ... elements ... can also length > 1 (@mgirlich, #177). sys_sleep() (used req_retry() req_throttle()) gains progress bar (#202).","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-022","dir":"Changelog","previous_headings":"","what":"httr2 0.2.2","title":"httr2 0.2.2","text":"CRAN release: 2022-09-25 curl_translate() can now handle curl copied Chrome developer tools (@mgirlich, #161). req_oauth_*() can now refresh OAuth tokens. One, two, even times! (@jennybc, #166) req_oauth_device() can now work non-interactive environments, intendend (@flahn, #170) req_oauth_refresh() oauth_flow_refresh() now use envvar HTTR2_REFRESH_TOKEN, HTTR_REFRESH_TOKEN (@jennybc, #169). req_proxy() now uses appropriate authentication option (@jl5000). req_url_query() can now opt escaping () (@boshek, #152). Can now print responses content type empty string (@mgirlich, #163).","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-021","dir":"Changelog","previous_headings":"","what":"httr2 0.2.1","title":"httr2 0.2.1","text":"CRAN release: 2022-05-10 “Wrapping APIs” now article, vignette. req_template() now appends path instead replacing (@jchrom, #133)","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-020","dir":"Changelog","previous_headings":"","what":"httr2 0.2.0","title":"httr2 0.2.0","text":"CRAN release: 2022-04-28","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"new-features-0-2-0","dir":"Changelog","previous_headings":"","what":"New features","title":"httr2 0.2.0","text":"req_body_form(), req_body_multipart(), req_url_query() now support multiple arguments name (#97, #107). req_body_form(), req_body_multipart(), now match interface req_url_query(), taking name-value pairs .... Supplying single list() now deprecated removed future version. req_body_json() now overrides existing JSON body, rather attempting merge previous value (#95, #115). Implement req_proxy() (owenjonesuob, #77).","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"minor-improvements-and-bug-fixes-0-2-0","dir":"Changelog","previous_headings":"","what":"Minor improvements and bug fixes","title":"httr2 0.2.0","text":"httr_path class renamed httr2_path correctly match package name (#99). oauth_flow_device() gains PKCE support (@flahn, #92), interactive flow little user friendly. req_error() can now correct force successful HTTP statuses fail (#98). req_headers() now override Content-Type set req_body_*() (#116). req_throttle() correctly sets throttle rate (@jchrom, #101). req_url_query() never uses scientific notation queries (#93). req_perform() now respects httr::with_verbose() (#85). response() now defaults body raw(0) consistency real responses (#100). req_stream() longer throws error non 200 http status codes (@DMerch, #137)","code":""},{"path":"https://httr2.r-lib.org/dev/news/index.html","id":"httr2-011","dir":"Changelog","previous_headings":"","what":"httr2 0.1.1","title":"httr2 0.1.1","text":"CRAN release: 2021-09-28 Fix R CMD check failures CRAN Added NEWS.md file track changes package.","code":""}]