0Pricing
R Academy · Lezione

Introduzione a Plumber e REST

Comprenda i principi REST e annoti le funzioni R come endpoint API

Introduzione a Plumber e REST è una lezione R Academy gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento R Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso R Academy include 4 lezioni in totale.

Che cos'è un'API REST?

Un'API REST (Representational State Transfer) è un servizio web che espone dati e operazioni tramite HTTP. Principi fondamentali:

  • Stateless: ogni richiesta contiene tutte le informazioni necessarie; non esiste una sessione lato server.
  • Orientata alle risorse: gli endpoint rappresentano risorse (/users, /predictions).
  • Verbi HTTP standard: GET (lettura), POST (creazione), PUT (aggiornamento), DELETE (rimozione).
  • JSON: il formato dati standard per i corpi delle richieste e delle risposte.
# REST API concepts in HTTP terms:
# GET /api/model/predict?x=5      -> read a prediction
# POST /api/model/train           -> create a new model
# GET /api/data/summary           -> read data summary
# DELETE /api/cache/flush         -> remove cached results

# Plumber maps R functions to these HTTP endpoints
cat('REST: stateless, resource-oriented, JSON responses')

Sintassi delle annotazioni di plumber

plumber utilizza annotazioni speciali nei commenti, che iniziano con #*, per definire gli endpoint dell'API. Inserisca un'annotazione direttamente sopra la funzione R che gestisce l'endpoint. Gli argomenti della funzione vengono associati ai parametri della richiesta; il valore restituito diventa il corpo della risposta JSON.

# plumber.R
library(plumber)

#* @get /ping
function() {
  list(status = 'ok', time = Sys.time())
}

#* @get /add
#* @param a:int First number
#* @param b:int Second number
function(a, b) {
  list(result = as.integer(a) + as.integer(b))
}

pr() — Creazione di un router Plumber

pr('plumber.R') legge un file plumber e crea un oggetto router che registra tutti gli endpoint annotati. Il router è l'oggetto centrale da configurare (aggiungendo filtri, serializzatori e così via) prima dell'avvio.

library(plumber)

# Create a router from a plumber file
api <- pr('plumber.R')

# Inspect registered routes
print(api$routes)

# Alternatively, define inline without a file:
api <- pr() |>
  pr_get('/ping', function() list(status = 'ok')) |>
  pr_post('/echo', function(req) req$body)

pr_run() — Avvio del server

pr_run(router, host, port) avvia il server dell'API plumber. Per impostazione predefinita, si associa a 127.0.0.1:8000. Imposti host = '0.0.0.0' per accettare connessioni da qualsiasi interfaccia di rete, come richiesto da Docker o dall'accesso remoto.

library(plumber)

api <- pr('plumber.R')

# Start server on localhost port 8000
# pr_run(api, host = '127.0.0.1', port = 8000)

# For Docker/remote access, bind to all interfaces
# pr_run(api, host = '0.0.0.0', port = 8000)

# View auto-generated Swagger docs in browser
# (automatically available at /docs or /__docs__/ endpoint)
cat('Swagger UI auto-generated at http://localhost:8000/__docs__/')

Annotazione @get

L'annotazione #* @get /path associa una richiesta GET alla funzione. I parametri della query string (ad esempio ?name=Alice) vengono passati automaticamente come argomenti della funzione R. Se non viene specificata alcuna annotazione di conversione, i parametri arrivano come stringhe di caratteri.

# plumber.R

#* Greet a user by name
#* @param name:str The name to greet
#* @get /greet
function(name = 'World') {
  list(
    message = paste('Hello,', name),
    timestamp = format(Sys.time(), '%Y-%m-%d %H:%M:%S')
  )
}
# GET /greet?name=Alice
# -> {"message":"Hello, Alice","timestamp":"2026-01-01 12:00:00"}

Annotazione @post

L'annotazione #* @post /path associa una richiesta POST alla funzione. Il corpo della richiesta, in genere JSON, è accessibile tramite l'argomento speciale req come req$body (una lista analizzata quando il corpo della richiesta è JSON). POST viene utilizzato per le operazioni che creano risorse o avviano calcoli.

# plumber.R

#* Run a linear model prediction
#* @post /predict
function(req) {
  # req$body is already parsed from JSON
  input_data <- as.data.frame(req$body)

  # Run prediction with a pre-loaded model
  predictions <- predict(trained_model, newdata = input_data)

  list(
    predictions = as.numeric(predictions),
    n           = nrow(input_data)
  )
}

Serializzatore JSON

Per impostazione predefinita, plumber serializza i valori restituiti in JSON utilizzando jsonlite. L'annotazione #* @serializer json rende esplicito questo comportamento. È possibile configurare opzioni del serializzatore, come la formattazione leggibile o la gestione dei valori nulli, specificandole come lista JSON nell'annotazione.

# Default: automatic JSON serialization
#* @get /data
function() {
  list(values = 1:5, labels = c('a', 'b', 'c', 'd', 'e'))
}

# Explicit JSON serializer with options
#* @serializer json list(na = 'null', auto_unbox = TRUE)
#* @get /data_explicit
function() {
  list(value = 42, missing = NA)
}
# With auto_unbox=TRUE: {"value":42} not {"value":[42]}

Verbi HTTP — PUT, DELETE, PATCH

