From dc497b49ebb127460715902152e40e104ff8d99f Mon Sep 17 00:00:00 2001 From: andres Date: Tue, 30 Jan 2024 22:39:58 -0500 Subject: [PATCH] Completes README --- README.md | 73 ++++++++++++++++++++++++++++++++++++++++++ examples/counter/app.R | 29 +++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 examples/counter/app.R diff --git a/README.md b/README.md index 12119b6..605dc38 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,76 @@ +# tower + [![R-CMD-check](https://github.com/ixpantia/tower/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/ixpantia/tower/actions/workflows/R-CMD-check.yaml) + +Dead simple middleware for R Shiny. + +## Summary + +`tower` is a simple library for adding middleware to Shiny applications. +It is inspired by the [tower](https://docs.rs/tower/latest/tower/) crate for Rust. +It is designed to enable package authors and Shiny developers to extend +Shiny a little bit more than what is usually possible. + +You can use `tower` to add middlewares that forward, modify, or intercept +requests in Shiny applications. This can be useful for adding logging, authentication, +caching, or routing to your Shiny applications. + +## Installation + +You can install the development version of `tower` from GitHub with: + +``` r +# install.packages("remotes") +remotes::install_github("ixpantia/tower") +``` + +## Example + +We may want to add a new route to our Shiny application that adds a count +to a counter every time a user visits the route. We can do this with `tower` +by adding a middleware that intercepts the request and increments the counter. + +``` r +library(shiny) +library(tower) + +# Counter environment +COUNTER <- new.env() +COUNTER$counter <- 0 + +# Middleware to increment the counter +increment_counter <- function(req) { + if (req$PATH_INFO == "/increment") { + COUNTER$counter <- COUNTER$counter + 1 + return( + httpResponse( + 200, + "text/plain", + paste("Counter is now", COUNTER$counter) + ) + ) + } +} + +# A very empty Shiny app (not necessary for the demo) +ui <- fluidPage() +server <- function(input, output, session) {} + +shinyApp(ui, server) |> + create_tower() |> + add_http_layer(increment_counter) |> + build_tower() +``` + +If you run the code above and visit the route `/increment` in your browser, +you will see the counter increment every time you visit the route. + +## How it works + +Basically, `tower` adds layers to a Shiny application. A layer is a function +that takes a request and returns either a response or NULL. If a layer returns +a response, the response is sent to the client and the request is not forwarded +to the next layer. If a layer returns NULL, the request is forwarded to the next +layer. diff --git a/examples/counter/app.R b/examples/counter/app.R new file mode 100644 index 0000000..8a801df --- /dev/null +++ b/examples/counter/app.R @@ -0,0 +1,29 @@ +library(shiny) +library(tower) + +# Counter environment +COUNTER <- new.env() +COUNTER$counter <- 0 + +# Middleware to increment the counter +increment_counter <- function(req) { + if (req$PATH_INFO == "/increment") { + COUNTER$counter <- COUNTER$counter + 1 + return( + httpResponse( + 200, + "text/plain", + paste("Counter is now", COUNTER$counter) + ) + ) + } +} + +# A very empty Shiny app (not necesarry for the demo) +ui <- fluidPage() +server <- function(input, output, session) {} + +shinyApp(ui, server) |> + create_tower() |> + add_http_layer(increment_counter) |> + build_tower()