Why POST request in RShiny returns "Bad Request" when "www" directory is present?

Code inside "app.R"

library(shiny)

shiny:::handlerManager$addHandler(
  function(req) {
    print(req$REQUEST_METHOD)
    return(NULL)
  },
  "key"
)
ui <- fluidPage()
server <- function(input, output) {}
shinyApp(ui = ui, server = server)

When directory structure looks like this:

app/
|-- app.R

The commands

curl -X GET http://127.0.0.1:3818
curl -X POST http://127.0.0.1:3818

works fine.
The R console outputs

Listening on http://127.0.0.1:3818
[1] "GET"
[1] "POST"
[1] "GET"

But when i add empty www directory to app directory POST no longer works.
(If I add dir named www_tmp it works)

app/
|-- app.R
|-- www/

The R console outputs after same GET and POST request

Listening on http://127.0.0.1:3818
[1] "GET"
[1] "GET"

So my questions are ...

  • Why does www dir impacts POST request?
  • Can i fix it somehow? (Have www dir and POST request)

---------- EDIT 2023-03-30 Solution ----------
Why does www dir impacts POST request?

hg77 answered it in Accepting POST requests from Shiny · GitHub :

I think I found the root cause in https://github.com/rstudio/shiny/blob/main/R/server.R#L395
httpuv is handling the requests before they hit the R handlers.

"session" = excludeStaticPath(),

/session is excluded. And

curl -vX POST http://localhost:3838/session/post 

hits the R handlers.

Can i fix it somehow? (Have www dir and POST request)

Yes! But I need to exclude my path form handling by httpuv
I can do it by:

shiny_env <- shiny:::.globals
shiny_env$resourcePaths <- c(shiny_env$resourcePaths, list("MY_POST_ROOT_PATH" = httpuv::excludeStaticPath()))

The full working app would look like this:

library(shiny)

shiny:::handlerManager$addHandler(
  function(req) {
    print(req$REQUEST_METHOD)
    return(NULL)
  },
  "key"
)
ui <- fluidPage()
server <- function(input, output) {}

shiny_env <- shiny:::.globals
shiny_env$resourcePaths <- c(shiny_env$resourcePaths, list("postpath" = httpuv::excludeStaticPath()))

shinyApp(ui = ui, server = server)

This app can accept all POST request to path postpath
e.g.: curl -vX POST http://localhost:3838/postpath/
Note: The / at the end is required

1 Like

Currently I can't test it, however, you might want to check the app structure of Joe Cheng's gist here (the www subdirectory issue is mentioned in a comment - not sure what the outcome was) or my post here.

By now I tested it - same behaviour:
HTTP/1.1 400 Bad Request once the app is deployed with a www folder.

1 Like

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.