R/pull_geo_data.R

Defines functions pull_geo_data

Documented in pull_geo_data

#' Pull Google Maps data with error handling
#'
#' This function, primarily, is a helper for \code{\link{drive_time}} and \code{\link{geocode_url}}.
#' It attempts to pull Google Maps data for a complete URL, recording http errors/connection failures
#' within the \code{status} and \code{error_message} paramaters.

#' To debug invalid signature requests, refer to the \href{https://developers.google.com/maps/documentation/business/webservices/auth}{Google Developer documention}.

#' @param urls_out character string; a complete URL with valid character encoding.
#' @param tmout number; the length of time, in seconds, to wait for a valid server
#' response before triggering a connection timeout error (defaults to 10 seconds).
#' @param messages logical; when \code{TRUE}, displays message from the API call(s). Generally,
#' this parameter is passed from \code{\link{drive_time}} or \code{\link{geocode_url}}.
#'
#' @importFrom RCurl getURL
#' @importFrom jsonlite fromJSON
#' @return A list with validly formatted JSON objects whose length equals \code{urls_out}
#' @examples
#' \dontrun{
#' # Fetch URLs contained within character vector "togoogle", waiting 20 seconds
#' # before triggering a server timeout error.
#' output <- pull_geo_data(togoogle, tmout=20)
#' }
#' @export

pull_geo_data <- function(urls_out, tmout=10, messages=TRUE){
	if(is.null(messages) | !is.logical(messages)) messages <- FALSE
	.urlset <- urls_out
	opts = RCurl::curlOptions(connecttimeout=tmout) # set max connection time out
	mapsin <- function(urls){
		errjson <- "{\n   \"error_message\" : \"URL was unreachable. Check your network connection.\",\n   \"results\" : [],\n    "
		out <- tryCatch(
			{
				if(messages) message("Reading:", urls)
				RCurl::getURL(urls, .opts = opts)
			},
			error=function(cond) {
				if(messages) message(paste("This URL is not reachable:", urls))
				if(messages) message("Error message:")
				if(messages) message(cond)
				return(paste0(errjson, "\"status\" : \"CONNECTION_ERROR\"", "}"))
			},
			warning=function(cond){
				if(messages) message(paste("This URL triggered a warning:", urls))
				if(messages) message("Warning message:")
				if(messages) message(cond)
				return(paste0("{", errjson, "\"status\" : \"CONNECTION_WARNING\"", "}"))
			},
			finally={
				if(messages) message(paste("Processed URL:", urls))
			}
		)
		return(out)
	}

	fromgoogle <- lapply(.urlset, mapsin)

	# Invalid signatures do not trigger an http error from the API; additionally,
	# these returns are not transmitted in JSON format The following
	# transformations convert signature errors into a JSON object with status
	# and error_message fields.

	# Shorten signature error message length
	fromgoogle <- lapply(fromgoogle, function (x) gsub("request. Provided 'signature'.*", "request.", x))

	# Convert to JSON
	fromgoogle <- ifelse(grepl("Unable to authenticate the request", fromgoogle, ignore.case=TRUE),
						 paste0("{\n   \"error_message\" : \"Unable to authenticate the request with the signature supplied. Check your client ID and private key.\",\n",
						 	   "\"results\" : [],\n   \"status\" : \"INVALID_SIGNATURE\"\n}\n"), fromgoogle)

	json <- lapply(fromgoogle, jsonlite::fromJSON)
	return(json)
}

Try the placement package in your browser

Any scripts or data that you put into this service are public.

placement documentation built on May 29, 2017, 11:54 p.m.