plumber supporta tutti i verbi HTTP standard tramite annotazioni corrispondenti:

  • #* @put /path: sostituzione completa di una risorsa.
  • #* @delete /path: rimozione di una risorsa.
  • #* @patch /path: aggiornamento parziale di una risorsa.
  • #* @head /path: solo intestazioni, senza corpo.
# plumber.R — CRUD-style endpoints

#* Update a model configuration
#* @put /config/<model_id>
function(model_id, req) {
  config <- req$body
  save_config(model_id, config)
  list(updated = model_id, config = config)
}

#* Remove cached results
#* @delete /cache/<key>
function(key) {
  cache_env <- globalenv()$cache
  rm(list = key, envir = cache_env)
  list(deleted = key)
}

Parametri del percorso

I parametri del percorso vengono definiti utilizzando parentesi angolari nella route: /user/. plumber estrae il valore dall'URL e lo passa come argomento della funzione con lo stesso nome. Sono diversi dai parametri della query, che compaiono dopo ?.

# plumber.R

#* Get stats for a specific dataset
#* @param dataset_id:str The dataset identifier
#* @get /datasets/<dataset_id>/stats
function(dataset_id) {
  if (!dataset_id %in% available_datasets()) {
    stop(paste('Dataset not found:', dataset_id))
  }
  ds <- load_dataset(dataset_id)
  list(
    id    = dataset_id,
    rows  = nrow(ds),
    cols  = ncol(ds),
    names = names(ds)
  )
}

Gestione degli errori

Quando una funzione R genera un errore, plumber lo intercetta e restituisce una risposta HTTP 500 con il messaggio di errore in JSON. Per le API rivolte agli utenti, restituisca esplicitamente codici di stato HTTP appropriati utilizzando res$status e stop() per gli errori di validazione.

# plumber.R

#* Divide two numbers safely
#* @get /divide
function(a, b, res) {
  a <- suppressWarnings(as.numeric(a))
  b <- suppressWarnings(as.numeric(b))

  if (is.na(a) || is.na(b)) {
    res$status <- 400  # Bad Request
    return(list(error = 'Both a and b must be numeric'))
  }
  if (b == 0) {
    res$status <- 422  # Unprocessable Entity
    return(list(error = 'Division by zero is not allowed'))
  }
  list(result = a / b)
}

Documentazione Swagger generata automaticamente

plumber genera automaticamente la documentazione interattiva Swagger UI a partire dalle annotazioni. Visiti /__docs__/ quando il server è in esecuzione per visualizzare tutti gli endpoint e i relativi parametri e provarli nel browser. Utilizzi #* @tag per raggruppare logicamente gli endpoint.

# plumber.R with Swagger metadata

#* @apiTitle My ML Prediction API
#* @apiDescription Serves predictions from trained R models
#* @apiVersion 1.0.0

#* @tag model
#* @get /health
function() list(status = 'healthy')

#* Predict house price
#* @tag prediction
#* @param sqft:dbl Square footage
#* @param bedrooms:int Number of bedrooms
#* @get /predict
function(sqft = 1000, bedrooms = 3) {
  pred <- predict(price_model, data.frame(sqft = as.numeric(sqft),
                                          bedrooms = as.integer(bedrooms)))
  list(predicted_price = round(as.numeric(pred), 2))
}

Verifica rapida

In plumber, qual è la differenza tra un parametro della query (ad esempio /greet?name=Alice) e un parametro del percorso (ad esempio /user/42)?

Riepilogo di plumber e REST

Punti chiave dell'introduzione a plumber e REST:

  • REST: stateless, orientato alle risorse, utilizza verbi HTTP standard e restituisce JSON.
  • plumber associa le funzioni R agli endpoint utilizzando annotazioni #* sopra le funzioni.
  • pr('file.R') crea un router; pr_run(api, host, port) avvia il server.
  • #* @get /path gestisce GET; #* @post /path gestisce POST.
  • Parametri del percorso: /user/; parametri della query: /search?term=foo.
  • Restituisca liste con nomi: plumber le serializza automaticamente in JSON.
  • Swagger UI viene generata automaticamente in /__docs__/ a partire dalle annotazioni.
# Complete minimal plumber API
library(plumber)

#* @apiTitle Simple Prediction API

#* Health check
#* @get /health
function() list(status = 'ok')

#* Predict mpg from weight
#* @param wt:dbl Car weight (1000 lbs)
#* @get /predict
function(wt = 3.0) {
  pred <- predict(lm(mpg ~ wt, data = mtcars),
                  newdata = data.frame(wt = as.numeric(wt)))
  list(wt = as.numeric(wt), predicted_mpg = round(pred, 2))
}

# Run:
# api <- pr('plumber.R')
# pr_run(api, port = 8000)

Domande Frequenti

La lezione «Introduzione a Plumber e REST» è gratuita?

Sì — il testo completo di «Introduzione a Plumber e REST» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso R Academy, passa a CoddyKit PRO. Il corso R Academy include 4 lezioni in totale.

Cosa imparerò in «Introduzione a Plumber e REST»?

Comprenda i principi REST e annoti le funzioni R come endpoint API Eserciti R Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare R Academy?

Non è richiesta alcuna esperienza precedente. R Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.

Quanto tempo richiede la lezione «Introduzione a Plumber e REST»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione R Academy?

Sì. Ogni lezione R Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Introduzione a Plumber e REST
  2. Creazione di endpoint GET e POST
  3. Autenticazione e sicurezza delle API
  4. Distribuzione in produzione delle API Plumber
← Torna a R Academy