more robust error handling when API not available (#26)

development
Norwin 6 years ago
parent b69e5dc57f
commit 563b48eac2

@ -4,11 +4,32 @@
# for CSV responses (get_measurements) the readr package is a hidden dependency
# ==============================================================================
default_api = 'https://api.opensensemap.org'
#' Get the default openSenseMap API endpoint
#' @export
#' @return A character string with the HTTP URL of the openSenseMap API
osem_endpoint = function() {
'https://api.opensensemap.org'
osem_endpoint = function() default_api
#' Check if the given openSenseMap API endpoint is available
#' @param endpoint The API base URL to check, defaulting to \code{\link{osem_endpoint}}
#' @return \code{TRUE} if the API is available, otherwise \code{stop()} is called.
osem_ensure_api_available = function(endpoint = osem_endpoint()) {
code = FALSE
try({
code = httr::status_code(httr::GET(endpoint, path='stats'))
}, silent = TRUE)
if (code == 200)
return(TRUE)
errtext = paste('The API at', endpoint, 'is currently not available.')
if (code != FALSE)
errtext = paste0(errtext, ' (HTTP code ', code, ')')
if (endpoint == default_api)
errtext = c(errtext, 'If the issue persists, please check back at https://status.sensebox.de/778247404 and notify support@sensebox.de')
stop(paste(errtext, collapse='\n '), call. = FALSE)
FALSE
}
get_boxes_ = function (..., endpoint) {
@ -81,7 +102,7 @@ osem_get_resource = function (host, path, ..., type = 'parsed', progress = T, ca
}
res = osem_request_(host, path, query, type, progress)
if (!is.na(cache)) saveRDS(res, filename)
if (!is.na(res) && !is.na(cache)) saveRDS(res, filename)
res
}
@ -115,6 +136,9 @@ osem_clear_cache = function (location = tempdir()) {
}
osem_request_ = function (host, path, query = list(), type = 'parsed', progress = TRUE) {
# stop() if API is not available
osem_ensure_api_available(host)
progress = if (progress && !is_non_interactive()) httr::progress() else NULL
res = httr::GET(host, progress, path = path, query = query)

@ -0,0 +1,7 @@
context('API error handling')
test_that('unavailable API yields informative error message', {
expect_error({
osem_boxes(endpoint = 'example.zip')
}, 'The API at example.zip is currently not available')
})

@ -18,6 +18,7 @@ test_that('osem_box_to_archive_name does the correct character replacements', {
})
test_that('osem_box_to_archive_name works for one box', {
check_api()
if (is.null(box)) skip('no box data could be fetched')
archivename = opensensmapr:::osem_box_to_archivename(box)
@ -26,6 +27,7 @@ test_that('osem_box_to_archive_name works for one box', {
})
test_that('osem_box_to_archive_name works for multiple boxes', {
check_api()
if (is.null(boxes)) skip('no box data available')
archivename = opensensmapr:::osem_box_to_archivename(boxes)
@ -36,6 +38,7 @@ test_that('osem_box_to_archive_name works for multiple boxes', {
context('osem_measurements_archive()')
test_that('osem_measurements_archive works for one box', {
check_api()
if (is.null(box)) skip('no box data could be fetched')
m = osem_measurements_archive(box, as.POSIXlt('2018-08-08'))
@ -44,6 +47,7 @@ test_that('osem_measurements_archive works for one box', {
})
test_that('osem_measurements_archive fails for multiple boxes', {
check_api()
if (is.null(boxes)) skip('no box data available')
expect_error(

@ -19,6 +19,8 @@ test_that('a single box can be retrieved by ID', {
})
test_that('required box attributes are correctly parsed', {
check_api()
expect_is(box$X_id, 'character')
expect_is(box$name, 'character')
expect_is(box$exposure, 'character')
@ -29,6 +31,8 @@ test_that('required box attributes are correctly parsed', {
})
test_that('optional box attributes are correctly parsed', {
check_api()
completebox = osem_box('5a676e49411a790019290f94') # all fields populated
expect_is(completebox$description, 'character')
expect_is(completebox$grouptag, 'character')
@ -65,6 +69,8 @@ test_that('[.sensebox maintains attributes', {
})
test_that("print.sensebox filters important attributes for a single box", {
check_api()
msg = capture.output({
print(box)
})
@ -72,6 +78,8 @@ test_that("print.sensebox filters important attributes for a single box", {
})
test_that("summary.sensebox outputs all metrics for a single box", {
check_api()
msg = capture.output({
summary(box)
})

@ -123,6 +123,7 @@ test_that('[.osem_measurements maintains attributes', {
})
test_that('data.frame can be converted to measurements data.frame', {
check_api()
m = osem_measurements('Windrichtung')
df = osem_as_measurements(data.frame(c(1, 2), c('a', 'b')))
expect_equal(class(df), class(m))

@ -25,6 +25,8 @@ test_that('phenomena from boxes has all phenomena', {
})
test_that('phenomena from a not sensebox data.frame returns error', {
check_api()
expect_error(osem_phenomena(list()), 'no applicable method')
expect_error(osem_phenomena(data.frame()), 'no applicable method')
boxes_df = boxes

Loading…
Cancel
Save