Skip to content

Allowing httr::write_disk to actually create files #121

@davidorme

Description

@davidorme
Session Info
r$> devtools::session_info() 
─ Session info ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 setting  value
 version  R version 4.2.0 (2022-04-22)
 os       macOS Monterey 12.1
 system   x86_64, darwin21.3.0
 ui       unknown
 language (EN)
 collate  en_US.UTF-8
 ctype    en_US.UTF-8
 tz       Europe/London
 date     2023-05-11
 pandoc   2.11.1.1 @ /usr/local/bin/pandocPackages ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 ! package     * version    date (UTC) lib source
   base64enc     0.1-3      2015-07-28 [1] CRAN (R 4.2.0)
   brio          1.1.3      2021-11-30 [1] CRAN (R 4.2.0)
   cachem        1.0.6      2021-08-19 [1] CRAN (R 4.2.0)
   callr         3.7.0      2021-04-20 [1] CRAN (R 4.2.0)
   cellranger    1.1.0      2016-07-27 [1] CRAN (R 4.2.0)
   chron         2.3-57     2022-05-30 [1] CRAN (R 4.2.0)
   class         7.3-20     2022-01-16 [2] CRAN (R 4.2.0)
   classInt      0.4-7      2022-06-10 [1] CRAN (R 4.2.0)
   cli           3.4.1      2022-09-23 [1] CRAN (R 4.2.0)
   crayon        1.5.1      2022-03-26 [1] CRAN (R 4.2.0)
   crul          1.3        2022-09-03 [1] CRAN (R 4.2.0)
   curl          4.3.2      2021-06-23 [1] CRAN (R 4.2.0)
   DBI           1.1.3      2022-06-18 [1] CRAN (R 4.2.0)
   desc          1.4.1      2022-03-06 [1] CRAN (R 4.2.0)
   devtools      2.4.3      2021-11-30 [1] CRAN (R 4.2.0)
   dplyr         1.0.10     2022-09-01 [1] CRAN (R 4.2.0)
   e1071         1.7-11     2022-06-07 [1] CRAN (R 4.2.0)
   ellipsis      0.3.2      2021-04-29 [1] CRAN (R 4.2.0)
   fansi         1.0.3      2022-03-24 [1] CRAN (R 4.2.0)
   fastmap       1.1.0      2021-01-25 [1] CRAN (R 4.2.0)
   fauxpas       0.5.2      2023-05-03 [1] CRAN (R 4.2.0)
   fs            1.5.2      2021-12-08 [1] CRAN (R 4.2.0)
   generics      0.1.3      2022-07-05 [1] CRAN (R 4.2.0)
   glue          1.6.2      2022-02-24 [1] CRAN (R 4.2.0)
   httpcode      0.3.0      2020-04-10 [1] CRAN (R 4.2.0)
   httr        * 1.4.3      2022-05-04 [1] CRAN (R 4.2.0)
   igraph        1.3.4      2022-07-19 [1] CRAN (R 4.2.0)
   jsonlite      1.8.0      2022-02-22 [1] CRAN (R 4.2.0)
   KernSmooth    2.23-20    2021-05-03 [2] CRAN (R 4.2.0)
   lifecycle     1.0.3      2022-10-07 [1] CRAN (R 4.2.0)
   magrittr      2.0.3      2022-03-30 [1] CRAN (R 4.2.0)
   memoise       2.0.1      2021-11-26 [1] CRAN (R 4.2.0)
   pillar        1.7.0      2022-02-01 [1] CRAN (R 4.2.0)
   pkgbuild      1.3.1      2021-12-20 [1] CRAN (R 4.2.0)
   pkgconfig     2.0.3      2019-09-22 [1] CRAN (R 4.2.0)
   pkgload       1.2.4      2021-11-30 [1] CRAN (R 4.2.0)
   prettyunits   1.1.1      2020-01-24 [1] CRAN (R 4.2.0)
   processx      3.5.3      2022-03-25 [1] CRAN (R 4.2.0)
   proxy         0.4-27     2022-06-09 [1] CRAN (R 4.2.0)
   ps            1.7.0      2022-04-23 [1] CRAN (R 4.2.0)
   purrr         0.3.4      2020-04-17 [1] CRAN (R 4.2.0)
   R6            2.5.1      2021-08-19 [1] CRAN (R 4.2.0)
   Rcpp          1.0.9      2022-07-08 [1] CRAN (R 4.2.0)
   readxl        1.4.0      2022-03-28 [1] CRAN (R 4.2.0)
   remotes       2.4.2      2021-11-30 [1] CRAN (R 4.2.0)
   rlang         1.0.6      2022-09-24 [1] CRAN (R 4.2.0)
   rprojroot     2.0.3      2022-04-02 [1] CRAN (R 4.2.0)
   rstudioapi    0.13       2020-11-12 [1] CRAN (R 4.2.0)
 P safedata    * 1.1.2.9000 2023-05-03 [?] load_all()
   sessioninfo   1.2.2      2021-12-06 [1] CRAN (R 4.2.0)
   sf            1.0-11     2023-03-15 [1] CRAN (R 4.2.0)
   testthat    * 3.1.4      2022-04-26 [1] CRAN (R 4.2.0)
   tibble        3.1.7      2022-05-03 [1] CRAN (R 4.2.0)
   tidyselect    1.2.0      2022-10-10 [1] CRAN (R 4.2.0)
   triebeard     0.3.0      2016-08-04 [1] CRAN (R 4.2.0)
   units         0.8-0      2022-02-05 [1] CRAN (R 4.2.0)
   urltools      1.7.3      2019-04-14 [1] CRAN (R 4.2.0)
   usethis       2.1.5      2021-12-09 [1] CRAN (R 4.2.0)
   utf8          1.2.2      2021-07-24 [1] CRAN (R 4.2.0)
   vctrs         0.4.1      2022-04-13 [1] CRAN (R 4.2.0)
   webmockr    * 0.9.0      2023-02-28 [1] CRAN (R 4.2.0)
   whisker       0.4        2019-08-28 [1] CRAN (R 4.2.0)
   withr         2.5.0      2022-03-03 [1] CRAN (R 4.2.0)

 [1] /usr/local/lib/R/4.2/site-library
 [2] /usr/local/Cellar/r/4.2.0/lib/R/library

 P ── Loaded and on-disk path mismatch.

