Cross-origin requests with beakr
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
beakr is a lightweight and flexible web framework that allows you to incorporate R code as the Middleware responsible for handling web requests. At Mazama Science, we developed beakr to simplify the process of creating R-based web services that we use to deliver a variety of products: data files, images, rendered Rmarkdown documents, etc.
In this article, we discuss using beakr to set a CORS header and create an example beakr instance that can respond to cross-origin javascript requests.
What is CORS?
Normally, sharing resources across various domains is restricted in modern browsers by a Same-Origin Policy. Why? SOP serves as a security mechanism as it permits scripts contained in a web page to access data from a web service only if they share the same domain (aka ‘origin’). Generally speaking, the SOP mechanism is good practice as it prevents malicious javascript code from making unauthorized requests.
You may be wondering how it is you are able to share images and/or data across websites. This is where CORS comes in. CORS stands for Cross-Origin Resource Sharing. As the name suggests, it allows web pages from one domain to make resource requests from another trusted domain. The default CORS policy allows web pages to directly embed cross-origin images, stylesheets, etc. However, the default policy limits javascript requests for web resources to resources coming from the same origin as the requesting web page. For example, if you build a web page with javascript code that tries to retrieve JSON data or images from a different domain, this will be prohibited unless the web server at that different domain specifically allows cross-origin requests.
But this is precisely what we can allow with breakr!
beakr + CORS =
Websites use HTTP to negotiate the exchange between client and server and to determine access permissions. When a web page uses javascript to request a resource from a server, the browser passes along information about the web page origin. In order for javascript to be able to use the response data, the server responding to the request must tell the browser “This request-origin can access my resource“. The browser remembers that and allows cross-origin resource sharing.
A web server allows programmatic (javascript) resource requests from another origin by overriding the default, highly restrictive CORS access policy. This is done by specifying Access-Control-Allow-Origin
in the HTTP response header. In a beakr web application, the HTTP header is part of the built-in Response (res
) object. Changes to the response header are made with the res$setHeader()
method. That’s it.
An Example
The beakr instance below demonstrates how to allow cross-origin requests. This instance serves the mtcars
dataset as a JSON object at the address 127.0.0.1:8888/json_data
. We explicitly set the CORS policy to allow access from any (*
) external server.
# Import the beakr library library(beakr) # Create JSON data from the mtcars dataset json <- jsonlite::toJSON(mtcars) # Create the beakr instance newBeakr() %>% # Respond to GET requests at the '/json_data' route httpGET("/json_data", function(req, res, err) { res$setContentType("application/json") # Set the CORS access policy! res$setHeader("Access-Control-Allow-Origin", "*") return(json) }) %>% # Set up a server on localhost port 8888 listen(host = "127.0.0.1", port = 8888)
Now it will be possible for another web page not served from our local host (known as “mtcars.org” to the outside world) to access this information programmatically with the following javascript snippet:
<html> ... <script> ... async function mtcarsJSON() { let url = 'mtcars.org:8888/json_data'; try { let res = await fetch(url); return await res.json(); } catch (error) { console.log(error); } } </script </html>
If our server didn’t explicitly allow CORS requests, the web browser javascript console would display one of the many CORS error messages after making the request.
The great thing about working with beakr is that it allows us to create a web service with fine-grained control over which URL routes have restrictive CORS policies and which ones are more open.
Best of luck creating cross-origin web services with beakr!
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.