別のサーバーからデータを取得する必要がある、作成した光沢のあるアプリがあります。つまり、光沢のあるアプリを開くと、他のサーバーが光沢のあるアプリにリクエストを送信して、アプリを開き、必要なデータをフィードします。
これをシミュレートするために、Firefoxでアプリを開いたときにRシャイニーアプリに以下を送信できます。
http://localhost:3838/benchmark-module/?transformerData=data/TransformerDataSampleForShiny.json
これは、「data /TransformerDataSampleForShing.json」という内容の「TransformerData」というスティングを光沢のあるアプリに送信する単純なgetリクエストです。
コードを使用すると、正常に機能します。
#(Abridged code, I am only showing the start of the code)
shinyServer(function(input, output) {
jsonFile <- "data/TransformerDataSampleForShiny.json"
JSONdata <- fromJSON(jsonFile)
しかし、文字列「data/TransformerDataSampleForShiny.json」をハードコーディングするのではなく、まったく同じことをしたい場合は、上記のhttpリクエストからその文字列を受け取りたいと思います。どうすればいいですか?私はコードを試しました:
shinyServer(function(input, output) {
jsonFile <- input$transformerData
JSONdata <- fromJSON(jsonFile)
そして私も試しました:
....
jsonFile <- input$TransformerData
しかし、これらはどれも機能していません。
したがって、主な質問は、HTTPリクエストを受信するようにコーディングするにはどうすればよいですか? HTTP GETリクエストから文字列を受信したいのですが、POSTリクエストからJSONファイルを受信したいのですが。
明確にするために、私はRから投稿を送信したり、リクエストを取得したりしたくありません。それらを受信したいと思います。 httrパッケージまたはhttpRequestパッケージを受信に使用できません
本当にありがとう!
session$clientData
を使用してGETリクエストを受信できます。次の例を実行します
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)
に移動します
http://127.0.0.1:5678/?transformerData=data/TransformerDataSampleForShiny.json
POSTリクエストを公開する方法については、@ XinYinの回答を参照してください。
@jdharrisonの答えは、ShinyでGET
リクエストを処理する方法の1つです。残念ながら、彼または彼女の声明は
残念ながら、shinyはPOSTリクエストを処理しません。
厳密に言えば、100%正確ではありません。
関数session$registerDataObj
を使用して、ShinyでPOST
リクエストを処理できます。この関数の使用例 この例にあります 。基本的に、registerDataObj
関数を呼び出すと、uniqueリクエストURLが返され、そこからGET
またはPOST
リクエストを開始できます。ただし、上記の例は、次の理由から、質問のコンテキストではあまり役に立たないと思います。
registerDataObj
を利用してPNGファイルハンドラーを作成し、URLを<img>
タグのsrc
プロパティに直接バインドします。 。GET
ではなくPOST
リクエストをまだ使用しています。ただし、この便利な関数を多重化して、GET
とPOST
の両方を完全にうまく処理することができます。次の例を考えてみましょう。
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))
})
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>
')
)
)
))
ここで、次のテスト入力を入力するとします。
次に、"Upload"
を押して、POSTリクエストをShinyサーバーに送信します。これにより、Rコードに基づいて、ブラウザのPOSTリクエストがダンプされます。応答としてあなたにストリーミングします。
たとえば、次のようになります。
------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--
POSTリクエストプロセッサを適切に記述していれば、テキストデータだけでなく、ファイルのアップロードも処理できることは明らかです。これは簡単ではないかもしれませんが、少なくとももっともらしく、完全に実行可能です。
もちろん、このuniqueリクエストURLをクライアントまたはリクエストを開始するサーバーに通信する必要があるという明らかな欠点があります。しかし、技術的にはそれを行う方法はたくさんあります!
エキサイティングなアップデート:2017年1月の時点で、 RStudio Confで発表されました これは将来のバージョンで光沢のあるものに組み込まれる予定です(15:00分に視聴を開始してください)。
2017年5月の時点で、このAPI機能はまだリリースされていませんが、すぐに提供されることを期待しています。