I'm trying to use webmockr to mock an API for my safedata package, to allow code examples and vignette building in packaging to run without requiring a running server providing the API.

The issue I'm having is that I'd like to have request stub actually create a file from the response body. That is how httr::GET with write_disk works without mocking - the response body is written to the named file. However, when the request is stubbed then I think write_disk is ignored and replaced with whatever is set in the to_return body, which could be an existing file containing the response or some other in memory response. Or at least I think that is how it works (see R code below).

I can see why this is used - there's no duplication of content and running httr:content on the response object gets you the body - but in my case I want to use the request to build up a local file structure in the same way that it would if I wasn't mocking the API.

Is there a way to get webmockr to provide a response body from a file (or directly!) and allow httr to write it out to a new file?

r$> ## make a temp file
r$> f <- tempfile(fileext = ".json")
r$> ## write something to the file
r$> cat("{\"hello\":\"world\"}\n", file = f)
r$> httr_mock()
r$> stub_request("get", "https://httpbin.org/get") %>% 
            to_return(body = file(f), 
             headers = list('content-type' = "application/json"))
r$> # Stubbed request ignores write disk and points to body file
r$> out <- GET("https://httpbin.org/get", write_disk('new_file.txt'))
r$> out
Response [https://httpbin.org/get]
  Date: 2023-05-11 23:25
  Status: 200
  Content-Type: application/json
  Size: 18 B
<ON DISK>  /var/folders/62/cz0ctby96lq7ggnytfbtd__40000gn/T//RtmpKOpQFB/filec99b220f73af.json
r$> file.exists('new_file.txt')
[1] FALSE
r$> stub_request("get", "https://httpbin.org/get2") %>% 
            to_return(body = readLines(f), 
             headers = list('content-type' = "application/json"))
r$> # Again, write_disk is ignored and in memory body is used
r$> out <- GET("https://httpbin.org/get2", write_disk('new_file2.txt'))
r$> out
Response [https://httpbin.org/get2]
  Date: 2023-05-11 23:49
  Status: 200
  Content-Type: application/json
  Size: 17 B
r$> file.exists('new_file2.txt')
[1] FALSE
r$> httr::content(out)
$hello
[1] "world"
r$> # Turn off mocking
r$> httr_mock(FALSE)
r$> # 'Normal' usage writes the content to the named file.
r$> out <- GET("https://httpbin.org/get", write_disk('new_file.txt'))
r$> out
Response [https://httpbin.org/get]
  Date: 2023-05-11 22:25
  Status: 200
  Content-Type: application/json
  Size: 367 B
<ON DISK>  new_file.txt
r$> file.exists('new_file.txt')
[1] TRUE

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions