<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/rest-apis-and-plumber/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://rviews.rstudio.com/2018/07/23/rest-apis-and-plumber/"> R Views</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>Moving R resources from development to production can be a challenge, especially when the resource isn’t something like a <a rel="nofollow" href="http://shiny.rstudio.com/" target="_blank"><code>shiny</code> application</a> or <a rel="nofollow" href="https://rmarkdown.rstudio.com/" target="_blank"><code>rmarkdown</code> document</a> that can be easily published and consumed. Consider, as an example, a customer success model created in R. This model is responsible for taking customer data and returning a predicted outcome, like the likelihood the customer will churn. Once this model is developed and validated, there needs to be some way for the model output to be leveraged by other systems and individuals within the company.</p>
<p>Traditionally, moving this model into production has involved one of two approaches: either running customer data through the model on a batch basis and caching the results in a database, or handing the model definition off to a development team to translate the work done in R into another language, such as Java or Scala. Both approaches have significant downsides. Batch processing works, but it misses real-time updates. For example, if the batch job runs every night and a customer calls in the next morning and has a heated conversation with support, the model output will have no record of that exchange when the customer calls the customer loyalty department later the same day to cancel their service. In essence, model output is served on a lag, which can sometimes lead to critical information loss. However, the other option requires a large investment of time and resources to convert an existing model into another language just for the purpose of exposing that model as a real-time service. Neither of these approaches is ideal; to solve this problem, the optimal solution is to expose the existing R model as a service that can be easily accessed by other parts of the organization.</p>
<p><a rel="nofollow" href="https://www.rplumber.io/" target="_blank"><code>plumber</code></a> is an R package that allows existing R code to be exposed as a web service through special decorator comments. With minimal overhead, R programmers and analysts can use <code>plumber</code> to create REST APIs that expose their work to any number of internal and external systems. This solution provides real-time access to processes and services created entirely in R, and can effectively eliminate the need to perform batch operations or technical hand-offs in order to move R code into production.</p>
<p>This post will focus on a brief introduction to RESTful APIs, then an introduction to the <code>plumber</code> package and how it can be used to expose R services as API endpoints. In subsequent posts, we’ll build a functioning web API using <code>plumber</code> that integrates with <a rel="nofollow" href="https://slack.com/" target="_blank">Slack</a> and provides real-time customer status reports.</p>
<div>
<h2>Web APIs</h2>
<p>For some, <a rel="nofollow" href="https://en.wikipedia.org/wiki/Application_programming_interface" target="_blank">APIs (Application Programming Interface)</a> are things heard of but seldom seen. However, whether seen or unseen, APIs are part of everyday digital life. In fact, you’ve likely used a web API from within R, even if you didn’t recognize it at the time! Several R packages are simply wrappers around popular web APIs, such as <a rel="nofollow" href="https://walkerke.github.io/tidycensus/" target="_blank"><code>tidycensus</code></a> and <a rel="nofollow" href="https://github.com/r-lib/gh" target="_blank"><code>gh</code></a>. Web APIs are a common framework for sharing information across a network, most commonly through <a rel="nofollow" href="https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol" target="_blank">HTTP</a>.</p>
<div>
<h3>HTTP</h3>
<p>To understand how HTTP requests work, it’s helpful to know the players involved. A <em>client</em> makes a request to a <em>server</em>, which interprets the request and provides a response. An HTTP request can be thought of simply as a packet of information sent to the server, which the server attempts to interpret and respond to. Every time you visit a URL in a web browser, an HTTP request is made and the response is rendered by the browser as the website you see. It is possible to inspect this interaction using the development tools in a browser.</p>
<div>
<img src="https://i2.wp.com/rviews.rstudio.com/post/2018-07-17-blair-plumber-intro-files/devtools-screenshot-request.png?w=456&ssl=1" data-recalc-dims="1">
</div>
<p>As seen above, this request is composed of a URL and a request method, which in the case of a web browser accessing a website, is GET.</p>
<div>
<h4>Request</h4>
<p>There are several components of an <a rel="nofollow" href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html" target="_blank">HTTP request</a>, but here we’ll mention on only a few.</p>
<ul>
<li>URL: the address or endpoint for the request</li>
<li>Verb / method: a specific method invoked on the endpoint (GET, POST, DELETE, PUT)</li>
<li>Headers: additional data sent to the server, such as who is making the request and what type of response is expected</li>
<li>Body: data sent to the server outside of the headers, common for POST and PUT requests</li>
</ul>
<p>In the browser example above, a GET request was made by the web browser to www.rstudio.com.</p>
</div>
<div>
<h4>Response</h4>
<p>The API response mirrors the request to some extent. It includes headers that contain information about the response and a body that contains any data returned by the API. The headers include the HTTP status code that informs the client how the request was received, along with details about the content that’s being delivered. In the example of a web browser accessing www.rstudio.com, we can see below that the response headers include the status code (200) along with details about the response content, including the fact that the content returned is HTML. This HTML content is what the browser renders into a webpage.</p>
<div>
<img src="https://i2.wp.com/rviews.rstudio.com/post/2018-07-17-blair-plumber-intro-files/devtools-screenshot-response.png?w=456&ssl=1" data-recalc-dims="1">
</div>
</div>
</div>
<div>
<h3>httr</h3>
<p>The <a rel="nofollow" href="http://httr.r-lib.org/index.html" target="_blank"><code>httr</code></a> package provides a nice framework for working with HTTP requests in R. The following basic example demonstrates some of what we’ve already learned by using <code>httr</code> and <a rel="nofollow" href="http://httpbin.org/" target="_blank">httpbin.org</a>, which provides a playground of sorts for HTTP requests.</p>
<pre><code>library(httr)
# A simple GET request
response &lt;- GET(&quot;http://httpbin.org/get&quot;)
response</code></pre>
<pre><code>## Response [http://httpbin.org/get]
##   Date: 2018-07-23 14:57
##   Status: 200
##   Content-Type: application/json
##   Size: 266 B
## {&quot;args&quot;:{},&quot;headers&quot;:{&quot;Accept&quot;:&quot;application/json, text/xml, application/...</code></pre>
<p>In this example we’ve made a GET request to httpbin.org/get and received a response. We know our request was successful because we see that the status is 200. We also see that the response contains data in JSON format. The <a rel="nofollow" href="http://httr.r-lib.org/articles/quickstart.html" target="_blank"><em>Getting started with httr</em></a> page provides additional examples of working with HTTP requests and responses.</p>
</div>
<div>
<h3>REST</h3>
<p><a rel="nofollow" href="https://en.wikipedia.org/wiki/Representational_state_transfer" target="_blank">Representational State Transfer (REST)</a> is an architectural style for APIs that includes specific constraints for building APIs to ensure that they are consistent, performant, and scalable. In order to be considered truly RESTful, an API must meet each of the following six constraints:</p>
<ul>
<li>Uniform interface: clearly defined interface between client and server</li>
<li>Stateless: state is managed via the requests themselves, not through reliance on an external service</li>
<li>Cacheable: responses should be cacheable in order to improve scalability</li>
<li>Client-Server: clear separation of client and server, each with it’s on distinct responsibilities in the exchange</li>
<li>Layered System: there may be intermediaries between the client and the server, but the client should be unaware of them</li>
<li>Code on Demand: the response can include logic executable by the client</li>
</ul>
<p>We could spend a lot of time diving further into each of these specifications, but that is beyond the scope of this post. More detail about REST can be found <a rel="nofollow" href="https://www.restapitutorial.com/" target="_blank">here</a>.</p>
</div>
</div>
<div>
<h2>Plumber</h2>
<p>Creating RESTful APIs using R is straightforward using the <code>plumber</code> package. Even if you have never written an API, <code>plumber</code> makes it easy to turn existing R functions into API endpoints. Developing <code>plumber</code> endpoints is simply a matter of providing specialized R comments before R functions. <code>plumber</code> recognizes both <code>#'</code> and <code>#*</code> comments, although the latter is recommended in order to avoid potential conflicts with <a rel="nofollow" href="https://github.com/yihui/roxygen2" target="_blank"><code>roxygen2</code></a>. The following defines a <code>plumber</code> endpoint that simply returns the data provided in the request query string.</p>
<pre><code>library(plumber)

#* @apiTitle Simple API

#* Echo provided text
#* @param text The text to be echoed in the response
#* @get /echo
function(text = &quot;&quot;) {
  list(
    message_echo = paste(&quot;The text is:&quot;, text)
  )
}</code></pre>
<p>Here we’ve defined a simple function that takes a parameter, <code>text</code>, and returns it with some additional comments as part of a list. By default, <code>plumber</code> will serialize the object returned from a function into JSON using the <a rel="nofollow" href="https://github.com/jeroen/jsonlite" target="_blank"><code>jsonlite</code></a> package. We’ve provided specialized comments to inform <code>plumber</code> that this endpoint is available at <code>api-url/echo</code> and will respond to GET requests.</p>
<p>There are a few ways this <code>plumber</code> script can be run locally. First, assuming the file is saved as <code>plumber.R</code>, the following code would start a local web server hosting the API.</p>
<pre><code>plumber::plumb(&quot;plumber.R&quot;)$run(port = 5762)</code></pre>
<p>Once the web server has started, the API can be interacted with using any set of HTTP tools. We could even interact with it using <code>httr</code> as demonstrated earlier, although we would need to open a separate R session to do so since the current R session is busy serving the API.</p>
<p>The other method for running the API requires a recent <a rel="nofollow" href="https://www.rstudio.com/products/rstudio/download/preview/" target="_blank">preview build</a> of the RStudio IDE. Recent preview builds include features that make it easier to work with <code>plumber</code>. When editing a <code>plumber</code> script in a recent version of the IDE, a “Run API” icon will appear in the top right hand corner of the source editor. Clicking this button will automatically run a line of code similar to the one we ran above to start a web server hosting the API. A <a rel="nofollow" href="https://swagger.io/" target="_blank">swagger</a>-generated UI will be rendered in the Viewer pane, and the API can be interacted with directly from within this UI.</p>
<div>
<img src="https://i2.wp.com/rviews.rstudio.com/post/2018-07-17-blair-plumber-intro-files/swagger-screenshot.png?w=456&ssl=1" data-recalc-dims="1">
</div>
<p>Now that we have a running <code>plumber</code> API, we can query it using <code>curl</code> from the command line to investigate it’s behavior.</p>
<pre><code>$ curl &quot;localhost:5762/echo&quot; | jq '.'
{
  &quot;message_echo&quot;: [
    &quot;The text is: &quot;
  ]
}</code></pre>
<p>In this case, we queried the API without providing any additional data or parameters. As a result, the <code>text</code> parameter is the default empty string, as seen in the response. In order to pass a value to our underlying function, we can define a query string in the request as follows:</p>
<pre><code>$ curl &quot;localhost:5762/echo?text=Hi%20there&quot; | jq '.'
{
  &quot;message_echo&quot;: [
    &quot;The text is: Hi there&quot;
  ]
}</code></pre>
<p>In this case, the <code>text</code> parameter is defined as part of the query string, which is appended to the end of the URL. Additional parameters could be defined by separating each key-value pair with <code>&amp;</code>. It’s also possible to pass the parameter as part of the request body. However, to leverage this method of data delivery, we need to update our API definition so that the <code>/echo</code> endpoint also accepts POST requests. We’ll also update our API to consider multiple parameters, and return the parsed parameters along with the entire request body.</p>
<pre><code>library(plumber)

#* @apiTitle Simple API

#* Echo provided text
#* @param text The text to be echoed in the response
#* @param number A number to be echoed in the response
#* @get /echo
#* @post /echo
function(req, text = &quot;&quot;, number = 0) {
  list(
    message_echo = paste(&quot;The text is:&quot;, text),
    number_echo = paste(&quot;The number is:&quot;, number),
    raw_body = req$postBody
  )
}</code></pre>
<p>With this new API definition, the following <code>curl</code> request can be made to pass parameters to the API via the request body.</p>
<pre><code>$ curl --data &quot;text=Hi%20there&amp;number=42&amp;other_param=something%20else&quot; &quot;localhost:5762/echo&quot; | jq '.'
{
  &quot;message_echo&quot;: [
    &quot;The text is: Hi there&quot;
  ],
  &quot;number_echo&quot;: [
    &quot;The number is: 42&quot;
  ],
  &quot;raw_body&quot;: [
    &quot;text=Hi%20there&amp;number=42&amp;other_param=something%20else&quot;
  ]
}</code></pre>
<p>Notice that we passed more than just <code>text</code> and <code>number</code> in the request body. <code>plumber</code> parses the request body and matches any arguments found in the R function definition. Additional arguments, like <code>other_param</code> in this case, are ignored. <code>plumber</code> can parse the request body if it is URL-encoded or JSON. The following example shows the same request, but with the request body encoded as JSON.</p>
<pre><code>$ curl --data '{&quot;text&quot;:&quot;Hi there&quot;, &quot;number&quot;:&quot;42&quot;, &quot;other_param&quot;:&quot;something else&quot;}' &quot;localhost:5762/echo&quot; | jq '.'
{
  &quot;message_echo&quot;: [
    &quot;The text is: Hi there&quot;
  ],
  &quot;number_echo&quot;: [
    &quot;The number is: 42&quot;
  ],
  &quot;raw_body&quot;: [
    &quot;{\&quot;text\&quot;:\&quot;Hi there\&quot;, \&quot;number\&quot;:\&quot;42\&quot;, \&quot;other_param\&quot;:\&quot;something else\&quot;}&quot;
  ]
}</code></pre>
<p>While these examples are fairly simple, they demonstrate the extraordinary facility of <code>plumber</code>. Thanks to <code>plumber</code>, it is now a fairly straightforward process to expose R functions so they can be consumed and leveraged by any number of systems and processes. We’ve only scratched the surface of its capabilities and, as mentioned, future posts will walk through the creation of a Slack app using <code>plumber</code>. Comprehensive documentation for <code>plumber</code> can be found <a rel="nofollow" href="https://www.rplumber.io/docs/" target="_blank">here</a>.</p>
</div>
<div>
<h2>Deploying</h2>
<p>Up until now, we’ve just been interacting with our APIs in our local development environment. That’s great for development and testing, but when it comes time to expose an API to external services, we don’t want our laptop held responsible (at least, I don’t!). There are several <a rel="nofollow" href="https://www.rplumber.io/docs/hosting.html" target="_blank">deployment methods</a> for <code>plumber</code> outlined in the documentation. The most straightforward method of deployment is to use <a rel="nofollow" href="https://www.rstudio.com/products/connect/" target="_blank">RStudio Connect</a>. When editing a <code>plumber</code> script in recent versions of the RStudio IDE, a blue publish button will appear in the top right-hand corner of the source editor. Clicking this button brings up a menu that enables the user to publish the API to an instance of RStudio Connect. Once published, API access and performance can be configured through RStudio Connect and the API can be leveraged by external systems and processes.</p>
</div>
<div>
<h2>Conclusion</h2>
<p>Web APIs are a powerful mechanism for providing systematic access to computational processes. Writing APIs with <code>plumber</code> makes it easy for others to take advantage of the work you’ve created in R without the need to rely on batch processing or code rewriting. <code>plumber</code> is exceptionally flexible and can be used to define a wide variety of endpoints. These endpoints can be used to integrate R with other systems. As an added bonus, downstream consumers of these APIs require no knowledge of R. They only need to know how to properly interact with the API via HTTP. <code>plumber</code> provides a convenient and reliable bridge between R and other systems and/or languages used within an organization.</p>
</div>
<p> </p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://rviews.rstudio.com/2018/07/23/rest-apis-and-plumber/"> R Views</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/aHG5vqpxMbk" height="1"></a></div>