mirror of
https://github.com/sensebox/opensensmapr
synced 2025-02-22 14:53:57 +01:00
fail gracefully when api is not available (#27)
more robust error handling when API not available (#26)
This commit is contained in:
parent
b69e5dc57f
commit
f69cf62b27
6 changed files with 48 additions and 2 deletions
28
R/api.R
28
R/api.R
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
||||
|
|
7
tests/testthat/test_api.R
Normal file
7
tests/testthat/test_api.R
Normal file
|
@ -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…
Add table
Reference in a new issue