plumber
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"