@@ -111,19 +111,23 @@ print.epidata_call <- function(epidata_call) {
111
111
# ' time_value and value fields or c("-direction") to return everything except
112
112
# ' the direction field
113
113
# ' @param disable_date_parsing disable automatic date parsing
114
+ # ' @param return_empty boolean that allows returning an empty tibble if there is no data
115
+ # ' @param timeout_seconds the maximum amount of time to wait for a response
114
116
# ' @return
115
117
# ' - For `fetch`: a tibble or a JSON-like list
116
118
# ' @export
117
119
# '
118
- fetch <- function (epidata_call , fields = NULL , disable_date_parsing = FALSE ) {
120
+ fetch <- function (epidata_call , fields = NULL , disable_date_parsing = FALSE , return_empty = FALSE , timeout_seconds = 30 ) {
119
121
stopifnot(inherits(epidata_call , " epidata_call" ))
120
122
stopifnot(is.null(fields ) || is.character(fields ))
121
123
stopifnot(is.logical(disable_date_parsing ), length(disable_date_parsing ) == 1 )
124
+ stopifnot(is.logical(return_empty ))
125
+ stopifnot(is.numeric(timeout_seconds ))
122
126
123
127
if (epidata_call $ only_supports_classic ) {
124
- return (fetch_classic(epidata_call , fields ))
128
+ return (fetch_classic(epidata_call , fields , return_empty = return_empty , timeout_seconds = timeout_seconds ))
125
129
} else {
126
- return (fetch_tbl(epidata_call , fields , disable_date_parsing ))
130
+ return (fetch_tbl(epidata_call , fields , disable_date_parsing , return_empty , timeout_seconds = timeout_seconds ))
127
131
}
128
132
}
129
133
@@ -136,17 +140,21 @@ fetch <- function(epidata_call, fields = NULL, disable_date_parsing = FALSE) {
136
140
# ' time_value and value fields or c("-direction") to return everything except
137
141
# ' the direction field
138
142
# ' @param disable_date_parsing disable automatic date parsing
143
+ # ' @param return_empty boolean that allows returning an empty tibble if there is no data.
144
+ # ' @param timeout_seconds the maximum amount of time to wait for a response
139
145
# ' @importFrom readr read_csv
140
146
# ' @importFrom httr stop_for_status content
141
147
# ' @importFrom rlang abort
142
148
# ' @return
143
149
# ' - For `fetch_tbl`: a [`tibble::tibble`]
144
150
# ' @importFrom tibble as_tibble
145
151
# ' @keywords internal
146
- fetch_tbl <- function (epidata_call , fields = NULL , disable_date_parsing = FALSE ) {
152
+ fetch_tbl <- function (epidata_call , fields = NULL , disable_date_parsing = FALSE , return_empty = FALSE , timeout_seconds = 30 ) {
147
153
stopifnot(inherits(epidata_call , " epidata_call" ))
148
154
stopifnot(is.null(fields ) || is.character(fields ))
149
155
stopifnot(is.logical(disable_date_parsing ), length(disable_date_parsing ) == 1 )
156
+ stopifnot(is.logical(return_empty ))
157
+ stopifnot(is.numeric(timeout_seconds ))
150
158
151
159
if (epidata_call $ only_supports_classic ) {
152
160
rlang :: abort(" This endpoint only supports the classic message format, due to a non-standard behavior. Use fetch_classic instead." ,
@@ -155,7 +163,10 @@ fetch_tbl <- function(epidata_call, fields = NULL, disable_date_parsing = FALSE)
155
163
)
156
164
}
157
165
158
- response_content <- fetch_classic(epidata_call , fields , disable_data_frame_parsing = FALSE )
166
+ response_content <- fetch_classic(epidata_call , fields , disable_data_frame_parsing = FALSE , return_empty = return_empty , timeout_seconds = timeout_seconds )
167
+ if (return_empty && length(response_content ) == 0 ) {
168
+ return (tibble())
169
+ }
159
170
return (parse_data_frame(epidata_call , response_content , disable_date_parsing ) %> % as_tibble())
160
171
}
161
172
@@ -172,32 +183,38 @@ fetch_tbl <- function(epidata_call, fields = NULL, disable_date_parsing = FALSE)
172
183
# ' @param disable_data_frame_parsing do not automatically cast the epidata
173
184
# ' output to a data frame (some endpoints return a list of lists, which is not
174
185
# ' a data frame)
186
+ # ' @param return_empty boolean that allows returning an empty tibble if there is no data.
187
+ # ' @param timeout_seconds the maximum amount of time to wait for a response
175
188
# ' @importFrom httr stop_for_status content http_error
176
189
# ' @importFrom jsonlite fromJSON
177
190
# ' @return
178
191
# ' - For `fetch_classic`: a JSON-like list
179
192
# ' @keywords internal
180
- fetch_classic <- function (epidata_call , fields = NULL , disable_data_frame_parsing = TRUE ) {
193
+ fetch_classic <- function (epidata_call , fields = NULL , disable_data_frame_parsing = TRUE , return_empty = FALSE , timeout_seconds = 30 ) {
181
194
stopifnot(inherits(epidata_call , " epidata_call" ))
182
195
stopifnot(is.null(fields ) || is.character(fields ))
196
+ stopifnot(is.logical(return_empty ))
197
+ stopifnot(is.numeric(timeout_seconds ))
183
198
184
- response <- request_impl(epidata_call , " classic" , fields )
199
+ response <- request_impl(epidata_call , " classic" , fields , timeout_seconds )
185
200
response_content <- httr :: content(response , as = " text" , encoding = " UTF-8" )
186
201
187
202
response_content <- jsonlite :: fromJSON(response_content , simplifyDataFrame = ! disable_data_frame_parsing )
188
203
189
204
# success is 1, no results is -2, truncated is 2, -1 is generic error
190
205
if (response_content $ result != 1 ) {
191
- rlang :: abort(paste0(" epidata error: " , response_content $ message ), " epidata_error" )
206
+ if ((response_content $ result != - 2 ) && ! (return_empty )) {
207
+ rlang :: abort(paste0(" epidata error: " , response_content $ message ), " epidata_error" )
208
+ }
192
209
}
193
210
if (response_content $ message != " success" ) {
194
211
rlang :: warn(paste0(" epidata warning: " , response_content $ message ), " epidata_warning" )
195
212
}
196
213
return (response_content $ epidata )
197
214
}
198
215
199
- fetch_debug <- function (epidata_call , format_type = " classic" , fields = NULL ) {
200
- response <- request_impl(epidata_call , format_type , fields )
216
+ fetch_debug <- function (epidata_call , format_type = " classic" , fields = NULL , timeout_seconds = 30 ) {
217
+ response <- request_impl(epidata_call , format_type , fields , timeout_seconds )
201
218
content <- httr :: content(response , " text" , encoding = " UTF-8" )
202
219
content
203
220
}
@@ -247,13 +264,13 @@ with_base_url <- function(epidata_call, base_url) {
247
264
# ' HTTP errors and forwarding the HTTP body in R errors
248
265
# ' @importFrom httr stop_for_status content http_type
249
266
# ' @importFrom xml2 read_html xml_find_all xml_text
250
- request_impl <- function (epidata_call , format_type , fields = NULL ) {
267
+ request_impl <- function (epidata_call , format_type , fields = NULL , timeout_seconds = 30 ) {
251
268
stopifnot(inherits(epidata_call , " epidata_call" ))
252
269
stopifnot(format_type %in% c(" json" , " csv" , " classic" ))
253
270
254
271
url <- full_url(epidata_call )
255
272
params <- request_arguments(epidata_call , format_type , fields )
256
- response <- do_request(url , params )
273
+ response <- do_request(url , params , timeout_seconds )
257
274
258
275
if (response $ status_code != 200 ) {
259
276
# 500, 429, 401 are possible
0 commit comments