studio - Aceptar solicitud HTTP en R aplicación brillante
tags$style shiny (3)
Tengo una aplicación brillante que he hecho que necesita obtener sus datos de otro servidor, es decir, el otro servidor cuando se abre la brillante aplicación envía una solicitud a la brillante aplicación para abrir la aplicación y darle los datos que necesita.
Para simular esto, puedo enviar lo siguiente a la aplicación brillante R cuando abro la aplicación en firefox:
http://localhost:3838/benchmark-module/?transformerData=data/TransformerDataSampleForShiny.json
Esta es una solicitud de obtención simple que envía la picadura llamada: "Datos del transformador" con el contenido "data / TransformerDataSampleForShing.json" a la aplicación brillante.
Cuando uso el código, funciona bien:
#(Abridged code, I am only showing the start of the code)
shinyServer(function(input, output) {
jsonFile <- "data/TransformerDataSampleForShiny.json"
JSONdata <- fromJSON(jsonFile)
pero cuando quiero hacer exactamente lo mismo, salvo que sea difícil codificar la cadena "data / TransformerDataSampleForShiny.json", quiero recibir esa cadena de la solicitud http anterior. ¿¿Cómo hago esto?? He intentado el código:
shinyServer(function(input, output) {
jsonFile <- input$transformerData
JSONdata <- fromJSON(jsonFile)
y también he intentado:
....
jsonFile <- input$TransformerData
pero ninguno de estos ha funcionado.
ASÍ QUE la pregunta principal es, ¿cómo codigo para recibir solicitudes HTTP? Me gustaría recibir cadenas de solicitudes HTTP GET y / o archivos JSON de solicitudes POST.
Solo para aclarar que NO deseo enviar publicaciones u obtener solicitudes de R. Quiero recibirlas. No puedo usar el paquete httr o el paquete httpRequest para recibir
¡Muchas gracias!
La respuesta de @ jdharrison es una forma de cómo puedes manejar las solicitudes GET
en Shiny. Lamentablemente, su declaración de que
brillante no maneja las solicitudes POST desafortunadamente.
no es, estrictamente hablando, 100% exacto.
Puede manejar solicitudes POST
en Shiny con la ayuda de la session$registerDataObj
función session$registerDataObj
. Un ejemplo del uso de esta función se puede encontrar en este ejemplo . Básicamente, al llamar a la función registerDataObj
, devuelve una URL de solicitud única a la que puede iniciar solicitudes GET
o POST
. Sin embargo, no consideraría el ejemplo anterior muy útil en el contexto de su pregunta porque:
- No hay un uso explícito de AJAX en este ejemplo. Más bien, el ejemplo explota
registerDataObj
para crear un manejador de archivos PNG y vincula directamente el URL a la propiedadsrc
de la etiqueta<img>
. - Todavía está utilizando la solicitud
GET
noPOST
.
Pero, puede multiplexar esta práctica función para manejar tanto GET
como POST
perfectamente bien. Considere el siguiente ejemplo:
servidor.R
library(shiny)
shinyServer(function(input, output, session) {
api_url <- session$registerDataObj(
name = ''api'', # an arbitrary but unique name for the data object
data = list(), # you can bind some data here, which is the data argument for the
# filter function below.
filter = function(data, req) {
print(ls(req)) # you can inspect what variables are encapsulated in this req
# environment
if (req$REQUEST_METHOD == "GET") {
# handle GET requests
query <- parseQueryString(req$QUERY_STRING)
# say:
# name <- query$name
# etc...
}
if (req$REQUEST_METHOD == "POST") {
# handle POST requests here
reqInput <- req$rook.input
# read a chuck of size 2^16 bytes, should suffice for our test
buf <- reqInput$read(2^16)
# simply dump the HTTP request (input) stream back to client
shiny:::httpResponse(
200, ''text/plain'', buf
)
}
}
)
# because the API entry is UNIQUE, we need to send it to the client
# we can create a custom pipeline to convey this message
session$sendCustomMessage("api_url", list(url=api_url))
})
ui.R
library(shiny)
shinyUI(fluidPage(
singleton(tags$head(HTML(
''
<script type="text/javascript">
$(document).ready(function() {
// creates a handler for our special message type
Shiny.addCustomMessageHandler("api_url", function(message) {
// set up the the submit URL of the form
$("#form1").attr("action", "/" + message.url);
$("#submitbtn").click(function() { $("#form1").submit(); });
});
})
</script>
''
))),
tabsetPanel(
tabPanel(''POST request example'',
# create a raw HTML form
HTML(''
<form enctype="multipart/form-data" method="post" action="" id="form1">
<span>Name:</span>
<input type="text" name="name" /> <br />
<span>Passcode: </span> <br />
<input type="password" name="passcode" /><br />
<span>Avatar:</span>
<input name="file" type="file" /> <br />
<input type="button" value="Upload" id="submitbtn" />
</form>
'')
)
)
))
Ahora, digamos que ingreso esta entrada de prueba:
Luego presiona "Upload"
, envías una solicitud POST al servidor Shiny, que, en función de nuestro código R, arrojará la transmisión de solicitud POST de tu navegador como respuesta.
Por ejemplo, obtengo:
------WebKitFormBoundary5Z0hAYXQXBHPTLHs
Content-Disposition: form-data; name="name"
foo
------WebKitFormBoundary5Z0hAYXQXBHPTLHs
Content-Disposition: form-data; name="passcode"
bar
------WebKitFormBoundary5Z0hAYXQXBHPTLHs
Content-Disposition: form-data; name="file"; filename="conductor.png"
Content-Type: image/png
‰PNG
IHDR X ¦ 5Š_ pHYs a a¨?§i ÕiTXtXML:com.adobe.xmp <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.1.2">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:tiff="http://ns.adobe.com/tiff/1.0/">
<tiff:Compression>5</tiff:Compression>
<tiff:PhotometricInterpretation>2</tiff:PhotometricInterpretation>
<tiff:Orientation>1</tiff:Orientation>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
# here I removed the binary file content
------WebKitFormBoundary5Z0hAYXQXBHPTLHs--
Es evidente que puede manejar no solo los datos de texto, sino también las cargas de archivos siempre que escriba un procesador de solicitud POST de forma adecuada. Aunque esto puede no ser trivial, ¡pero al menos es plausible y totalmente factible!
Por supuesto, tiene el inconveniente obvio de que de alguna manera necesita comunicar esta URL de solicitud única al cliente o al servidor que iniciará la solicitud. ¡Pero técnicamente hay muchas maneras en que puedes hacer eso!
Puede recibir solicitudes GET usando la session$clientData
. Un ejemplo ejecuta el siguiente
library(shiny)
runApp(list(
ui = bootstrapPage(
textOutput(''text'')
),
server = function(input, output, session) {
output$text <- renderText({
query <- parseQueryString(session$clientData$url_search)
paste(names(query), query, sep = "=", collapse=", ")
})
}
), port = 5678, launch.browser = FALSE)
y navega a
http://127.0.0.1:5678/?transformerData=data/TransformerDataSampleForShiny.json
Consulte @Xin Yin answer para conocer un método para exponer las solicitudes POST.
Emocionante actualización: A partir de enero de 2017, se anunció en RStudio Conf que esto se incorporará en brillante en una versión futura (comience a ver en el minuto 15:00).
A partir de mayo de 2017, esta función API aún no se ha publicado, pero espero que llegue pronto.