rstudio / plumber

Turn your R code into a web API.
https://www.rplumber.io
Other
1.39k stars 256 forks source link

Plumber API inaccessible from browser(Google Chrome) #435

Open anv42 opened 5 years ago

anv42 commented 5 years ago

Hello,

I'm trying to access a Plumber API hosted on an RStudio Connect Server from Chrome. Here's a simplified structure of the plumber.R file :

#* Check API readiness
#* @get /healthcheck
function(res, req) {
  res$status <- 200
  return("Give some data, I'm ready to cluster")  
}

#' CORS testing
#' @post /test
function(req, res, in_str) {
  if (identical(req$postBody, character(0))){
    res$status <- 400
    return("Empty body: provide a user id")
    stop()
  } else {
    message(">>> Working on it... <<<")
    out_str <- glue::glue("Test : {in_str}")
    res$body <- out_str
  }
}  

This API is working with a simple CURL statement issued from the command line, like so:

curl -X POST "https://r-studio-connect-xxx.com/content/169/test"  -H  "accept: application/json" -H 'Authorization: Key XXXXX' -d '{"in_str":"successful"}'

However, when I try to access the same API by submitting a fetch request from the chrome console, I get a 404 response.

Here's the call to the API from the Chrome Console :

fetch('https://r-studio-connect-xxx/content/169/test', { method: 'POST', mode: 'cors', headers: { accept: 'application/json', Authorization: "Key XXXXX" }, body: '{"in_str":"successful"}'  }).then(res => res.json()).then(data => console.warn('Yay, CORS worked`, data')).catch(error => console.error('Ooops, something went wrong'))

And here's the error:

> Access to fetch at 'https://r-studio-connect-xxx/content/169/test' from origin 'https://www.google.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

In order to fix the issue, I tried adding two kinds of approaches to a filter on top of my plumber.R script as suggested before in the forum but they don't work and I'm getting the exact same response. Here are the filters:

#* @filter cors
cors <- function(req, res) {
  res$setHeader('Access-Control-Allow-Origin', '*')
  plumber::forward()
}
#' @filter cors
cors <- function(req, res) {

  res$setHeader("Access-Control-Allow-Origin", "*")

  if (req$REQUEST_METHOD == "OPTIONS") {
    res$setHeader("Access-Control-Allow-Methods","*")
    res$setHeader("Access-Control-Allow-Headers", req$HTTP_ACCESS_CONTROL_REQUEST_HEADERS)
    res$status <- 200 
    return(list())
  } else {
    plumber::forward()
  }

}

Has anyone faced this before and been able to resolve it? I'd be grateful for any kind of help on this.

schloerke commented 5 years ago

@blairj09 do you think this is related to the other RSC bug?

blairj09 commented 5 years ago

Unfortunately, this is a known issue in RStudio Connect that is currently being worked on. The problem is that the pre-flight request sent by the web browser doesn't contain the Authorization header that RStudio Connect expects, so an error is returned. If you can open the API up without requiring RStudio Connect authentication, then the second CORS filter you've described will work.

averyrobbins1 commented 3 years ago

If you can open the API up without requiring RStudio Connect authentication, then the second CORS filter you've described will work.

How would one use an API hosted on RStudio Connect that requires the authentication? Does something need to be changed in the API (like the CORS), or does this involve sending credentials in the header of a request being made?

blairj09 commented 3 years ago

@averyrobbins1 to access an authenticated API hosted on RStudio Connect, you supply a valid RStudio Connect API key in an Authorization header with the request. More details can be found here.

brettduersch commented 2 years ago

Unfortunately, this is a known issue in RStudio Connect that is currently being worked on. The problem is that the pre-flight request sent by the web browser doesn't contain the Authorization header that RStudio Connect expects, so an error is returned. If you can open the API up without requiring RStudio Connect authentication, then the second CORS filter you've described will work.

Any solutions to this issue yet? I'm having the exact issue described above - the plumber API hosted on RSC works fine when no authentication required, but as soon as authentication is required I get the preflight warning above - using RSC 1.8.8

blairj09 commented 2 years ago

CORS may need to be enabled in RStudio Connect: https://docs.rstudio.com/connect/admin/appendix/configuration/#CORS