---
title: "A first look into tower: Powerful middleware in Shiny"
description: Tower is a powerful R package built to make writing middlewares for Shiny applications as simple as possible.
image: https://www.ixpantia.com/hubfs/821e66f3-345a-4390-84d8-bf74e4f7c08f.webp
---

[Skip to content](https://www.ixpantia.com/en/blog/a-first-look-into-tower-powerful-middleware-in-shiny#main-content)

[![ixpantia-logo](https://www.ixpantia.com/hubfs/ixpantia-logo.svg)](https://www.ixpantia.com/en/?hsLang=en)

- [About Us](https://www.ixpantia.com/en/ixpantia)
- [Practices](https://www.ixpantia.com/en/)
  
  Show submenu for Practices 
  
    - [Science and Methodology](https://www.ixpantia.com/en/science-methodology)
    - [Adoption & Maturity](https://www.ixpantia.com/en/products-impact)
    - [Engineering and Architecture](https://www.ixpantia.com/en/engineering-and-architecture)
- [Industries](https://www.ixpantia.com/en/industries)
- [Content](https://www.ixpantia.com/en/content)
  
  Show submenu for Content 
  
    - [Events](https://www.ixpantia.com/en/events)
- [Contact Us](https://www.ixpantia.com/en/contact-us)

Open main navigation

Close main navigation

- [About Us](https://www.ixpantia.com/en/ixpantia)
- [Practices](https://www.ixpantia.com/en/)
  
  Show submenu for Practices 
  
    - [Science and Methodology](https://www.ixpantia.com/en/science-methodology)
    - [Adoption & Maturity](https://www.ixpantia.com/en/products-impact)
    - [Engineering and Architecture](https://www.ixpantia.com/en/engineering-and-architecture)
- [Industries](https://www.ixpantia.com/en/industries)
- [Content](https://www.ixpantia.com/en/content)
  
  Show submenu for Content 
  
    - [Events](https://www.ixpantia.com/en/events)
- [Contact Us](https://www.ixpantia.com/en/contact-us)

 Jul 15, 2024, 5:05:28 PM

# A first look into tower: Powerful middleware in Shiny

![Picture of Andrés Quintero Moreano](https://www.ixpantia.com/hs-fs/hubfs/DSC_2307-1.jpg?width=50&name=DSC_2307-1.jpg) [Andrés Quintero Moreano](https://www.ixpantia.com/en/blog/author/andres-quintero-moreano)

Share: [linkedin-in icon](http://www.linkedin.com/shareArticle?mini=true&url=https://www.ixpantia.com/en/blog/a-first-look-into-tower-powerful-middleware-in-shiny) [facebook-f icon](http://www.facebook.com/share.php?u=https://www.ixpantia.com/en/blog/a-first-look-into-tower-powerful-middleware-in-shiny) [X Twitter icon](https://twitter.com/intent/tweet?url=https://www.ixpantia.com/en/blog/a-first-look-into-tower-powerful-middleware-in-shiny) [pinterest-p icon](http://pinterest.com/pin/create/link/?url=https://www.ixpantia.com/en/blog/a-first-look-into-tower-powerful-middleware-in-shiny) [envelope icon](mailto:?body=https://www.ixpantia.com/en/blog/a-first-look-into-tower-powerful-middleware-in-shiny)

This is a first look into [tower](https://ixpantia.github.io/tower/), an R package dedicated to make it convenient to write custom middlewares directly into Shiny.

Tower was born with the purpose to help us implement authorization flows directly into our Shiny Apps, however it has been used for many other purposes.

In this post we will cover how to get started with tower and how to implement a very simple authorization flow with HTTP cookies.

## How does tower work

Tower works by taking a Shiny app object and breaking it down into a mutable structure to which we can add layers. A layer is just a function that takes in a *request* environment object and returns either an HTTP response or *NULL*. If a layer returns a response it short circuits and takes the response back to the user, if it returns *NULL* then it goes on to the next layer until it reaches a response.

Tower also includes some helper functions to build HTTP responses more easily, we will take a look into that later in the post.

## Building a simple authorization workflow in Shiny

For this post we will be building a very simple (not secure in any sense of the word) authorization workflow. Basically, the user will have to access a super secret URL before being allowed to use the application.

For example, if the user tries to enter the app without previous authorization then they should get some sort of “Not authenticated” page. Once the user enter *http://localhost:3838/secret\_entry\_page*, then they should be able to use the app.

To achieve this we will use HTTP cookies and build our service directly into our Shiny app using tower.

### Building our app

Let’s start by building a very minimal Shiny App. This is the code for the app we will build on top of. 

```
library(shiny)ui <- fluidPage(  "This is a secret Shiny app")server <- function(input, output, session) {}shinyApp(ui, server)
```

We want the user to not be able to use the app unless they have some sort of key. For this example, we will hard-code it into our app.

```
SECRET <- "SUPER_SECURE_PASSPHRASE"
```

Now we will need to build a middleware layer that checks the user’s cookies and checks if it has the secret. This function will take a request object and continue the flow if the secrets match, if not it will return a 401 HTTP response.

```
http_check_secret_layer <- function(req) {  cookies <- tower::req_cookies()  if (identical(cookies$secret, SECRET)) {    return(NULL)  }  tower::response_builder() |>    tower::set_status(401) |>    tower::add_body("Not authorized") |>    tower::build_response()}
```

Now in order to add this layer to our app we will need to take the app object and insert the layer into it. Now our code should look something like this:

```
shinyApp(ui, server) |>  tower::create_tower() |>  tower::add_http_layer(http_check_secret_layer) |>  tower::build_tower()
```

In this case we take our app, create a tower, add the layer we just built and construct the tower into a new shiny app object. If we try to access the app now we should see a not authorized response.

![2024-07-15_17-27](https://www.ixpantia.com/hs-fs/hubfs/2024-07-15_17-27.png?width=313&height=206&name=2024-07-15_17-27.png)

### Adding a way for users to enter the app

Now that we can block incoming HTTP requests, we need to add a way to allow users to enter. For this we will create a secret page that if the user enters it sets the appropriate cookie and returns the user back to the home page.

For this we will create another layer, this time this layer will work as a route for our application.

```
http_add_secret_cookie <- function(req) {  tower::response_builder() |>    tower::set_status(302) |>    tower::set_header("Location", "/") |>    tower::add_cookie("secret", SECRET) |>    tower::add_body(NULL) |>    tower::build_response()}shinyApp(ui, server) |>  tower::create_tower() |>  tower::add_get_route("/secret_entry_page", http_add_secret_cookie) |>  tower::add_http_layer(http_check_secret_layer) |>  tower::build_tower()
```

The layer returns a response that redirects the user back to the home page “/”, and in the process, adds the secret as a cookie. 

We then add this handler to our tower before the *http\_check\_secret\_layer* middleware layer. Now if we try to enter into *http://localhost:3838/secret\_entry\_page* we will see our app.

![2024-07-15_17-38](https://www.ixpantia.com/hs-fs/hubfs/2024-07-15_17-38.png?width=415&height=229&name=2024-07-15_17-38.png)

## Conclusion

Tower is a very powerful R package to make Shiny application development more flexible. It is still under development so expect changes, but feedback is more than welcome. Any suggestions, bug reports, etc are welcome in the official [GitHub Page](https://github.com/ixpantia/tower).

[R](https://www.ixpantia.com/en/blog/tag/r), [Data Engineering](https://www.ixpantia.com/en/blog/tag/data-engineering), [Data Architecture](https://www.ixpantia.com/en/blog/tag/data-architecture)

## Related posts

[![](https://www.ixpantia.com/hs-fs/hubfs/Mauro%20Positron%20a%20Rstudio%20(1).png?height=200&name=Mauro%20Positron%20a%20Rstudio%20(1).png)](https://www.ixpantia.com/en/blog/positron-from-rstudio?hsLang=en)

[R](https://www.ixpantia.com/en/blog/tag/r), [Code](https://www.ixpantia.com/en/blog/tag/code), [RSE](https://www.ixpantia.com/en/blog/tag/rse), [Data Science](https://www.ixpantia.com/en/blog/tag/data-science), [software development](https://www.ixpantia.com/en/blog/tag/software-development), [Posit conf](https://www.ixpantia.com/en/blog/tag/posit-conf)

## [Approaching Positron from RStudio](https://www.ixpantia.com/en/blog/positron-from-rstudio?hsLang=en)

![Picture of Mauro Lepore](https://www.ixpantia.com/hs-fs/hubfs/mauro.jpeg?width=50&name=mauro.jpeg) [Mauro Lepore](https://www.ixpantia.com/en/blog/author/mauro-lepore) 

 Apr 2, 2025, 8:54:14 AM

If you have worked with the R language, chances are you have used the integrated development...

[Read more](https://www.ixpantia.com/en/blog/positron-from-rstudio?hsLang=en)

[![](https://www.ixpantia.com/hs-fs/hubfs/Snap.png?height=200&name=Snap.png)](https://www.ixpantia.com/en/blog/code-getting-started-with-async-programming-in-r-with-promises-and-rust?hsLang=en)

[R](https://www.ixpantia.com/en/blog/tag/r), [Shiny](https://www.ixpantia.com/en/blog/tag/shiny), [Data Engineering](https://www.ixpantia.com/en/blog/tag/data-engineering), [Rust](https://www.ixpantia.com/en/blog/tag/rust)

## [Getting started with Async Programming in R with Promises and Rust 🦀](https://www.ixpantia.com/en/blog/code-getting-started-with-async-programming-in-r-with-promises-and-rust?hsLang=en)

![Picture of Andrés Quintero Moreano](https://www.ixpantia.com/hs-fs/hubfs/DSC_2307-1.jpg?width=50&name=DSC_2307-1.jpg) [Andrés Quintero Moreano](https://www.ixpantia.com/en/blog/author/andres-quintero-moreano) 

 Sep 12, 2024, 2:08:32 PM

Writing asynchronous or parallel R can be a challenge for many. Worry no more, in this guide you...

[Read more](https://www.ixpantia.com/en/blog/code-getting-started-with-async-programming-in-r-with-promises-and-rust?hsLang=en)

[![](https://www.ixpantia.com/hs-fs/hubfs/blog%20banner%20(17).png?height=200&name=blog%20banner%20(17).png)](https://www.ixpantia.com/en/blog/how-to-run-r-shiny-in-docker-guide?hsLang=en)

[Shiny](https://www.ixpantia.com/en/blog/tag/shiny), [Docker](https://www.ixpantia.com/en/blog/tag/docker), [Faucet](https://www.ixpantia.com/en/blog/tag/faucet), [Shiny in Docker](https://www.ixpantia.com/en/blog/tag/shiny-in-docker), [R in Docker](https://www.ixpantia.com/en/blog/tag/r-in-docker), [Scale Shiny Apps](https://www.ixpantia.com/en/blog/tag/scale-shiny-apps), [Rocker/Shiny](https://www.ixpantia.com/en/blog/tag/rocker-shiny)

## [How to Run R Shiny in Docker: A Step-by-Step Guide](https://www.ixpantia.com/en/blog/how-to-run-r-shiny-in-docker-guide?hsLang=en)

![Picture of Andrés Quintero Moreano](https://www.ixpantia.com/hs-fs/hubfs/DSC_2307-1.jpg?width=50&name=DSC_2307-1.jpg) [Andrés Quintero Moreano](https://www.ixpantia.com/en/blog/author/andres-quintero-moreano) 

 Oct 8, 2024, 7:05:55 AM

R Shiny is one of the most efficient ways of writing interactive data applications. And when it’s...

[Read more](https://www.ixpantia.com/en/blog/how-to-run-r-shiny-in-docker-guide?hsLang=en)

[facebook-f icon](https://www.facebook.com/ixpantia/) [linkedin-in icon](https://www.linkedin.com/company/ixpantia/) [Twitter icon](https://twitter.com/ixpantia)

This is a search field with an auto-suggest feature attached.

- There are no suggestions because the search field is empty.

- [About Us](https://www.ixpantia.com/en/ixpantia)
- [Practices](https://www.ixpantia.com/en/) 
    - [Science and Methodology](https://www.ixpantia.com/en/science-methodology)
    - [Adoption & Maturity](https://www.ixpantia.com/en/products-impact)
    - [Engineering and Architecture](https://www.ixpantia.com/en/engineering-and-architecture)
- [Industries](https://www.ixpantia.com/en/industries)
- [Content](https://www.ixpantia.com/en/content) 
    - [Events](https://www.ixpantia.com/en/events)
- [Contact Us](https://www.ixpantia.com/en/contact-us)

---

Copyright © 2026, ixpantia  
hola@ixpantia.com

 

```json
{
  "@context" : "https://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Andrés Quintero Moreano",
    "url" : "https://www.ixpantia.com/en/blog/author/andres-quintero-moreano"
  },
  "dateModified" : "2024-07-16T14:36:16.982Z",
  "datePublished" : "2024-07-15T23:05:28.000Z",
  "headline" : "A first look into tower: Powerful middleware in Shiny",
  "image" : [ "https://www.ixpantia.com/hubfs/821e66f3-345a-4390-84d8-bf74e4f7c08f.webp" ],
  "mainEntityOfPage" : {
    "@id" : "https://www.ixpantia.com/en/blog/a-first-look-into-tower-powerful-middleware-in-shiny",
    "@type" : "WebPage"
  },
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "url" : "https://www.ixpantia.com/hubfs/ixpantia-logo-1.svg"
    },
    "name" : "ixpantia"
  }
}
```