我需要你的帮助!
我在
shinyapps.io上托管了一个
R
Shiny
应用程序,最近我在该应用程序上从互联网下载 10 MB 文件时遇到问题。当我在本地运行应用程序时,一切仍然运行完美。
自从问题出现以来,我在shinyapps.io日志中发现了以下内容:
Warning: Error in open.connection: HTTP/2 stream 0 was not closed cleanly: INTERNAL_ERROR (err 2)
一种解决方案是强制使用 HTTP/1.1,如此处和此处所示。我已经尝试过,但我偶然发现了另一个问题。文件仍未下载,日志显示以下内容:
old SSL session ID is stale, removing
我已经准备了一个完整的示例在shinyapps.io和下面供您重现:
library(shiny)
library(curl)
library(readr)
ui <- fluidPage(
titlePanel("Debug HTTP from shinyapps.io to edf.fr"),
sidebarLayout(
sidebarPanel(
radioButtons(
"radio", "Select option",
choices = list("HTTP/2" = 1, "HTTP/1.1" = 2), selected = 1
)
),
mainPanel(textOutput("text"))
)
)
server <- function(input, output) {
url <- "https://www.edf.fr/doaat/export/light/csv"
h <- new_handle(failonerror = TRUE, verbose = TRUE)
output$text <- renderText({
if (input$radio == 2) {
handle_setopt(h, http_version = 2)
}
req <- curl_fetch_memory(url, handle = h)
file <- rawToChar(req$content)
read_lines(file, n_max=1, locale=locale(encoding='latin1')) })
}
shinyApp(ui = ui, server = server)
上面的示例在本地运行时完美运行(即成功 = 下载的 10 MB CSV 文件的第一行出现在主面板上),但在闪亮应用程序.io 上运行时在 HTTP/2 和 HTTP/1.1 中均失败。
这似乎与shinyapps.io 上的curl 版本和/或与服务器(shinyapps.io 或edf.fr)的错误HTTP 事务有关。因此,我在下面为 HTTP 专家分享了更多详细的卷曲日志。
Listening on http://127.0.0.1:37633
* Trying 104.68.246.156:443...
* Connected to www.edf.fr (104.68.246.156) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: C=FR; ST=�le-de-France; L=Paris; O=ELECTRICITE DE FRANCE SA; CN=edf.fr
* start date: Mar 22 00:00:00 2024 GMT
* expire date: Mar 21 23:59:59 2025 GMT
* subjectAltName: host "www.edf.fr" matched cert's "www.edf.fr"
* issuer: C=IE; O=DigiCert Ireland Limited; CN=DigiCert G2 TLS EU RSA4096 SHA384 2022 CA1
* SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* Using Stream ID: 1 (easy handle 0x5c8f626765d0)
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> GET /doaat/export/light/csv HTTP/2
Host: www.edf.fr
user-agent: R/4.4.1 (ubuntu-22.04) R (4.4.1 x86_64-pc-linux-gnu x86_64 linux-gnu)
accept: */*
accept-encoding: deflate, gzip, br, zstd
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* HTTP/2 stream 0 was not closed cleanly: INTERNAL_ERROR (err 2)
* stopped the pause stream!
* Connection #0 to host www.edf.fr left intact
Warning: Error in curl_fetch_memory: HTTP/2 stream 0 was not closed cleanly: INTERNAL_ERROR (err 2)
Listening on http://127.0.0.1:36691
* Trying 104.68.246.156:443...
* Connected to www.edf.fr (104.68.246.156) port 443 (#0)
* ALPN, offering http/1.1
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: C=FR; ST=�le-de-France; L=Paris; O=ELECTRICITE DE FRANCE SA; CN=edf.fr
* start date: Mar 22 00:00:00 2024 GMT
* expire date: Mar 21 23:59:59 2025 GMT
* subjectAltName: host "www.edf.fr" matched cert's "www.edf.fr"
* issuer: C=IE; O=DigiCert Ireland Limited; CN=DigiCert G2 TLS EU RSA4096 SHA384 2022 CA1
* SSL certificate verify ok.
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> GET /doaat/export/light/csv HTTP/1.1
Host: www.edf.fr
User-Agent: R/4.4.1 (ubuntu-22.04) R (4.4.1 x86_64-pc-linux-gnu x86_64 linux-gnu)
Accept: */*
Accept-Encoding: deflate, gzip, br, zstd
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
作为解决方法,也许可以使用
httr2
发出该请求,即使关闭该连接存在一些问题,req_perform(..., path = dest)
也应该存储内容。
在以下示例中
resp$body
指向存储内容的 tmp 文件。
library(shiny)
library(httr2)
library(readr)
ui <- fluidPage(
titlePanel("Debug HTTP from shinyapps.io to edf.fr"),
mainPanel(
verbatimTextOutput("resp"),
verbatimTextOutput("text"))
)
server <- function(input, output) {
url <- "https://www.edf.fr/doaat/export/light/csv"
tmp_csv <- tempfile()
resp <-
request(url) |>
req_perform(path = tmp_csv)
output$resp <- renderPrint(str(resp))
output$text <- renderPrint(read_lines(resp$body, n_max=1, locale=locale(encoding='latin1')))
}
shinyApp(ui = ui, server = server, options = list(display.mode = "showcase"))