Title: | Stubbing and Setting Expectations on 'HTTP' Requests |
---|---|
Description: | Stubbing and setting expectations on 'HTTP' requests. Includes tools for stubbing 'HTTP' requests, including expected request conditions and response conditions. Match on 'HTTP' method, query parameters, request body, headers and more. Can be used for unit tests or outside of a testing context. |
Authors: | Scott Chamberlain [aut, cre] , Aaron Wolen [ctb] , rOpenSci [fnd] (https://ropensci.org) |
Maintainer: | Scott Chamberlain <[email protected]> |
License: | MIT + file LICENSE |
Version: | 2.0.0 |
Built: | 2024-12-14 05:20:56 UTC |
Source: | https://github.com/ropensci/webmockr |
Build a crul request
build_crul_request(x)
build_crul_request(x)
x |
an unexecuted crul request object |
a crul request
Build a crul response
build_crul_response(req, resp)
build_crul_response(req, resp)
req |
a request |
resp |
a response |
a crul response
Build a httr request
build_httr_request(x)
build_httr_request(x)
x |
an unexecuted httr request object |
a httr request
Build a httr response
build_httr_response(req, resp)
build_httr_response(req, resp)
req |
a request |
resp |
a response |
a httr response
Build an httr2 request
build_httr2_request(x)
build_httr2_request(x)
x |
an unexecuted httr2 request object |
a httr2_request
httr2_response
)Build a httr2 response (httr2_response
)
build_httr2_response(req, resp)
build_httr2_response(req, resp)
req |
a request |
resp |
a response |
an httr2 response (httr2_response
)
## Not run: # x <- Httr2Adapter$new() # library(httr2) # req <- request("https://r-project.org") # req = req %>% req_body_json(list(x = 1, y = 2)) # #req$method <- 'POST' # stub_request("post", "https://r-project.org") %>% # to_return(status = 418, body = list(a = 5)) # stub = webmockr_stub_registry$request_stubs[[1]] # stub$counter$.__enclos_env__$private$total <- 1 # resp = x$.__enclos_env__$private$build_stub_response(stub) # resp = x$.__enclos_env__$private$build_response(req, resp) # resp = x$.__enclos_env__$private$add_response_sequences(stub, resp) # out # out$body # out$content ## End(Not run)
## Not run: # x <- Httr2Adapter$new() # library(httr2) # req <- request("https://r-project.org") # req = req %>% req_body_json(list(x = 1, y = 2)) # #req$method <- 'POST' # stub_request("post", "https://r-project.org") %>% # to_return(status = 418, body = list(a = 5)) # stub = webmockr_stub_registry$request_stubs[[1]] # stub$counter$.__enclos_env__$private$total <- 1 # resp = x$.__enclos_env__$private$build_stub_response(stub) # resp = x$.__enclos_env__$private$build_response(req, resp) # resp = x$.__enclos_env__$private$add_response_sequences(stub, resp) # out # out$body # out$content ## End(Not run)
Adapter
is the base parent class used to implement
webmockr support for different HTTP clients. It should not be used
directly. Instead, use one of the client-specific adapters that webmockr
currently provides:
CrulAdapter
for crul
HttrAdapter
for httr
Httr2Adapter
for httr2
Note that the documented fields and methods are the same across all client-specific adapters.
webmockr::Adapter
-> CrulAdapter
client
HTTP client package name
name
adapter name
clone()
The objects of this class are cloneable with this method.
CrulAdapter$clone(deep = FALSE)
deep
Whether to make a deep clone.
webmockr::Adapter
-> HttrAdapter
client
HTTP client package name
name
adapter name
clone()
The objects of this class are cloneable with this method.
HttrAdapter$clone(deep = FALSE)
deep
Whether to make a deep clone.
webmockr::Adapter
-> Httr2Adapter
client
HTTP client package name
name
adapter name
clone()
The objects of this class are cloneable with this method.
Httr2Adapter$clone(deep = FALSE)
deep
Whether to make a deep clone.
client
HTTP client package name
name
adapter name
new()
Create a new Adapter object
Adapter$new()
enable()
Enable the adapter
Adapter$enable(quiet = FALSE)
quiet
(logical) suppress messages? default: FALSE
TRUE
, invisibly
disable()
Disable the adapter
Adapter$disable(quiet = FALSE)
quiet
(logical) suppress messages? default: FALSE
FALSE
, invisibly
handle_request()
All logic for handling a request
Adapter$handle_request(req)
req
a request
various outcomes
remove_stubs()
Remove all stubs
Adapter$remove_stubs()
nothing returned; removes all request stubs
clone()
The objects of this class are cloneable with this method.
Adapter$clone(deep = FALSE)
deep
Whether to make a deep clone.
## Not run: if (requireNamespace("httr", quietly = TRUE)) { # library(httr) # normal httr request, works fine # real <- GET("https://httpbin.org/get") # real # with webmockr # library(webmockr) ## turn on httr mocking # httr_mock() ## now this request isn't allowed # GET("https://httpbin.org/get") ## stub the request # stub_request('get', uri = 'https://httpbin.org/get') %>% # wi_th( # headers = list('Accept' = 'application/json, text/xml, application/xml, */*') # ) %>% # to_return(status = 418, body = "I'm a teapot!", headers = list(a = 5)) ## now the request succeeds and returns a mocked response # (res <- GET("https://httpbin.org/get")) # res$status_code # rawToChar(res$content) # allow real requests while webmockr is loaded # webmockr_allow_net_connect() # webmockr_net_connect_allowed() # GET("https://httpbin.org/get?animal=chicken") # webmockr_disable_net_connect() # webmockr_net_connect_allowed() # GET("https://httpbin.org/get?animal=chicken") # httr_mock(FALSE) } ## End(Not run)
## Not run: if (requireNamespace("httr", quietly = TRUE)) { # library(httr) # normal httr request, works fine # real <- GET("https://httpbin.org/get") # real # with webmockr # library(webmockr) ## turn on httr mocking # httr_mock() ## now this request isn't allowed # GET("https://httpbin.org/get") ## stub the request # stub_request('get', uri = 'https://httpbin.org/get') %>% # wi_th( # headers = list('Accept' = 'application/json, text/xml, application/xml, */*') # ) %>% # to_return(status = 418, body = "I'm a teapot!", headers = list(a = 5)) ## now the request succeeds and returns a mocked response # (res <- GET("https://httpbin.org/get")) # res$status_code # rawToChar(res$content) # allow real requests while webmockr is loaded # webmockr_allow_net_connect() # webmockr_net_connect_allowed() # GET("https://httpbin.org/get?animal=chicken") # webmockr_disable_net_connect() # webmockr_net_connect_allowed() # GET("https://httpbin.org/get?animal=chicken") # httr_mock(FALSE) } ## End(Not run)
Enable or disable webmockr
enable(adapter = NULL, options = list(), quiet = FALSE) enabled(adapter = "crul") disable(adapter = NULL, options = list(), quiet = FALSE)
enable(adapter = NULL, options = list(), quiet = FALSE) enabled(adapter = "crul") disable(adapter = NULL, options = list(), quiet = FALSE)
adapter |
(character) the adapter name, 'crul', 'httr', or 'httr2'. one or the other. if none given, we attempt to enable both adapters |
options |
list of options - ignored for now. |
quiet |
(logical) suppress messages? default: |
enable()
enables webmockr for all adapters
disable()
disables webmockr for all adapters
enabled()
answers whether webmockr is enabled for a given adapter
enable()
and disable()
invisibly returns booleans for
each adapter, as a result of running enable or disable, respectively,
on each HttpLibAdapaterRegistry object. enabled
returns a
single boolean
hash with counter, to store requests, and count each time it is used
hash
(list) a list for internal use only, with elements
key
, sig
, and count
put()
Register a request by it's key
HashCounter$put(req_sig)
req_sig
an object of class RequestSignature
nothing returned; registers request and iterates internal counter
get()
Get a request by key
HashCounter$get(req_sig)
req_sig
an object of class RequestSignature
(integer) the count of how many times the request has been made
clone()
The objects of this class are cloneable with this method.
HashCounter$clone(deep = FALSE)
deep
Whether to make a deep clone.
Other request-registry:
RequestRegistry
,
request_registry()
x <- HashCounter$new() x$hash z <- RequestSignature$new(method = "get", uri = "https:/httpbin.org/get") x$put(z) x$hash x$get(z) x$put(z) x$get(z)
x <- HashCounter$new() x$hash z <- RequestSignature$new(method = "get", uri = "https:/httpbin.org/get") x$put(z) x$hash x$get(z) x$put(z) x$get(z)
http lib adapter registry
adapters
list
print()
print method for the HttpLibAdapaterRegistry
class
HttpLibAdapaterRegistry$print(x, ...)
x
self
...
ignored
register()
Register an http library adapter
HttpLibAdapaterRegistry$register(x)
x
an http lib adapter, e.g., CrulAdapter
nothing, registers the library adapter
clone()
The objects of this class are cloneable with this method.
HttpLibAdapaterRegistry$clone(deep = FALSE)
deep
Whether to make a deep clone.
x <- HttpLibAdapaterRegistry$new() x$register(CrulAdapter$new()) x x$adapters x$adapters[[1]]$name
x <- HttpLibAdapaterRegistry$new() x$register(CrulAdapter$new()) x x$adapters x$adapters[[1]]$name
httr
mockingSets a callback that routes httr
requests through webmockr
httr_mock(on = TRUE)
httr_mock(on = TRUE)
on |
(logical) set to |
Silently returns TRUE
when enabled and FALSE
when disabled.
httr2
mockingSets a callback that routes httr2
requests through webmockr
httr2_mock(on = TRUE)
httr2_mock(on = TRUE)
on |
(logical) |
Silently returns TRUE
when enabled and FALSE
when disabled.
For use inside wi_th()
including(x) excluding(x)
including(x) excluding(x)
x |
(list) a list; may support other classes in the future |
same as x
, but with two attributes added:
partial_match: always TRUE
partial_type: the type of match, one of include
or exclude
Matching on headers already handles partial matching. That is,
wi_th(headers = list(Fruit = "pear"))
matches any request
that has any request header that matches - the request can have
other request headers, but those don't matter as long as there is
a match. These helpers (including
/excluding
) are needed
for query parameters and bodies because by default matching must be
exact for those.
including(list(foo = "bar")) excluding(list(foo = "bar")) # get just keys by setting values as NULL including(list(foo = NULL, bar = NULL)) # in a stub req <- stub_request("get", "https://httpbin.org/get") req ## query wi_th(req, query = list(foo = "bar")) wi_th(req, query = including(list(foo = "bar"))) wi_th(req, query = excluding(list(foo = "bar"))) ## body wi_th(req, body = list(foo = "bar")) wi_th(req, body = including(list(foo = "bar"))) wi_th(req, body = excluding(list(foo = "bar"))) # cleanup stub_registry_clear()
including(list(foo = "bar")) excluding(list(foo = "bar")) # get just keys by setting values as NULL including(list(foo = NULL, bar = NULL)) # in a stub req <- stub_request("get", "https://httpbin.org/get") req ## query wi_th(req, query = list(foo = "bar")) wi_th(req, query = including(list(foo = "bar"))) wi_th(req, query = excluding(list(foo = "bar"))) ## body wi_th(req, body = list(foo = "bar")) wi_th(req, body = including(list(foo = "bar"))) wi_th(req, body = excluding(list(foo = "bar"))) # cleanup stub_registry_clear()
Get the last HTTP request made
last_request()
last_request()
NULL
if no requests registered; otherwise the last
registered request made as a RequestSignature
class
# no requests request_registry_clear() last_request() # a request is found enable() stub_request("head", "https://nytimes.com") library(crul) crul::ok("https://nytimes.com") last_request() # cleanup request_registry_clear() stub_registry_clear()
# no requests request_registry_clear() last_request() # a request is found enable() stub_request("head", "https://nytimes.com") library(crul) crul::ok("https://nytimes.com") last_request() # cleanup request_registry_clear() stub_registry_clear()
Get the last stub created
last_stub()
last_stub()
NULL
if no stubs found; otherwise the last stub created
as a StubbedRequest
class
# no requests stub_registry_clear() last_stub() # a stub is found stub_request("head", "https://nytimes.com") last_stub() stub_request("post", "https://nytimes.com/stories") last_stub() # cleanup stub_registry_clear()
# no requests stub_registry_clear() last_stub() # a stub is found stub_request("head", "https://nytimes.com") last_stub() stub_request("post", "https://nytimes.com/stories") last_stub() # cleanup stub_registry_clear()
Mock file
mock_file(path, payload)
mock_file(path, payload)
path |
(character) a file path. required |
payload |
(character) string to be written to the file given
at |
a list with S3 class mock_file
mock_file(path = tempfile(), payload = "{\"foo\": \"bar\"}")
mock_file(path = tempfile(), payload = "{\"foo\": \"bar\"}")
Mocking writing to disk
## Not run: # enable mocking enable() # getOption('httr2_mock') # Write to a file before mocked request # crul library(crul) ## make a temp file f <- tempfile(fileext = ".json") ## write something to the file cat("{\"hello\":\"world\"}\n", file = f) readLines(f) ## make the stub stub_request("get", "https://httpbin.org/get") %>% to_return(body = file(f)) ## make a request (out <- HttpClient$new("https://httpbin.org/get")$get(disk = f)) out$content readLines(out$content) # httr library(httr) ## make a temp file f <- tempfile(fileext = ".json") ## write something to the file cat("{\"hello\":\"world\"}\n", file = f) readLines(f) ## make the stub stub_request("get", "https://httpbin.org/get") %>% to_return( body = file(f), headers = list("content-type" = "application/json") ) ## make a request ## with httr, you must set overwrite=TRUE or you'll get an errror out <- GET("https://httpbin.org/get", write_disk(f, overwrite = TRUE)) out out$content content(out, "text", encoding = "UTF-8") # httr2 library(httr2) ## make a temp file f <- tempfile(fileext = ".json") ## write something to the file cat("{\"hello\":\"world\"}\n", file = f) readLines(f) ## make the stub stub_request("get", "https://httpbin.org/get") %>% to_return( body = file(f), headers = list("content-type" = "application/json") ) ## make a request req <- request("https://httpbin.org/get") out <- req_perform(req, path = f) out out$body out out$headers readLines(out$body) # Use mock_file to have webmockr handle file and contents # crul library(crul) f <- tempfile(fileext = ".json") ## make the stub stub_request("get", "https://httpbin.org/get") %>% to_return(body = mock_file(f, "{\"hello\":\"mars\"}\n")) ## make a request (out <- crul::HttpClient$new("https://httpbin.org/get")$get(disk = f)) out$content readLines(out$content) # httr library(httr) ## make a temp file f <- tempfile(fileext = ".json") ## make the stub stub_request("get", "https://httpbin.org/get") %>% to_return( body = mock_file(path = f, payload = "{\"foo\": \"bar\"}"), headers = list("content-type" = "application/json") ) ## make a request out <- GET("https://httpbin.org/get", write_disk(f)) out ## view stubbed file content out$content readLines(out$content) content(out, "text", encoding = "UTF-8") # httr2 library(httr2) ## make a temp file f <- tempfile(fileext = ".json") ## make the stub stub_request("get", "https://httpbin.org/get") %>% to_return( body = mock_file(path = f, payload = "{\"foo\": \"bar\"}"), headers = list("content-type" = "application/json") ) ## make a request req <- request("https://httpbin.org/get") out <- req_perform(req, path = f) out ## view stubbed file content out$body readLines(out$body) # disable mocking disable() ## End(Not run)
## Not run: # enable mocking enable() # getOption('httr2_mock') # Write to a file before mocked request # crul library(crul) ## make a temp file f <- tempfile(fileext = ".json") ## write something to the file cat("{\"hello\":\"world\"}\n", file = f) readLines(f) ## make the stub stub_request("get", "https://httpbin.org/get") %>% to_return(body = file(f)) ## make a request (out <- HttpClient$new("https://httpbin.org/get")$get(disk = f)) out$content readLines(out$content) # httr library(httr) ## make a temp file f <- tempfile(fileext = ".json") ## write something to the file cat("{\"hello\":\"world\"}\n", file = f) readLines(f) ## make the stub stub_request("get", "https://httpbin.org/get") %>% to_return( body = file(f), headers = list("content-type" = "application/json") ) ## make a request ## with httr, you must set overwrite=TRUE or you'll get an errror out <- GET("https://httpbin.org/get", write_disk(f, overwrite = TRUE)) out out$content content(out, "text", encoding = "UTF-8") # httr2 library(httr2) ## make a temp file f <- tempfile(fileext = ".json") ## write something to the file cat("{\"hello\":\"world\"}\n", file = f) readLines(f) ## make the stub stub_request("get", "https://httpbin.org/get") %>% to_return( body = file(f), headers = list("content-type" = "application/json") ) ## make a request req <- request("https://httpbin.org/get") out <- req_perform(req, path = f) out out$body out out$headers readLines(out$body) # Use mock_file to have webmockr handle file and contents # crul library(crul) f <- tempfile(fileext = ".json") ## make the stub stub_request("get", "https://httpbin.org/get") %>% to_return(body = mock_file(f, "{\"hello\":\"mars\"}\n")) ## make a request (out <- crul::HttpClient$new("https://httpbin.org/get")$get(disk = f)) out$content readLines(out$content) # httr library(httr) ## make a temp file f <- tempfile(fileext = ".json") ## make the stub stub_request("get", "https://httpbin.org/get") %>% to_return( body = mock_file(path = f, payload = "{\"foo\": \"bar\"}"), headers = list("content-type" = "application/json") ) ## make a request out <- GET("https://httpbin.org/get", write_disk(f)) out ## view stubbed file content out$content readLines(out$content) content(out, "text", encoding = "UTF-8") # httr2 library(httr2) ## make a temp file f <- tempfile(fileext = ".json") ## make the stub stub_request("get", "https://httpbin.org/get") %>% to_return( body = mock_file(path = f, payload = "{\"foo\": \"bar\"}"), headers = list("content-type" = "application/json") ) ## make a request req <- request("https://httpbin.org/get") out <- req_perform(req, path = f) out ## view stubbed file content out$body readLines(out$body) # disable mocking disable() ## End(Not run)
Returns an appropriate representation of the data contained within a request body based on its encoding.
pluck_body(x)
pluck_body(x)
x |
an unexecuted crul, httr or httr2 request object |
one of the following:
NULL
if the request is not associated with a body
NULL
if an upload is used not in a list
list containing the multipart-encoded body
character vector with the JSON- or raw-encoded body, or upload form file
Remove a request stub
remove_request_stub(stub)
remove_request_stub(stub)
stub |
a request stub, of class |
logical, TRUE
if removed, FALSE
if not removed
Other stub-registry:
StubRegistry
,
stub_registry()
,
stub_registry_clear()
(x <- stub_request("get", "https://httpbin.org/get")) stub_registry() remove_request_stub(x) stub_registry()
(x <- stub_request("get", "https://httpbin.org/get")) stub_registry() remove_request_stub(x) stub_registry()
List or clear requests in the request registry
request_registry() request_registry_clear()
request_registry() request_registry_clear()
request_registry()
lists the requests that have been made
that webmockr knows about; request_registry_clear()
resets the
request registry (removes all recorded requests)
an object of class RequestRegistry
, print method gives the
requests in the registry and the number of times each one has been
performed
Other request-registry:
HashCounter
,
RequestRegistry
webmockr::enable() stub_request("get", "https://httpbin.org/get") %>% to_return(body = "success!", status = 200) # nothing in the request registry request_registry() # make the request z <- crul::HttpClient$new(url = "https://httpbin.org")$get("get") # check the request registry - the request was made 1 time request_registry() # do the request again z <- crul::HttpClient$new(url = "https://httpbin.org")$get("get") # check the request registry - now it's been made 2 times, yay! request_registry() # clear the request registry request_registry_clear() webmockr::disable()
webmockr::enable() stub_request("get", "https://httpbin.org/get") %>% to_return(body = "success!", status = 200) # nothing in the request registry request_registry() # make the request z <- crul::HttpClient$new(url = "https://httpbin.org")$get("get") # check the request registry - the request was made 1 time request_registry() # do the request again z <- crul::HttpClient$new(url = "https://httpbin.org")$get("get") # check the request registry - now it's been made 2 times, yay! request_registry() # clear the request registry request_registry_clear() webmockr::disable()
class handling all request matchers
method_pattern
xxx
uri_pattern
xxx
body_pattern
xxx
headers_pattern
xxx
new()
Create a new RequestPattern
object
RequestPattern$new( method, uri = NULL, uri_regex = NULL, query = NULL, body = NULL, headers = NULL, basic_auth = NULL )
method
the HTTP method (any, head, options, get, post, put, patch, trace, or delete). "any" matches any HTTP method. required.
uri
(character) request URI. required or uri_regex
uri_regex
(character) request URI as regex. required or uri
query
(list) query parameters, optional
body
(list) body request, optional
headers
(list) headers, optional
basic_auth
(list) vector of length 2 (username, passwdord), optional
A new RequestPattern
object
matches()
does a request signature match the selected matchers?
RequestPattern$matches(request_signature)
request_signature
a RequestSignature object
a boolean
to_s()
Print pattern for easy human consumption
RequestPattern$to_s()
a string
clone()
The objects of this class are cloneable with this method.
RequestPattern$clone(deep = FALSE)
deep
Whether to make a deep clone.
pattern classes for HTTP method MethodPattern, headers HeadersPattern, body BodyPattern, and URI/URL UriPattern
## Not run: (x <- RequestPattern$new(method = "get", uri = "httpbin.org/get")) x$body_pattern x$headers_pattern x$method_pattern x$uri_pattern x$to_s() # make a request signature rs <- RequestSignature$new(method = "get", uri = "http://httpbin.org/get") # check if it matches x$matches(rs) # regex uri (x <- RequestPattern$new(method = "get", uri_regex = ".+ossref.org")) x$uri_pattern x$uri_pattern$to_s() x$to_s() # uri with query parameters (x <- RequestPattern$new( method = "get", uri = "https://httpbin.org/get", query = list(foo = "bar") )) x$to_s() ## query params included in url, not separately (x <- RequestPattern$new( method = "get", uri = "https://httpbin.org/get?stuff=things" )) x$to_s() x$query_params # just headers (via setting method=any & uri_regex=.+) headers <- list( "User-Agent" = "Apple", "Accept-Encoding" = "gzip, deflate", "Accept" = "application/json, text/xml, application/xml, */*" ) x <- RequestPattern$new( method = "any", uri_regex = ".+", headers = headers ) x$to_s() rs <- RequestSignature$new( method = "any", uri = "http://foo.bar", options = list(headers = headers) ) rs x$matches(rs) # body x <- RequestPattern$new( method = "post", uri = "httpbin.org/post", body = list(y = crul::upload(system.file("CITATION"))) ) x$to_s() rs <- RequestSignature$new( method = "post", uri = "http://httpbin.org/post", options = list( body = list(y = crul::upload(system.file("CITATION"))) ) ) rs x$matches(rs) # basic auth x <- RequestPattern$new( method = "post", uri = "httpbin.org/post", basic_auth = c("user", "pass") ) x x$headers_pattern$to_s() x$to_s() rs <- RequestSignature$new( method = "post", uri = "http://httpbin.org/post", options = list(headers = prep_auth("user:pass")) ) rs x$matches(rs) # TRUE rs <- RequestSignature$new( method = "post", uri = "http://httpbin.org/post", options = list(headers = prep_auth("user:longpassword")) ) x$matches(rs) # FALSE ## End(Not run)
## Not run: (x <- RequestPattern$new(method = "get", uri = "httpbin.org/get")) x$body_pattern x$headers_pattern x$method_pattern x$uri_pattern x$to_s() # make a request signature rs <- RequestSignature$new(method = "get", uri = "http://httpbin.org/get") # check if it matches x$matches(rs) # regex uri (x <- RequestPattern$new(method = "get", uri_regex = ".+ossref.org")) x$uri_pattern x$uri_pattern$to_s() x$to_s() # uri with query parameters (x <- RequestPattern$new( method = "get", uri = "https://httpbin.org/get", query = list(foo = "bar") )) x$to_s() ## query params included in url, not separately (x <- RequestPattern$new( method = "get", uri = "https://httpbin.org/get?stuff=things" )) x$to_s() x$query_params # just headers (via setting method=any & uri_regex=.+) headers <- list( "User-Agent" = "Apple", "Accept-Encoding" = "gzip, deflate", "Accept" = "application/json, text/xml, application/xml, */*" ) x <- RequestPattern$new( method = "any", uri_regex = ".+", headers = headers ) x$to_s() rs <- RequestSignature$new( method = "any", uri = "http://foo.bar", options = list(headers = headers) ) rs x$matches(rs) # body x <- RequestPattern$new( method = "post", uri = "httpbin.org/post", body = list(y = crul::upload(system.file("CITATION"))) ) x$to_s() rs <- RequestSignature$new( method = "post", uri = "http://httpbin.org/post", options = list( body = list(y = crul::upload(system.file("CITATION"))) ) ) rs x$matches(rs) # basic auth x <- RequestPattern$new( method = "post", uri = "httpbin.org/post", basic_auth = c("user", "pass") ) x x$headers_pattern$to_s() x$to_s() rs <- RequestSignature$new( method = "post", uri = "http://httpbin.org/post", options = list(headers = prep_auth("user:pass")) ) rs x$matches(rs) # TRUE rs <- RequestSignature$new( method = "post", uri = "http://httpbin.org/post", options = list(headers = prep_auth("user:longpassword")) ) x$matches(rs) # FALSE ## End(Not run)
keeps track of HTTP requests
request_signatures
a HashCounter object
print()
print method for the RequestRegistry
class
RequestRegistry$print(x, ...)
x
self
...
ignored
reset()
Reset the registry to no registered requests
RequestRegistry$reset()
nothing returned; ressets registry to no requests
register_request()
Register a request
RequestRegistry$register_request(request)
request
a character string of the request, serialized from
a RequestSignature$new(...)$to_s()
nothing returned; registers the request
times_executed()
How many times has a request been made
RequestRegistry$times_executed(request_pattern)
request_pattern
an object of class RequestPattern
if no match is found for the request pattern, 0 is returned
integer, the number of times the request has been made
clone()
The objects of this class are cloneable with this method.
RequestRegistry$clone(deep = FALSE)
deep
Whether to make a deep clone.
stub_registry()
and StubRegistry
Other request-registry:
HashCounter
,
request_registry()
x <- RequestRegistry$new() z1 <- RequestSignature$new("get", "http://scottchamberlain.info") z2 <- RequestSignature$new("post", "https://httpbin.org/post") x$register_request(request = z1) x$register_request(request = z1) x$register_request(request = z2) # print method to list requests x # more complex requests w <- RequestSignature$new( method = "get", uri = "https:/httpbin.org/get", options = list(headers = list(`User-Agent` = "foobar", stuff = "things")) ) w$to_s() x$register_request(request = w) x # hashes, and number of times each requested x$request_signatures$hash # times_executed method pat <- RequestPattern$new( method = "get", uri = "https:/httpbin.org/get", headers = list(`User-Agent` = "foobar", stuff = "things") ) pat$to_s() x$times_executed(pat) z <- RequestPattern$new(method = "get", uri = "http://scottchamberlain.info") x$times_executed(z) w <- RequestPattern$new(method = "post", uri = "https://httpbin.org/post") x$times_executed(w) ## pattern with no matches - returns 0 (zero) pat <- RequestPattern$new( method = "get", uri = "http://recology.info/" ) pat$to_s() x$times_executed(pat) # reset the request registry x$reset()
x <- RequestRegistry$new() z1 <- RequestSignature$new("get", "http://scottchamberlain.info") z2 <- RequestSignature$new("post", "https://httpbin.org/post") x$register_request(request = z1) x$register_request(request = z1) x$register_request(request = z2) # print method to list requests x # more complex requests w <- RequestSignature$new( method = "get", uri = "https:/httpbin.org/get", options = list(headers = list(`User-Agent` = "foobar", stuff = "things")) ) w$to_s() x$register_request(request = w) x # hashes, and number of times each requested x$request_signatures$hash # times_executed method pat <- RequestPattern$new( method = "get", uri = "https:/httpbin.org/get", headers = list(`User-Agent` = "foobar", stuff = "things") ) pat$to_s() x$times_executed(pat) z <- RequestPattern$new(method = "get", uri = "http://scottchamberlain.info") x$times_executed(z) w <- RequestPattern$new(method = "post", uri = "https://httpbin.org/post") x$times_executed(w) ## pattern with no matches - returns 0 (zero) pat <- RequestPattern$new( method = "get", uri = "http://recology.info/" ) pat$to_s() x$times_executed(pat) # reset the request registry x$reset()
General purpose request signature builder
method
(character) an http method
uri
(character) a uri
body
(various) request body
headers
(list) named list of headers
proxies
(list) proxies as a named list
auth
(list) authentication details, as a named list
url
internal use
disk
(character) if writing to disk, the path
fields
(various) request body details
output
(various) request output details, disk, memory, etc
new()
Create a new RequestSignature
object
RequestSignature$new(method, uri, options = list())
method
the HTTP method (any, head, options, get, post, put, patch, trace, or delete). "any" matches any HTTP method. required.
uri
(character) request URI. required.
options
(list) options. optional. See Details.
A new RequestSignature
object
print()
print method for the RequestSignature
class
RequestSignature$print()
x
self
...
ignored
to_s()
Request signature to a string
RequestSignature$to_s()
a character string representation of the request signature
clone()
The objects of this class are cloneable with this method.
RequestSignature$clone(deep = FALSE)
deep
Whether to make a deep clone.
# make request signature x <- RequestSignature$new(method = "get", uri = "https:/httpbin.org/get") # method x$method # uri x$uri # request signature to string x$to_s() # headers w <- RequestSignature$new( method = "get", uri = "https:/httpbin.org/get", options = list(headers = list(`User-Agent` = "foobar", stuff = "things")) ) w w$headers w$to_s() # headers and body bb <- RequestSignature$new( method = "get", uri = "https:/httpbin.org/get", options = list( headers = list(`User-Agent` = "foobar", stuff = "things"), body = list(a = "tables") ) ) bb bb$headers bb$body bb$to_s() # with disk path f <- tempfile() bb <- RequestSignature$new( method = "get", uri = "https:/httpbin.org/get", options = list(disk = f) ) bb bb$disk bb$to_s()
# make request signature x <- RequestSignature$new(method = "get", uri = "https:/httpbin.org/get") # method x$method # uri x$uri # request signature to string x$to_s() # headers w <- RequestSignature$new( method = "get", uri = "https:/httpbin.org/get", options = list(headers = list(`User-Agent` = "foobar", stuff = "things")) ) w w$headers w$to_s() # headers and body bb <- RequestSignature$new( method = "get", uri = "https:/httpbin.org/get", options = list( headers = list(`User-Agent` = "foobar", stuff = "things"), body = list(a = "tables") ) ) bb bb$headers bb$body bb$to_s() # with disk path f <- tempfile() bb <- RequestSignature$new( method = "get", uri = "https:/httpbin.org/get", options = list(disk = f) ) bb bb$disk bb$to_s()
custom webmockr http response class
url
(character) a url
body
(various) list, character, etc
content
(various) response content/body
request_headers
(list) a named list
response_headers
(list) a named list
options
(character) list
status_code
(integer) an http status code
exception
(character) an exception message
should_timeout
(logical) should the response timeout?
new()
Create a new Response
object
Response$new(options = list())
options
(list) a list of options
A new Response
object
print()
print method for the Response
class
Response$print(x, ...)
x
self
...
ignored
set_url()
set the url for the response
Response$set_url(url)
url
(character) a url
nothing returned; sets url
get_url()
get the url for the response
Response$get_url()
(character) a url
set_request_headers()
set the request headers for the response
Response$set_request_headers(headers, capitalize = TRUE)
headers
(list) named list
capitalize
(logical) whether to capitalize first letters of
each header; default: TRUE
nothing returned; sets request headers on the response
get_request_headers()
get the request headers for the response
Response$get_request_headers()
(list) request headers, a named list
set_response_headers()
set the response headers for the response
Response$set_response_headers(headers, capitalize = TRUE)
headers
(list) named list
capitalize
(logical) whether to capitalize first letters of
each header; default: TRUE
nothing returned; sets response headers on the response
get_respone_headers()
get the response headers for the response
Response$get_respone_headers()
(list) response headers, a named list
set_body()
set the body of the response
Response$set_body(body, disk = FALSE)
body
(various types)
disk
(logical) whether its on disk; default: FALSE
nothing returned; sets body on the response
get_body()
get the body of the response
Response$get_body()
various
set_status()
set the http status of the response
Response$set_status(status)
status
(integer) the http status
nothing returned; sets the http status of the response
get_status()
get the http status of the response
Response$get_status()
(integer) the http status
set_exception()
set an exception
Response$set_exception(exception)
exception
(character) an exception string
nothing returned; sets an exception
get_exception()
get the exception, if set
Response$get_exception()
(character) an exception
clone()
The objects of this class are cloneable with this method.
Response$clone(deep = FALSE)
deep
Whether to make a deep clone.
## Not run: (x <- Response$new()) x$set_url("https://httpbin.org/get") x x$set_request_headers(list("Content-Type" = "application/json")) x x$request_headers x$set_response_headers(list("Host" = "httpbin.org")) x x$response_headers x$set_status(404) x x$get_status() x$set_body("hello world") x x$get_body() # raw body x$set_body(charToRaw("hello world")) x x$get_body() x$set_exception("exception") x x$get_exception() ## End(Not run)
## Not run: (x <- Response$new()) x$set_url("https://httpbin.org/get") x x$set_request_headers(list("Content-Type" = "application/json")) x x$request_headers x$set_response_headers(list("Host" = "httpbin.org")) x x$response_headers x$set_status(404) x x$get_status() x$set_body("hello world") x x$get_body() # raw body x$set_body(charToRaw("hello world")) x x$get_body() x$set_exception("exception") x x$get_exception() ## End(Not run)
Requires the Suggested package diffobj
stub_body_diff(stub = last_stub(), request = last_request())
stub_body_diff(stub = last_stub(), request = last_request())
stub |
object of class |
request |
object of class |
Returns error message if either stub
or request
are NULL
.
Even though you may not intentionally pass in a NULL
, the return values
of last_stub()
and last_request()
when there's nothing found is NULL
.
Under the hood the Suggested package diffobj
is used to do the comparison.
object of class Diff
from the diffobj package
webmockr_configure()
to toggle webmockr
showing request body
diffs when there's not a match. stub_body_diff()
is offered as a manual
way to compare requests and stubs - whereas turning on with
webmockr_configure()
will do the diff for you.
# stops with error if no stub and request request_registry_clear() stub_registry_clear() stub_body_diff() # Gives diff when there's a stub and request found - however, no request body stub_request("get", "https://hb.opencpu.org/get") enable() library(crul) HttpClient$new("https://hb.opencpu.org")$get(path = "get") stub_body_diff() # Gives diff when there's a stub and request found - with request body stub_request("post", "https://hb.opencpu.org/post") %>% wi_th(body = list(apple = "green")) enable() library(crul) HttpClient$new("https://hb.opencpu.org")$post( path = "post", body = list(apple = "red") ) stub_body_diff() # Gives diff when there's a stub and request found - with request body stub_request("post", "https://hb.opencpu.org/post") %>% wi_th(body = "the quick brown fox") HttpClient$new("https://hb.opencpu.org")$post( path = "post", body = "the quick black fox" ) stub_body_diff()
# stops with error if no stub and request request_registry_clear() stub_registry_clear() stub_body_diff() # Gives diff when there's a stub and request found - however, no request body stub_request("get", "https://hb.opencpu.org/get") enable() library(crul) HttpClient$new("https://hb.opencpu.org")$get(path = "get") stub_body_diff() # Gives diff when there's a stub and request found - with request body stub_request("post", "https://hb.opencpu.org/post") %>% wi_th(body = list(apple = "green")) enable() library(crul) HttpClient$new("https://hb.opencpu.org")$post( path = "post", body = list(apple = "red") ) stub_body_diff() # Gives diff when there's a stub and request found - with request body stub_request("post", "https://hb.opencpu.org/post") %>% wi_th(body = "the quick brown fox") HttpClient$new("https://hb.opencpu.org")$post( path = "post", body = "the quick black fox" ) stub_body_diff()
List stubs in the stub registry
stub_registry()
stub_registry()
an object of class StubRegistry
, print method gives the
stubs in the registry
Other stub-registry:
StubRegistry
,
remove_request_stub()
,
stub_registry_clear()
# make a stub stub_request("get", "https://httpbin.org/get") %>% to_return(body = "success!", status = 200) # check the stub registry, there should be one in there stub_registry() # make another stub stub_request("get", "https://httpbin.org/get") %>% to_return(body = "woopsy", status = 404) # check the stub registry, now there are two there stub_registry() # to clear the stub registry stub_registry_clear()
# make a stub stub_request("get", "https://httpbin.org/get") %>% to_return(body = "success!", status = 200) # check the stub registry, there should be one in there stub_registry() # make another stub stub_request("get", "https://httpbin.org/get") %>% to_return(body = "woopsy", status = 404) # check the stub registry, now there are two there stub_registry() # to clear the stub registry stub_registry_clear()
Clear all stubs in the stub registry
stub_registry_clear()
stub_registry_clear()
an empty list invisibly
Other stub-registry:
StubRegistry
,
remove_request_stub()
,
stub_registry()
(x <- stub_request("get", "https://httpbin.org/get")) stub_registry() stub_registry_clear() stub_registry()
(x <- stub_request("get", "https://httpbin.org/get")) stub_registry() stub_registry_clear() stub_registry()
Stub an http request
stub_request(method = "get", uri = NULL, uri_regex = NULL)
stub_request(method = "get", uri = NULL, uri_regex = NULL)
method |
(character) HTTP method, one of "get", "post", "put", "patch", "head", "delete", "options" - or the special "any" (for any method) |
uri |
(character) The request uri. Can be a full or partial uri.
webmockr can match uri's without the "http" scheme, but does
not match if the scheme is "https". required, unless |
uri_regex |
(character) A URI represented as regex. required, if |
Internally, this calls StubbedRequest which handles the logic
See stub_registry()
for listing stubs, stub_registry_clear()
for removing all stubs and remove_request_stub()
for removing specific
stubs
If multiple stubs match the same request, we use the first stub. So if you want to use a stub that was created after an earlier one that matches, remove the earlier one(s).
Note on wi_th()
: If you pass query
, values are coerced to character
class in the recorded stub. You can pass numeric, integer, etc., but
all will be coerced to character.
See wi_th()
for details on request body/query/headers and
to_return()
for details on how response status/body/headers
are handled
an object of class StubbedRequest
, with print method describing
the stub.
When you use uri
, we compare the URIs without query params AND
also the query params themselves without the URIs.
When you use uri_regex
we don't compare URIs and query params;
we just use your regex string defined in uri_regex
as the pattern
for a call to grepl
To construct stubs, one uses stub_request()
first - which registers
the stub in the stub registry. Any additional calls to modify the stub
with for example wi_th()
or to_return()
can error. In those error
cases we ideally want to remove (unregister) the stub because you
certainly don't want a registered stub that is not exactly what you
intended.
When you encounter an error creating a stub you should see a warning message that the stub has been removed, for example:
stub_request("get", "https://httpbin.org/get") %>% wi_th(query = mtcars) #> Error in `wi_th()`: #> ! z$query must be of class list or partial #> Run `rlang::last_trace()` to see where the error occurred. #> Warning message: #> Encountered an error constructing stub #> • Removed stub #> • To see a list of stubs run stub_registry()
Trailing slashes are dropped from stub URIs before matching
wi_th()
, to_return()
, to_timeout()
, to_raise()
,
mock_file()
## Not run: # basic stubbing stub_request("get", "https://httpbin.org/get") stub_request("post", "https://httpbin.org/post") # any method, use "any" stub_request("any", "https://httpbin.org/get") # list stubs stub_registry() # request headers stub_request("get", "https://httpbin.org/get") %>% wi_th(headers = list("User-Agent" = "R")) # request body stub_request("post", "https://httpbin.org/post") %>% wi_th(body = list(foo = "bar")) stub_registry() library(crul) x <- crul::HttpClient$new(url = "https://httpbin.org") crul::mock() x$post("post", body = list(foo = "bar")) # add expectation with to_return stub_request("get", "https://httpbin.org/get") %>% wi_th( query = list(hello = "world"), headers = list("User-Agent" = "R") ) %>% to_return(status = 200, body = "stuff", headers = list(a = 5)) # list stubs again stub_registry() # regex stub_request("get", uri_regex = ".+ample\\..") # set stub an expectation to timeout stub_request("get", "https://httpbin.org/get") %>% to_timeout() x <- crul::HttpClient$new(url = "https://httpbin.org") res <- x$get("get") # raise exception library(fauxpas) stub_request("get", "https://httpbin.org/get") %>% to_raise(HTTPAccepted) stub_request("get", "https://httpbin.org/get") %>% to_raise(HTTPAccepted, HTTPGone) x <- crul::HttpClient$new(url = "https://httpbin.org") stub_request("get", "https://httpbin.org/get") %>% to_raise(HTTPBadGateway) crul::mock() x$get("get") # pass a list to .list z <- stub_request("get", "https://httpbin.org/get") wi_th(z, .list = list(query = list(foo = "bar"))) # just body stub_request("any", uri_regex = ".+") %>% wi_th(body = list(foo = "bar")) ## with crul library(crul) x <- crul::HttpClient$new(url = "https://httpbin.org") crul::mock() x$post("post", body = list(foo = "bar")) x$put("put", body = list(foo = "bar")) ## with httr library(httr) httr_mock() POST("https://example.com", body = list(foo = "bar")) PUT("https://google.com", body = list(foo = "bar")) # just headers headers <- list( "Accept-Encoding" = "gzip, deflate", "Accept" = "application/json, text/xml, application/xml, */*" ) stub_request("any", uri_regex = ".+") %>% wi_th(headers = headers) library(crul) x <- crul::HttpClient$new(url = "https://httpbin.org", headers = headers) crul::mock() x$post("post") x$put("put", body = list(foo = "bar")) x$get("put", query = list(stuff = 3423234L)) # many responses ## the first response matches the first to_return call, and so on stub_request("get", "https://httpbin.org/get") %>% to_return(status = 200, body = "foobar", headers = list(a = 5)) %>% to_return(status = 200, body = "bears", headers = list(b = 6)) con <- crul::HttpClient$new(url = "https://httpbin.org") con$get("get")$parse("UTF-8") con$get("get")$parse("UTF-8") ## OR, use times with to_return() to repeat the same response many times library(fauxpas) stub_request("get", "https://httpbin.org/get") %>% to_return(status = 200, body = "apple-pie", times = 2) %>% to_raise(HTTPUnauthorized) con <- crul::HttpClient$new(url = "https://httpbin.org") con$get("get")$parse("UTF-8") con$get("get")$parse("UTF-8") con$get("get")$parse("UTF-8") # partial matching ## query parameters library(httr) enable() ### matches stub_request("get", "https://hb.opencpu.org/get") %>% wi_th(query = including(list(fruit = "pear"))) %>% to_return(body = "matched on partial query!") resp <- GET("https://hb.opencpu.org/get", query = list(fruit = "pear", bread = "scone") ) rawToChar(content(resp)) ### doesn't match stub_registry_clear() stub_request("get", "https://hb.opencpu.org/get") %>% wi_th(query = list(fruit = "pear")) %>% to_return(body = "didn't match, ugh!") # GET("https://hb.opencpu.org/get", # query = list(fruit = "pear", meat = "chicken")) ## request body ### matches - including stub_request("post", "https://hb.opencpu.org/post") %>% wi_th(body = including(list(fruit = "pear"))) %>% to_return(body = "matched on partial body!") resp <- POST("https://hb.opencpu.org/post", body = list(fruit = "pear", meat = "chicken") ) rawToChar(content(resp)) ### matches - excluding stub_request("post", "https://hb.opencpu.org/post") %>% wi_th(body = excluding(list(fruit = "pear"))) %>% to_return(body = "matched on partial body!") res <- POST("https://hb.opencpu.org/post", body = list(color = "blue") ) rawToChar(content(res)) # POST("https://hb.opencpu.org/post", # body = list(fruit = "pear", meat = "chicken")) # clear all stubs stub_registry() stub_registry_clear() ## End(Not run)
## Not run: # basic stubbing stub_request("get", "https://httpbin.org/get") stub_request("post", "https://httpbin.org/post") # any method, use "any" stub_request("any", "https://httpbin.org/get") # list stubs stub_registry() # request headers stub_request("get", "https://httpbin.org/get") %>% wi_th(headers = list("User-Agent" = "R")) # request body stub_request("post", "https://httpbin.org/post") %>% wi_th(body = list(foo = "bar")) stub_registry() library(crul) x <- crul::HttpClient$new(url = "https://httpbin.org") crul::mock() x$post("post", body = list(foo = "bar")) # add expectation with to_return stub_request("get", "https://httpbin.org/get") %>% wi_th( query = list(hello = "world"), headers = list("User-Agent" = "R") ) %>% to_return(status = 200, body = "stuff", headers = list(a = 5)) # list stubs again stub_registry() # regex stub_request("get", uri_regex = ".+ample\\..") # set stub an expectation to timeout stub_request("get", "https://httpbin.org/get") %>% to_timeout() x <- crul::HttpClient$new(url = "https://httpbin.org") res <- x$get("get") # raise exception library(fauxpas) stub_request("get", "https://httpbin.org/get") %>% to_raise(HTTPAccepted) stub_request("get", "https://httpbin.org/get") %>% to_raise(HTTPAccepted, HTTPGone) x <- crul::HttpClient$new(url = "https://httpbin.org") stub_request("get", "https://httpbin.org/get") %>% to_raise(HTTPBadGateway) crul::mock() x$get("get") # pass a list to .list z <- stub_request("get", "https://httpbin.org/get") wi_th(z, .list = list(query = list(foo = "bar"))) # just body stub_request("any", uri_regex = ".+") %>% wi_th(body = list(foo = "bar")) ## with crul library(crul) x <- crul::HttpClient$new(url = "https://httpbin.org") crul::mock() x$post("post", body = list(foo = "bar")) x$put("put", body = list(foo = "bar")) ## with httr library(httr) httr_mock() POST("https://example.com", body = list(foo = "bar")) PUT("https://google.com", body = list(foo = "bar")) # just headers headers <- list( "Accept-Encoding" = "gzip, deflate", "Accept" = "application/json, text/xml, application/xml, */*" ) stub_request("any", uri_regex = ".+") %>% wi_th(headers = headers) library(crul) x <- crul::HttpClient$new(url = "https://httpbin.org", headers = headers) crul::mock() x$post("post") x$put("put", body = list(foo = "bar")) x$get("put", query = list(stuff = 3423234L)) # many responses ## the first response matches the first to_return call, and so on stub_request("get", "https://httpbin.org/get") %>% to_return(status = 200, body = "foobar", headers = list(a = 5)) %>% to_return(status = 200, body = "bears", headers = list(b = 6)) con <- crul::HttpClient$new(url = "https://httpbin.org") con$get("get")$parse("UTF-8") con$get("get")$parse("UTF-8") ## OR, use times with to_return() to repeat the same response many times library(fauxpas) stub_request("get", "https://httpbin.org/get") %>% to_return(status = 200, body = "apple-pie", times = 2) %>% to_raise(HTTPUnauthorized) con <- crul::HttpClient$new(url = "https://httpbin.org") con$get("get")$parse("UTF-8") con$get("get")$parse("UTF-8") con$get("get")$parse("UTF-8") # partial matching ## query parameters library(httr) enable() ### matches stub_request("get", "https://hb.opencpu.org/get") %>% wi_th(query = including(list(fruit = "pear"))) %>% to_return(body = "matched on partial query!") resp <- GET("https://hb.opencpu.org/get", query = list(fruit = "pear", bread = "scone") ) rawToChar(content(resp)) ### doesn't match stub_registry_clear() stub_request("get", "https://hb.opencpu.org/get") %>% wi_th(query = list(fruit = "pear")) %>% to_return(body = "didn't match, ugh!") # GET("https://hb.opencpu.org/get", # query = list(fruit = "pear", meat = "chicken")) ## request body ### matches - including stub_request("post", "https://hb.opencpu.org/post") %>% wi_th(body = including(list(fruit = "pear"))) %>% to_return(body = "matched on partial body!") resp <- POST("https://hb.opencpu.org/post", body = list(fruit = "pear", meat = "chicken") ) rawToChar(content(resp)) ### matches - excluding stub_request("post", "https://hb.opencpu.org/post") %>% wi_th(body = excluding(list(fruit = "pear"))) %>% to_return(body = "matched on partial body!") res <- POST("https://hb.opencpu.org/post", body = list(color = "blue") ) rawToChar(content(res)) # POST("https://hb.opencpu.org/post", # body = list(fruit = "pear", meat = "chicken")) # clear all stubs stub_registry() stub_registry_clear() ## End(Not run)
stubbed request class underlying stub_request()
method
(xx) xx
uri
(xx) xx
uri_regex
(xx) xx
regex
a logical
uri_parts
(xx) xx
host
(xx) xx
query
(xx) xx
body
(xx) xx
basic_auth
(xx) xx
request_headers
(xx) xx
response_headers
(xx) xx
responses_sequences
(xx) xx
status_code
(xx) xx
counter
a StubCounter object
new()
Create a new StubbedRequest
object
StubbedRequest$new(method, uri = NULL, uri_regex = NULL)
method
the HTTP method (any, head, get, post, put, patch, or delete). "any" matches any HTTP method. required.
uri
(character) request URI. either this or uri_regex
required. webmockr can match uri's without the "http" scheme,
but does not match if the scheme is "https". required, unless
uri_regex
given. See UriPattern for more.
uri_regex
(character) request URI as regex. either this or uri
required
A new StubbedRequest
object
print()
print method for the StubbedRequest
class
StubbedRequest$print(x, ...)
x
self
...
ignored
with()
Set expectations for what's given in HTTP request
StubbedRequest$with( query = NULL, body = NULL, headers = NULL, basic_auth = NULL )
query
(list) request query params, as a named list. optional
body
(list) request body, as a named list. optional
headers
(list) request headers as a named list. optional.
basic_auth
(character) basic authentication. optional.
nothing returned; sets only
to_return()
Set expectations for what's returned in HTTP response
StubbedRequest$to_return(status, body, headers)
status
(numeric) an HTTP status code
body
(list) response body, one of: character
, json
,
list
, raw
, numeric
, NULL
, FALSE
, or a file connection
(other connetion types not supported)
headers
(list) named list, response headers. optional.
nothing returned; sets whats to be returned
to_timeout()
Response should time out
StubbedRequest$to_timeout()
nothing returned
to_raise()
Response should raise an exception x
StubbedRequest$to_raise(x)
x
(character) an exception message
nothing returned
to_s()
Response as a character string
StubbedRequest$to_s()
(character) the response as a string
reset()
Reset the counter for the stub
StubbedRequest$reset()
nothing returned; resets stub counter to no requests
clone()
The objects of this class are cloneable with this method.
StubbedRequest$clone(deep = FALSE)
deep
Whether to make a deep clone.
## Not run: x <- StubbedRequest$new(method = "get", uri = "api.crossref.org") x$method x$uri x$with(headers = list("User-Agent" = "R", apple = "good")) x$to_return(status = 200, body = "foobar", headers = list(a = 5)) x x$to_s() # query x <- StubbedRequest$new(method = "get", uri = "httpbin.org") x$with(query = list(a = 5)) x x$to_s() ## including x <- StubbedRequest$new(method = "get", uri = "httpbin.org") x$with(query = including(list(a = 5))) x x$to_s() x$with(query = including(list(a = 5, b = 7))) x$to_s() ## excluding x <- StubbedRequest$new(method = "get", uri = "httpbin.org") x$with(query = excluding(list(a = 5))) x x$to_s() # many to_return's x <- StubbedRequest$new(method = "get", uri = "httpbin.org") x$to_return(status = 200, body = "foobar", headers = list(a = 5)) x$to_return(status = 200, body = "bears", headers = list(b = 6)) x x$to_s() # raw body x <- StubbedRequest$new(method = "get", uri = "api.crossref.org") x$to_return(status = 200, body = raw(0), headers = list(a = 5)) x$to_s() x x <- StubbedRequest$new(method = "get", uri = "api.crossref.org") x$to_return( status = 200, body = charToRaw("foo bar"), headers = list(a = 5) ) x$to_s() x # basic auth x <- StubbedRequest$new(method = "get", uri = "api.crossref.org") x$with(basic_auth = c("foo", "bar")) x$to_s() x # file path x <- StubbedRequest$new(method = "get", uri = "api.crossref.org") f <- tempfile() x$to_return(status = 200, body = file(f), headers = list(a = 5)) x x$to_s() unlink(f) # to_file(): file path and payload to go into the file # payload written to file during mocked response creation x <- StubbedRequest$new(method = "get", uri = "api.crossref.org") f <- tempfile() x$to_return( status = 200, body = mock_file(f, "{\"foo\": \"bar\"}"), headers = list(a = 5) ) x x$to_s() unlink(f) # uri_regex (x <- StubbedRequest$new(method = "get", uri_regex = ".+ossref.org")) x$method x$uri_regex x$to_s() # to timeout (x <- StubbedRequest$new(method = "get", uri_regex = ".+ossref.org")) x$to_s() x$to_timeout() x$to_s() x # to raise library(fauxpas) (x <- StubbedRequest$new(method = "get", uri_regex = ".+ossref.org")) x$to_s() x$to_raise(HTTPBadGateway) x$to_s() x ## End(Not run)
## Not run: x <- StubbedRequest$new(method = "get", uri = "api.crossref.org") x$method x$uri x$with(headers = list("User-Agent" = "R", apple = "good")) x$to_return(status = 200, body = "foobar", headers = list(a = 5)) x x$to_s() # query x <- StubbedRequest$new(method = "get", uri = "httpbin.org") x$with(query = list(a = 5)) x x$to_s() ## including x <- StubbedRequest$new(method = "get", uri = "httpbin.org") x$with(query = including(list(a = 5))) x x$to_s() x$with(query = including(list(a = 5, b = 7))) x$to_s() ## excluding x <- StubbedRequest$new(method = "get", uri = "httpbin.org") x$with(query = excluding(list(a = 5))) x x$to_s() # many to_return's x <- StubbedRequest$new(method = "get", uri = "httpbin.org") x$to_return(status = 200, body = "foobar", headers = list(a = 5)) x$to_return(status = 200, body = "bears", headers = list(b = 6)) x x$to_s() # raw body x <- StubbedRequest$new(method = "get", uri = "api.crossref.org") x$to_return(status = 200, body = raw(0), headers = list(a = 5)) x$to_s() x x <- StubbedRequest$new(method = "get", uri = "api.crossref.org") x$to_return( status = 200, body = charToRaw("foo bar"), headers = list(a = 5) ) x$to_s() x # basic auth x <- StubbedRequest$new(method = "get", uri = "api.crossref.org") x$with(basic_auth = c("foo", "bar")) x$to_s() x # file path x <- StubbedRequest$new(method = "get", uri = "api.crossref.org") f <- tempfile() x$to_return(status = 200, body = file(f), headers = list(a = 5)) x x$to_s() unlink(f) # to_file(): file path and payload to go into the file # payload written to file during mocked response creation x <- StubbedRequest$new(method = "get", uri = "api.crossref.org") f <- tempfile() x$to_return( status = 200, body = mock_file(f, "{\"foo\": \"bar\"}"), headers = list(a = 5) ) x x$to_s() unlink(f) # uri_regex (x <- StubbedRequest$new(method = "get", uri_regex = ".+ossref.org")) x$method x$uri_regex x$to_s() # to timeout (x <- StubbedRequest$new(method = "get", uri_regex = ".+ossref.org")) x$to_s() x$to_timeout() x$to_s() x # to raise library(fauxpas) (x <- StubbedRequest$new(method = "get", uri_regex = ".+ossref.org")) x$to_s() x$to_raise(HTTPBadGateway) x$to_s() x ## End(Not run)
hash with counter to store requests and count number of requests made against the stub
hash
(list) a list for internal use only, with elements
key
, sig
, and count
put()
Register a request by it's key
StubCounter$put(x)
x
an object of class RequestSignature
nothing returned; registers request & iterates internal counter
count()
Get the count of number of times any matching request has been made against this stub
StubCounter$count()
clone()
The objects of this class are cloneable with this method.
StubCounter$clone(deep = FALSE)
deep
Whether to make a deep clone.
x <- StubCounter$new() x x$hash x$count() z <- RequestSignature$new(method = "get", uri = "https:/httpbin.org/get") x$put(z) x$count() x$put(z) x$count()
x <- StubCounter$new() x x$hash x$count() z <- RequestSignature$new(method = "get", uri = "https:/httpbin.org/get") x$put(z) x$count() x$put(z) x$count()
stub registry to keep track of StubbedRequest stubs
request_stubs
(list) list of request stubs
print()
print method for the StubRegistry
class
StubRegistry$print(x, ...)
x
self
...
ignored
register_stub()
Register a stub
StubRegistry$register_stub(stub)
stub
an object of type StubbedRequest
nothing returned; registers the stub
find_stubbed_request()
Find a stubbed request
StubRegistry$find_stubbed_request(req)
req
an object of class RequestSignature
an object of type StubbedRequest, if matched
request_stub_for()
Find a stubbed request
StubRegistry$request_stub_for(request_signature, count = TRUE)
request_signature
an object of class RequestSignature
count
(bool) iterate counter or not. default: TRUE
logical, 1 or more
remove_request_stub()
Remove a stubbed request by matching request signature
StubRegistry$remove_request_stub(stub)
stub
an object of type StubbedRequest
nothing returned; removes the stub from the registry
remove_all_request_stubs()
Remove all request stubs
StubRegistry$remove_all_request_stubs()
nothing returned; removes all request stubs
is_registered()
Find a stubbed request from a request signature
StubRegistry$is_registered(x)
x
an object of class RequestSignature
nothing returned; registers the stub
is_stubbed()
Check if a stubbed request is in the stub registry
StubRegistry$is_stubbed(stub)
stub
an object of class StubbedRequest
single boolean, TRUE
or FALSE
clone()
The objects of this class are cloneable with this method.
StubRegistry$clone(deep = FALSE)
deep
Whether to make a deep clone.
Other stub-registry:
remove_request_stub()
,
stub_registry()
,
stub_registry_clear()
## Not run: # Make a stub stub1 <- StubbedRequest$new(method = "get", uri = "api.crossref.org") stub1$with(headers = list("User-Agent" = "R")) stub1$to_return(status = 200, body = "foobar", headers = list()) stub1 # Make another stub stub2 <- StubbedRequest$new(method = "get", uri = "api.crossref.org") stub2 # Put both stubs in the stub registry reg <- StubRegistry$new() reg$register_stub(stub = stub1) reg$register_stub(stub = stub2) reg reg$request_stubs ## End(Not run)
## Not run: # Make a stub stub1 <- StubbedRequest$new(method = "get", uri = "api.crossref.org") stub1$with(headers = list("User-Agent" = "R")) stub1$to_return(status = 200, body = "foobar", headers = list()) stub1 # Make another stub stub2 <- StubbedRequest$new(method = "get", uri = "api.crossref.org") stub2 # Put both stubs in the stub registry reg <- StubRegistry$new() reg$register_stub(stub = stub1) reg$register_stub(stub = stub2) reg reg$request_stubs ## End(Not run)
Set raise error condition
to_raise(.data, ...)
to_raise(.data, ...)
.data |
input. Anything that can be coerced to a |
... |
One or more HTTP exceptions from the fauxpas package. Run
|
The behavior in the future will be:
When multiple exceptions are passed, the first is used on the first mock, the second on the second mock, and so on. Subsequent mocks use the last exception
But for now, only the first exception is used until we get that fixed
an object of class StubbedRequest
, with print method describing
the stub
to_raise()
always raises a stop condition, while to_return(status=xyz)
only
sets the status code on the returned HTTP response object. So if you want to
raise a stop condition then to_raise()
is what you want. But if you
don't want to raise a stop condition use to_return()
. Use cases for each
vary. For example, in a unit test you may have a test expecting a 503 error;
in this case to_raise()
makes sense. In another case, if a unit test
expects to test some aspect of an HTTP response object that httr, httr2,
or crul typically returns, then you'll want to_return()
.
see examples in stub_request()
Set response status code, response body, and/or response headers
to_return(.data, ..., .list = list(), times = 1)
to_return(.data, ..., .list = list(), times = 1)
.data |
input. Anything that can be coerced to a |
... |
Comma separated list of named variables. accepts the following:
|
.list |
named list, has to be one of 'status', 'body',
and/or 'headers'. An alternative to passing in via |
times |
(integer) number of times the given response should be returned; default: 1. value must be greater than or equal to 1. Very large values probably don't make sense, but there's no maximum value. See Details. |
Values for status, body, and headers:
status: (numeric/integer) three digit status code
body: various: character
, json
, list
, raw
, numeric
,
NULL
, FALSE
, a file connection (other connetion types
not supported), or a mock_file
function call (see mock_file()
)
headers: (list) a named list, must be named
response headers are returned with all lowercase names and the values
are all of type character. if numeric/integer values are given
(e.g., to_return(headers = list(a = 10))
), we'll coerce any
numeric/integer values to character.
an object of class StubbedRequest
, with print method describing
the stub
to_return()
You can add more than one to_return()
to a webmockr stub (including
to_raise()
, to_timeout()
). Each one is a HTTP response returned.
That is, you'll match to an HTTP request based on stub_request()
and
wi_th()
; the first time the request is made, the first response
is returned; the second time the reqeust is made, the second response
is returned; and so on.
Be aware that webmockr has to track number of requests
(see request_registry()
), and so if you use multiple to_return()
or the times
parameter, you must clear the request registry
in order to go back to mocking responses from the start again.
webmockr_reset()
clears the stub registry and the request registry,
after which you can use multiple responses again (after creating
your stub(s) again of course)
to_raise()
always raises a stop condition, while to_return(status=xyz)
only
sets the status code on the returned HTTP response object. So if you want to
raise a stop condition then to_raise()
is what you want. But if you
don't want to raise a stop condition use to_return()
. Use cases for each
vary. For example, in a unit test you may have a test expecting a 503 error;
in this case to_raise()
makes sense. In another case, if a unit test
expects to test some aspect of an HTTP response object that httr, httr2,
or crul typically returns, then you'll want to_return()
.
see more examples in stub_request()
# first, make a stub object foo <- function() { stub_request("post", "https://httpbin.org/post") } # add status, body and/or headers foo() %>% to_return(status = 200) foo() %>% to_return(body = "stuff") foo() %>% to_return(body = list(a = list(b = "world"))) foo() %>% to_return(headers = list(a = 5)) foo() %>% to_return(status = 200, body = "stuff", headers = list(a = 5)) # .list - pass in a named list instead foo() %>% to_return(.list = list(body = list(foo = "bar"))) # multiple responses using chained `to_return()` foo() %>% to_return(body = "stuff") %>% to_return(body = "things") # many of the same response using the times parameter foo() %>% to_return(body = "stuff", times = 3)
# first, make a stub object foo <- function() { stub_request("post", "https://httpbin.org/post") } # add status, body and/or headers foo() %>% to_return(status = 200) foo() %>% to_return(body = "stuff") foo() %>% to_return(body = list(a = list(b = "world"))) foo() %>% to_return(headers = list(a = 5)) foo() %>% to_return(status = 200, body = "stuff", headers = list(a = 5)) # .list - pass in a named list instead foo() %>% to_return(.list = list(body = list(foo = "bar"))) # multiple responses using chained `to_return()` foo() %>% to_return(body = "stuff") %>% to_return(body = "things") # many of the same response using the times parameter foo() %>% to_return(body = "stuff", times = 3)
Set timeout as an expected return on a match
to_timeout(.data)
to_timeout(.data)
.data |
input. Anything that can be coerced to a |
an object of class StubbedRequest
, with print method describing
the stub
see examples in stub_request()
webmockr configuration
webmockr_configure( allow_net_connect = FALSE, allow_localhost = FALSE, allow = NULL, show_stubbing_instructions = TRUE, show_body_diff = FALSE ) webmockr_configure_reset() webmockr_configuration() webmockr_allow_net_connect() webmockr_disable_net_connect(allow = NULL) webmockr_net_connect_allowed(uri = NULL)
webmockr_configure( allow_net_connect = FALSE, allow_localhost = FALSE, allow = NULL, show_stubbing_instructions = TRUE, show_body_diff = FALSE ) webmockr_configure_reset() webmockr_configuration() webmockr_allow_net_connect() webmockr_disable_net_connect(allow = NULL) webmockr_net_connect_allowed(uri = NULL)
allow_net_connect |
(logical) Default: |
allow_localhost |
(logical) Default: |
allow |
(character) one or more URI/URL to allow (and by extension all others are not allowed) |
show_stubbing_instructions |
(logical) Default: |
show_body_diff |
(logical) Default: |
uri |
(character) a URI/URL as a character string - to determine whether or not it is allowed |
If there are stubs found for a request, even if net connections are
allowed (by running webmockr_allow_net_connect()
) the stubbed
response will be returned. If no stub is found, and net connections
are allowed, then a real HTTP request can be made.
## Not run: webmockr_configure() webmockr_configure( allow_localhost = TRUE ) webmockr_configuration() webmockr_configure_reset() webmockr_allow_net_connect() webmockr_net_connect_allowed() # disable net connect for any URIs webmockr_disable_net_connect() ### gives NULL with no URI passed webmockr_net_connect_allowed() # disable net connect EXCEPT FOR given URIs webmockr_disable_net_connect(allow = "google.com") ### is a specific URI allowed? webmockr_net_connect_allowed("google.com") # show body diff webmockr_configure(show_body_diff = TRUE) ## End(Not run)
## Not run: webmockr_configure() webmockr_configure( allow_localhost = TRUE ) webmockr_configuration() webmockr_configure_reset() webmockr_allow_net_connect() webmockr_net_connect_allowed() # disable net connect for any URIs webmockr_disable_net_connect() ### gives NULL with no URI passed webmockr_net_connect_allowed() # disable net connect EXCEPT FOR given URIs webmockr_disable_net_connect(allow = "google.com") ### is a specific URI allowed? webmockr_net_connect_allowed("google.com") # show body diff webmockr_configure(show_body_diff = TRUE) ## End(Not run)
Clear all stubs and the request counter
webmockr_reset()
webmockr_reset()
this function runs stub_registry_clear()
and
request_registry_clear()
- so you can run those two yourself
to achieve the same thing
nothing
stub_registry_clear()
request_registry_clear()
# webmockr_reset()
# webmockr_reset()
webmockr_enable()
: Function removed, see enable()
webmockr_disable()
: Function removed, see disable()
to_return_: Only to_return()
is available now
Set query params, request body, request headers and/or basic_auth
wi_th(.data, ..., .list = list())
wi_th(.data, ..., .list = list())
.data |
input. Anything that can be coerced to a |
... |
Comma separated list of named variables. accepts the following:
|
.list |
named list, has to be one of |
with
is a function in the base
package, so we went with
wi_th
Values for query, body, headers, and basic_auth:
query: (list) a named list. values are coerced to character class in the recorded stub. You can pass numeric, integer, etc., but all will be coerced to character.
body: various, including character string, list, raw, numeric,
upload (crul::upload()
, httr::upload_file()
, curl::form_file()
, or
curl::form_data()
they both create the same object in the end). for the
special case of an empty request body use NA
instead of NULL
because
with NULL
we can't determine if the user did not supply a body or
they supplied NULL
to indicate an empty body.
headers: (list) a named list
basic_auth: (character) a length two vector, username and password. We don't do any checking of the username/password except to detect edge cases where for example, the username/password were probably not set by the user on purpose (e.g., a URL is picked up by an environment variable). Only basic authentication supported https://en.wikipedia.org/wiki/Basic_access_authentication.
Note that there is no regex matching on query, body, or headers. They are tested for matches in the following ways:
query: compare stubs and requests with identical()
. this compares
named lists, so both list names and values are compared
body: varies depending on the body format (list vs. character, etc.)
headers: compare stub and request values with ==
. list names are
compared with %in%
. basic_auth
is included in headers (with the name
Authorization)
an object of class StubbedRequest
, with print method describing
the stub
see more examples in stub_request()
# first, make a stub object req <- stub_request("post", "https://httpbin.org/post") # add body # list wi_th(req, body = list(foo = "bar")) # string wi_th(req, body = '{"foo": "bar"}') # raw wi_th(req, body = charToRaw('{"foo": "bar"}')) # numeric wi_th(req, body = 5) # an upload wi_th(req, body = crul::upload(system.file("CITATION"))) # wi_th(req, body = httr::upload_file(system.file("CITATION"))) # add query - has to be a named list wi_th(req, query = list(foo = "bar")) # add headers - has to be a named list wi_th(req, headers = list(foo = "bar")) wi_th(req, headers = list(`User-Agent` = "webmockr/v1", hello = "world")) # .list - pass in a named list instead wi_th(req, .list = list(body = list(foo = "bar"))) # basic authentication wi_th(req, basic_auth = c("user", "pass")) wi_th(req, basic_auth = c("user", "pass"), headers = list(foo = "bar")) # partial matching, query params ## including wi_th(req, query = including(list(foo = "bar"))) ## excluding wi_th(req, query = excluding(list(foo = "bar"))) # partial matching, body ## including wi_th(req, body = including(list(foo = "bar"))) ## excluding wi_th(req, body = excluding(list(foo = "bar"))) # basic auth ## including wi_th(req, body = including(list(foo = "bar"))) ## excluding wi_th(req, body = excluding(list(foo = "bar")))
# first, make a stub object req <- stub_request("post", "https://httpbin.org/post") # add body # list wi_th(req, body = list(foo = "bar")) # string wi_th(req, body = '{"foo": "bar"}') # raw wi_th(req, body = charToRaw('{"foo": "bar"}')) # numeric wi_th(req, body = 5) # an upload wi_th(req, body = crul::upload(system.file("CITATION"))) # wi_th(req, body = httr::upload_file(system.file("CITATION"))) # add query - has to be a named list wi_th(req, query = list(foo = "bar")) # add headers - has to be a named list wi_th(req, headers = list(foo = "bar")) wi_th(req, headers = list(`User-Agent` = "webmockr/v1", hello = "world")) # .list - pass in a named list instead wi_th(req, .list = list(body = list(foo = "bar"))) # basic authentication wi_th(req, basic_auth = c("user", "pass")) wi_th(req, basic_auth = c("user", "pass"), headers = list(foo = "bar")) # partial matching, query params ## including wi_th(req, query = including(list(foo = "bar"))) ## excluding wi_th(req, query = excluding(list(foo = "bar"))) # partial matching, body ## including wi_th(req, body = including(list(foo = "bar"))) ## excluding wi_th(req, body = excluding(list(foo = "bar"))) # basic auth ## including wi_th(req, body = including(list(foo = "bar"))) ## excluding wi_th(req, body = excluding(list(foo = "bar")))