1

I'm using the R package httr2 to upload files to a secure environment. If a file already exists, I'd like to receive a warning. Instead, I get a response status of 200 which, means "OK". However, the file is not updated on the server.

This is the code I use for the upload:

url <- "<server URL><Filepath on server>?action=upload"

req <- request(url) %>%
  req_method("POST") %>%
  req_headers("X-Auth-Token" = token) %>%
  req_body_multipart(uploadFile = curl::form_file(file_path))
resp <- req_perform(req, verbosity=3)

I get the following status information:

> resp_status(resp)
[1] 200
> resp_status_desc(resp)
[1] "OK"

However, the curl status message (obtained using verbosity=3 with req_perform) shows "code":20012,"type":"WARNING"}. But the curl status is not included in the resp object so I can't include a check that the upload went as intended.

If I do the same request in httr instead of httr2, then the status will also be 200 but I can use the content function to obtain the curl status.

response <- PUT(
  url,
  add_headers(`X-Auth-Token` = token),
  body = list(uploadFile = upload_file(file_path))
)
> response$status
[1] 200
> content(response)$status$code
[1] 20012

I am aware that I can append &overwrite=true to the URL but I don't want to automatically overwrite the file. It's my understanding that the PUT method is intended for existing files and that POST should be used for new files. However, the server (LSAF 5.4.2, a statistical computing environment by SAS) only accepts PUT.

Is there a way to programmatically extract the curl status code using httr2?

3
  • 1
    What is "secure environment"? I do not the source code/documentation, quick and dirty might be a try/tryCatch/if-else-approach.
    – Friede
    Commented Apr 17 at 9:44
  • If the status "code":20012,"type":"WARNING"} is obtained from the verbosity you could use sink to capture the console-output and then tryCatch or handle it as you want. Other than that maybe httr2::resp_body_string(resp) offers more detail.
    – Tim G
    Commented Apr 17 at 10:09
  • 1
    There’s no such thing as a “curl status code” in this context. You can use resp_body_json() to get the response body. Commented Apr 17 at 12:19

1 Answer 1

2

You can parse JSON response with resp_body_json().
To override default HTTP error handling and to control if something in response body should turn response into error, check req_error() , it also lets you extract information, e.g. warnings from API.

We can test this with https://httpbin.org/ , all our request arguments are included in JSON response.

library(httr2)

# convert into R error if type in JSON response is not "OK"
f_is_error <- \(resp) resp_body_json(resp)$args$type != "OK"
# in your case it might look something like 
# f_is_error <- \(resp) resp_body_json(resp)$status$type == "WARNING"

# extract (part of) JSON response as string for some context
f_body <- \(resp) paste0("Something in response was not quite right: ",  
                         jsonlite::toJSON(resp_body_json(resp)$args, auto_unbox = TRUE))

# generate JSON response that includes a warning
request("https://httpbin.org/get?code=200012&type=WARNING") |> 
  req_error(is_error = f_is_error, body = f_body) |> 
  req_perform(verbosity = 2)
#> -> GET /get?code=200012&type=WARNING HTTP/1.1
#> ...
#> <- HTTP/1.1 200 OK
#> ...
#> << {
#> <<   "args": {
#> <<     "code": "200012",
#> <<     "type": "WARNING"
#> <<   },
#> <<   "headers": { ...
#> ...
#> << }
#> Error in `req_perform()`:
#> ! HTTP 200 OK.
#> • Something in response was not quite right: {"code":"200012","type":"WARNING"}

# generate JSON response with type "OK"
request("https://httpbin.org/get?code=100012&type=OK") |> 
  req_error(is_error = f_is_error, body = f_body) |> 
  req_perform(verbosity = 2)
#> -> GET /get?code=100012&type=OK HTTP/1.1
#> ...
#> <- HTTP/1.1 200 OK
#> ...
#> << {
#> <<   "args": {
#> <<     "code": "100012",
#> <<     "type": "OK"
#> <<   },
#> <<   "headers": { ...
#> ...
#> << }
#> <httr2_response>
#> GET https://httpbin.org/get?code=100012&type=OK
#> Status: 200 OK
#> Content-Type: application/json
#> Body: In memory (388 bytes)
1
  • Thanks for the help! For me, resp_body_json(resp)$status$code and resp_body_json(resp)$status$type provide the information I need.
    – ckx
    Commented Apr 22 at 9:16

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.