plumber

https://www.rplumber.io

Dockerfile

FROM rocker/r-base
LABEL maintainer="Stefan Kuethe <crazycapivara@gmail.com>"
RUN apt-get update -qq && apt-get install -y libxml2-dev
RUN install2.r plumber xml2 base64enci tm
COPY ./scripts /endpoints
EXPOSE 8000
ENTRYPOINT ["R", "-e", "pr <- plumber::plumb(commandArgs()[4]); pr$run(host = '0.0.0.0', port = 8000, swagger = TRUE)"]
CMD ["/endpoints/rstudio_rss-feed.R"]

Endpoints

RStudio rss feed

# rstudio_rss-feed.R
library(xml2)
library(magrittr)

rss_feed <- "https://blog.rstudio.com/index.xml"

#* @get /rstudio_rss_feed
rstudio_rss_feed <- function() {
  rss <- read_xml(rss_feed)
  items <- xml_find_all(rss, ".//item")
  titles <- xml_find_all(items, ".//title") %>%
    xml_text()
  links <- xml_find_all(items, ".//link") %>%
    xml_text()
  data.frame(header = titles, link = links)
}

Images

library(base64enc)

#* @get /plot_that
#* @png
plot_that <- function() {
  x <- seq(1, 10, 0.1)
  y <- sin(x)
  plot(x, y, type = "l")
}

#* @get /plot_base64
plot_base64 <- function() {
  x <- seq(1, 10, 0.1)
  y <- sin(x)
  tmp <- tempfile()
  png(tmp)
  plot(x, y, type = "l")
  dev.off()
  paste("data:image/png;base64,", base64encode(tmp))
}

Blog

library(xml2)
library(magrittr)

rss_feed <- "https://blog.rstudio.com/index.xml"

#* @get /rstudio_rss_feed
rstudio_rss_feed <- function() {
  rss <- read_xml(rss_feed)
  items <- xml_find_all(rss, ".//item")
  titles <- xml_find_all(items, ".//title") %>%
    xml_text()
  links <- xml_find_all(items, ".//link") %>%
    xml_text()
  data.frame(header = titles, link = links, stringsAsFactors = FALSE)
}

library(tm)

#* @get /rocket_science/<count>
rocket_science <- function(headers = NULL, count = 2, lang= "english") {
  if (is.null(headers)) {
    headers <- rstudio_rss_feed()$header
  }
  docs <- Corpus(VectorSource(enc2native(headers))) %>%
    tm_map(content_transformer(tolower)) %>%
    tm_map(removePunctuation) %>%
    tm_map(removeWords, enc2native(stopwords(lang))) %>%
    tm_map(removeNumbers) %>%
    tm_map(stripWhitespace)
  tdm <- TermDocumentMatrix(docs)
  findFreqTerms(tdm, as.integer(count))
}

blog <- "https://blog.eoda.de"

eoda_blog <- function(page = 1) {
  xml <- sprintf("%s/page/%i/", blog, page) %>%
    read_html()
  items <- xml_find_all(xml, ".//article")
  xml_find_all(items, ".//header/h2") %>%
    xml_text()
}

#* @get /eoda_blog
eoda_blog_ <- function(last_page = 3) {
  lapply(1:last_page, eoda_blog) %>%
    unlist()
}

#* @get /blog_that
blog_that <- function(count = 3) {
  rocket_science(eoda_blog_(), count = count, lang = "de")
}

Run and test

$ docker run -d -p 8011:8000 --name plumber \
    -v `pwd`/scripts:/endpoints crazycapivara/plumber r /endpoints/serve_that.R

curl -s http://localhost:8011/blog_that?count=4 | jq

Use in other apps

# app.py
from flask import Flask, render_template
import requests

api = "http://plumber:8000/rstudio_news"

def get_news():
   response = requests.get(api)
   data = response.json()
   response.close()
   return data

app = Flask(__name__)

@app.route("/")
def hello():
   return render_template("rstudio_news.html", news = get_news())

if __name__ == "__main__":
   app.run(host = "0.0.0.0", debug = True)
# docker-compose.yml
version: "2"

services:
  plumber:
    image: crazycapivara/plumber:rstudio_news
  flask:
    image: crazycapivara/flask
    command: app.py
    ports:
      - "5005:5000"