This is a 'shiny server', for serving Shiny applications over the web.
MOJ has developed this this one because the other shiny servers did not meet our needs.
Shiny apps use websockets, which is a newish addition beyond HTTP, so it is not supported by some older browsers (e.g. IE9) and older firewalls, which many corporates still have. A Shiny app will simply appear 'greyed out' if websockets are not available.
However SockJS is a bit of javascript that redirects websocket requests via normal HTTP, so this server adds this into every page, which kicks in as a fallback option. This is achieved by adding an HTTP filter that inserts the <script src="https://github.com/ministryofjustice/analytics-platform-shiny-server/raw/main/sock.js">
into HTTP responses from the app. You can also reduce the ALLOWED_PROTOCOLS the app will try to us, if you're still having trouble.
To collect analytics about your app's usage, you could either add the snippet of javascript into your Shiny app's code, or leave it to this server, by specifying SHINY_GAID.
Feature | AP Shiny Server | RStudio Shiny Server |
---|---|---|
Multiple Tenants | ✘ | ✓ |
Multiple Shiny Apps | ✘ | ✓ |
Multiple Users | ✓ | ✓ |
Google Analytics | ✓ | ✓ |
SockJS fallback | ✓ | ✓ |
Authentication | ✘ | ✓* (paid) |
Forward all headers | ✓ | ✓* (paid) |
Use non-system R | ✓ (will use R on PATH) | ✓* (paid) |
Timeouts (app and session) | ✘ | ✓ |
Restart by writing restart.txt | ✘ (TODO) | ✓ |
Here were the problems we had with RStudio Shiny Server Open Source:
We don't need several of the features of RStudio Shiny Server:
Writing a single thread shiny server is actually pretty simple, so that's what we have done. It's written in NodeJS merely because it interfaces with HTTP well.
There are some other shiny servers we also considered:
Name | Description | Default |
---|---|---|
SHINY_APP |
Location of Shiny app root | ./example |
SHINY_GAID |
Google Analytics tracking code (e.g. UA-XXXXX-X ) |
No Default |
LOG_LEVEL |
One of info or debug |
info |
ALLOWED_PROTOCOLS |
SockJS enabled transports | websocket, xdr-streaming, xhr-streaming, iframe-eventsource, iframe-htmlfile, xdr-polling, xhr-polling, iframe-xhr-polling, jsonp-polling |
PORT |
Port to run this server on | 9999 |
TARGET_PORT |
Port to run Shiny on. There probably isn't a good reason to change this. | 7999 |
$ npm i -g ministryofjustice/analytics-platform-shiny-server
$ SHINY_APP=/path/to/shiny-app analytics-platform-shiny-server
Which will give you a shiny-server that spawns the R shiny app as a child process, access it on http://localhost:9999
npm run build
The key line of code is to call Shiny's own server method:
shiny::runApp('/myapp', port=80, launch.browser=FALSE)
It configures a shiny.http.response.filter to inject into the <head>
of all sever responses the scripts for SockJS and protocol/transport options etc.
It sets up logging to stdout using logging.js.
GNU Affero General Public License version 3. See LICENCE
Why this licence? While this isn't a fork of the official shiny-server, it is heavily inspired by it. So we've decided to effectively treat this as a fork for licensing purposes and apply the same licence as that: AGPL-3.0.
The example app that is served when no SHINY_APP is specified has it's own licence.
The example app requires a working R and Rshiny install.
Sockjs is bundled in this repository and is licenced under MIT.