ministryofjustice / analytics-platform-shiny-server

Analytical Platform Shiny Server • This repository is defined and managed in Terraform
https://user-guide.analytical-platform.service.justice.gov.uk
GNU Affero General Public License v3.0
23 stars 7 forks source link
analytical-platform ministryofjustice

Analytics Platform Shiny Server

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.

Features

SockJS

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.

Google Analytics

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.

Why write another shiny server?

Comparison with Rstudio's Shiny-Server

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:

Configuration

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

How to Run

  1. Install it: $ npm i -g ministryofjustice/analytics-platform-shiny-server
  2. Run it: $ 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

How to release

  1. Make your changes
  2. npm run build
  3. Commit your files included transpiled ones in ./static/
  4. Push to a new branch on github and make a PR

Design

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.

Licences

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.

Example App (Creative Commons)

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 (MIT)

Sockjs is bundled in this repository and is licenced under MIT.