Skip to content

Commit

Permalink
Add comments on retrying/forcing a new session
Browse files Browse the repository at this point in the history
The logic is correct but confused me until I walked through it
carefully. The comments should keep future me from being confused.

Rename 'force.new' to 'is.retry' to make it clearer that the
call is a 'retry' call. Clean up existing comments.

See #382. See #383.
  • Loading branch information
joshuaulrich committed Jun 14, 2023
1 parent 8be0ffa commit 0c01ac5
Showing 1 changed file with 20 additions and 12 deletions.
32 changes: 20 additions & 12 deletions R/getQuote.R
Original file line number Diff line number Diff line change
Expand Up @@ -24,34 +24,42 @@ function(Symbols,src='yahoo',what, ...) {
df[Symbols,]
}

.yahooSession <- function(force.new = FALSE) {
.yahooSession <- function(is.retry = FALSE) {
cache.name <- "_yahoo_curl_session_"
ses <- get0(cache.name, .quantmodEnv) #get cached session
ses <- get0(cache.name, .quantmodEnv) # get cached session

if (is.null(ses) || force.new) {
if (is.null(ses) || is.retry) {
ses <- list()
ses$h <- curl::new_handle()
#yahoo finance doesn't seem to set cookies without these headers
#and the cookies are needed to get the crumb
# yahoo finance doesn't seem to set cookies without these headers
# and the cookies are needed to get the crumb
curl::handle_setheaders(ses$h, accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7")
URL <- "https://finance.yahoo.com/"
r <- curl::curl_fetch_memory(URL, handle = ses$h)
#yahoo redirects to a consent form w/ a single cookie for GDPR:
#detecting the redirect seems very brittle as its sensitive to the trailing "/"
# yahoo redirects to a consent form w/ a single cookie for GDPR:
# detecting the redirect seems very brittle as its sensitive to the trailing "/"
ses$can.crumb <- ((r$status_code == 200) && (URL == r$url) && (NROW(curl::handle_cookies(ses$h)) > 1))
assign(cache.name, ses, .quantmodEnv) #cache session
assign(cache.name, ses, .quantmodEnv) # cache session
}

if (ses$can.crumb) {
#get a crumb so that downstream callers dont have to handle invalid sessions.
#this is a network hop, but very lightweight payload
# get a crumb so that downstream callers don't have to handle invalid sessions.
# this is a network hop, but very lightweight payload
n <- if (unclass(Sys.time()) %% 1L >= 0.5) 1L else 2L
query.srv <- paste0("https://query", n, ".finance.yahoo.com/v1/test/getcrumb")
r <- curl::curl_fetch_memory(query.srv, handle = ses$h)
if ((r$status_code == 200) && (length(r$content) > 0)) {
ses$crumb = rawToChar(r$content)
ses$crumb <- rawToChar(r$content)
} else {
if (!force.new) ses <- .yahooSession(TRUE) else stop("Unable to get yahoo crumb")
# we were unable to get a crumb
if (is.retry) {
# we couldn't get a crumb with a new session
stop("unable to get yahoo crumb")
} else {
# we tried to re-use a session but couldn't get a crumb
# try to get a crumb using a new session
ses <- .yahooSession(TRUE)
}
}
}

Expand Down

0 comments on commit 0c01ac5

Please sign in to comment.