0

I'm looking to write some simple ETL scripts to query an API in R. They only authenticate successfully after I have run update.packages('openssl') and I'm not exactly sure what this means, beyond something being misconfigured.

Edit with runnable sample:

The following test GET request...

library(httr)
library(openssl)
library(tidyverse)
library(DBI)

#### SET QUERY/FORM VARIABLES ####
#### SET URL ENDPOINTS ####
api_base <- 'https://reqres.in'
sub_endpt <- '/api/unknown/2'
sub_url <- paste0(api_base, sub_endpt)

page_req <- GET(sub_url
                , encode = 'json'
                , verbose(info=TRUE)

...generates the following error:

*    Trying 172.67.222.36...
*  TCP_NODELAY set
*  Connected to reqres.in (172.67.222.36) port 443 (#0)
*  schannel: SSL/TLS connection with reqres.in port 443 (step 1/3)
*  schannel: disabled server certificate revocation checks
*  schannel: sending initial handshake data: sending 157 bytes...
*  schannel: sent initial handshake data: sent 157 bytes
*  schannel: SSL/TLS connection with reqres.in port 443 (step 2/3)
*  schannel: failed to receive handshake, need more data
*  schannel: SSL/TLS connection with reqres.in port 443 (step 2/3)
*  schannel: encrypted data got 139
*  schannel: encrypted data buffer: offset 139 length 4096
*  schannel: next InitializeSecurityContext failed: SEC_E_INVALID_TOKEN (0x80090308) - The token supplied to the function is invalid
*  Closing connection 0
*  schannel: shutting down SSL/TLS connection with reqres.in port 443
*  schannel: clear security context handle
Error in curl::curl_fetch_memory(url, handle = handle) : 
  schannel: next InitializeSecurityContext failed: SEC_E_INVALID_TOKEN (0x80090308) - The token supplied to the function is invalid

This same script works after running update.packages('openssl'), but only if update.packages('openssl') is run each time.

library(httr)
library(openssl)
library(tidyverse)
library(DBI)
update.packages('openssl')

#### SET QUERY/FORM VARIABLES ####
#### SET URL ENDPOINTS ####
api_base <- 'https://reqres.in'
sub_endpt <- '/api/unknown/2'
sub_url <- paste0(api_base, sub_endpt)

page_req <- GET(sub_url
                , encode = 'json'
                , verbose(info=TRUE)
)

After running the above, I instead receive:

Hostname in DNS cache was stale, zapped
 *    Trying 104.21.59.93...
 *  TCP_NODELAY set
 *  Connected to reqres.in (104.21.59.93) port 443 (#1)
 *  schannel: SSL/TLS connection with reqres.in port 443 (step 1/3)
 *  schannel: disabled server certificate revocation checks
 *  schannel: sending initial handshake data: sending 157 bytes...
 *  schannel: sent initial handshake data: sent 157 bytes
 *  schannel: SSL/TLS connection with reqres.in port 443 (step 2/3)
 *  schannel: failed to receive handshake, need more data
 *  schannel: SSL/TLS connection with reqres.in port 443 (step 2/3)
 *  schannel: encrypted data got 2563
 *  schannel: encrypted data buffer: offset 2563 length 4096
 *  schannel: sending next handshake data: sending 126 bytes...
 *  schannel: SSL/TLS connection with reqres.in port 443 (step 2/3)
 *  schannel: encrypted data got 258
 *  schannel: encrypted data buffer: offset 258 length 4096
 *  schannel: SSL/TLS handshake complete
 *  schannel: SSL/TLS connection with reqres.in port 443 (step 3/3)
 *  schannel: stored credential handle in session cache
-> GET /api/unknown/2 HTTP/1.1
-> Host: reqres.in
-> User-Agent: libcurl/7.59.0 r-curl/3.3 httr/1.4.1
-> Accept-Encoding: gzip, deflate
-> Accept: application/json, text/xml, application/xml, */*
-> 
 *  schannel: client wants to read 16384 bytes
 *  schannel: encdata_buffer resized 17408
 *  schannel: encrypted data buffer: offset 0 length 17408
 *  schannel: encrypted data got 1168
 *  schannel: encrypted data buffer: offset 1168 length 17408
 *  schannel: decrypted data length: 1105
 *  schannel: decrypted data added: 1105
 *  schannel: decrypted data cached: offset 1105 length 16384
 *  schannel: encrypted data length: 34
 *  schannel: encrypted data cached: offset 34 length 17408
 *  schannel: decrypted data length: 5
 *  schannel: decrypted data added: 5
 *  schannel: decrypted data cached: offset 1110 length 16384
 *  schannel: encrypted data buffer: offset 0 length 17408
 *  schannel: decrypted data buffer: offset 1110 length 16384
 *  schannel: schannel_recv cleanup
 *  schannel: decrypted data returned 1110
 *  schannel: decrypted data buffer: offset 0 length 16384
<- HTTP/1.1 200 OK
<- Date: Sat, 29 Jan 2022 16:11:59 GMT
<- Content-Type: application/json; charset=utf-8
<- Transfer-Encoding: chunked
<- Connection: keep-alive
<- x-powered-by: Express
<- access-control-allow-origin: *
<- etag: W/"e8-ov4wWh4/OY1IMQMqWgskYtOFnVs"
<- via: 1.1 vegur
<- Cache-Control: max-age=14400
<- CF-Cache-Status: REVALIDATED
<- Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
<- Report-To: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=fyNvgiYFkSfx2bLgj4G0uybx5hN7f9uUIiFjrgijkYbZD7FkoBWhZfFl%2BniMEaaf%2B8Ur5nMmH1Pe3mCgnwudLptXgIaYDRi8WZvItt%2Fz69En%2B%2BwTEhWhRuBbMDk%3D"}],"group":"cf-nel","max_age":604800}
<- NEL: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
<- Vary: Accept-Encoding
<- Server: cloudflare
<- CF-RAY: 6d53bd4fe9628c90-EWR
<- Content-Encoding: gzip
<- alt-svc: h3=":443"; ma=86400, h3-29=":443"; ma=86400
<- 
 *  Connection #1 to host reqres.in left intact

I've confirmed this fails with the same error if I restart my R session and run the script without update.packages('openssl').

I've also confirmed that this also succeeds when I run update.packages('openssl') before any of my library imports.

Original Post

I'm using the following libraries:

library(httr)
library(curl)
library(openssl)
library(tidyverse)
library(DBI)

After these imports, my sessionInfo() is:

R version 4.0.2 (2020-06-22)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 17763)

Matrix products: default

locale:
[1] LC_COLLATE=English_United States.1252  LC_CTYPE=English_United States.1252    LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C                           LC_TIME=English_United States.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] DBI_1.1.0            forcats_0.5.0        stringr_1.4.0        dplyr_1.0.0          purrr_0.3.4          readr_1.3.1         
 [7] tidyr_1.1.0          tibble_3.0.2         ggplot2_3.3.2        tidyverse_1.3.0      openssl_1.4.2        curl_3.3            
[13] httr_1.4.1           RevoUtils_11.0.2     RevoUtilsMath_11.0.0

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.5       cellranger_1.1.0 pillar_1.4.6     compiler_4.0.2   dbplyr_1.4.4     tools_4.0.2      lubridate_1.7.9 
 [8] jsonlite_1.7.0   lifecycle_0.2.0  gtable_0.3.0     pkgconfig_2.0.3  rlang_0.4.6      reprex_0.3.0     cli_2.0.2       
[15] rstudioapi_0.11  haven_2.3.1      withr_2.2.0      xml2_1.3.2       fs_1.4.2         hms_0.5.3        generics_0.0.2  
[22] vctrs_0.3.1      askpass_1.1      grid_4.0.2       tidyselect_1.1.0 glue_1.4.1       R6_2.3.0         fansi_0.4.1     
[29] readxl_1.3.1     modelr_0.1.8     blob_1.2.1       magrittr_1.5     backports_1.1.7  scales_1.1.1     ellipsis_0.3.1  
[36] rvest_0.3.5      assertthat_0.2.1 colorspace_1.4-1 stringi_1.4.6    munsell_0.5.0    broom_0.7.0      crayon_1.3.4

When I import those libraries and then run my script, I get the following:

schannel: SSL/TLS connection with www.formstack.com port 443 (step 1/3)
*  schannel: disabled server certificate revocation checks
*  schannel: sending initial handshake data: sending 165 bytes...
*  schannel: sent initial handshake data: sent 165 bytes
*  schannel: SSL/TLS connection with www.formstack.com port 443 (step 2/3)
*  schannel: failed to receive handshake, need more data
*  schannel: SSL/TLS connection with www.formstack.com port 443 (step 2/3)
*  schannel: encrypted data got 139
*  schannel: encrypted data buffer: offset 139 length 4096
*  schannel: next InitializeSecurityContext failed: SEC_E_INVALID_TOKEN (0x80090308) - The token supplied to the function is invalid
*  Closing connection 0
*  schannel: shutting down SSL/TLS connection with www.formstack.com port 443
*  schannel: clear security context handle
Error in curl::curl_fetch_memory(url, handle = handle) : 
  schannel: next InitializeSecurityContext failed: SEC_E_INVALID_TOKEN (0x80090308) - The token supplied to the function is invalid

My script succeeds when I instead run:

library(httr)
library(curl)
library(openssl)
library(tidyverse)
library(DBI)
update.packages('openssl')

I suspected that this might have something to do with a conflict between curl and httr, because of this upon import:

> library(curl)

Attaching package: ‘curl’

The following object is masked from ‘package:httr’:

    handle_reset

But the script also succeeds when I run the update first and swap the order of httr and curl imports, such as:

update.packages('openssl')
library(curl)
library(httr)
library(openssl)
library(tidyverse)
library(DBI)

I hope that's enough to help troubleshoot what's wrong in my environment here and appreciate any and all lessons about library maintenance / dependencies.

darren
  • 1
  • 1
  • Does your code really require both `httr` and `curl`? Those two packages seem to accomplish the same goal so it's odd they are both required. Without a minimal [reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) that we can run ourselves, it's difficult to say exactly what's going on. It should not be necessary to constantly re-run `update.packages()` – MrFlick Jan 28 '22 at 18:34
  • Thank you, @MrFlick! I've edited my post with a reproducible example. – darren Jan 29 '22 at 16:20

0 Answers0