### Install plumber2 Package Source: https://github.com/posit-dev/plumber2/blob/main/README.md Demonstrates how to install the plumber2 package from CRAN or the development version from GitHub using the 'pak' package manager. ```r # install.packages("pak") pak::pak("posit-dev/plumber2") ``` -------------------------------- ### plumber2 Hello World API Example Source: https://github.com/posit-dev/plumber2/blob/main/README.md A basic 'hello world' API example for plumber2, showcasing differences from the original plumber package. It includes an endpoint to echo a message and demonstrates path parameters. ```r #* Echo the parameter that was sent in #* #* @get /echo/ #* #* @param msg:string The message to echo back. #* #* @response 200:{msg:string} A string containing the input message #* function(msg) { list( msg = paste0("The message is: '", msg, "'") ) } ``` -------------------------------- ### Define GET Request Handlers Source: https://context7.com/posit-dev/plumber2/llms.txt Shows how to register GET endpoints using the api_get function. Includes examples for simple responses, typed path parameters, and query parameter access. ```R pa <- api() |> api_get("/hello", function() { list(message = "Hello, World!") }) pa <- api() |> api_get("/user/", function(id) { list(user_id = id, name = paste("User", id)) }) pa <- api() |> api_get("/user//posts/", function(username, post_id) { list( username = username, post_id = post_id, content = "Post content here" ) }) pa <- api() |> api_get("/search", function(query) { list( search_term = query$q %||% "", page = query$page %||% 1, results = list() ) }) ``` -------------------------------- ### Adding GET Handlers Source: https://context7.com/posit-dev/plumber2/llms.txt Shows how to add handlers for GET requests at specified paths, including support for path parameters and query parameters. ```APIDOC ## Adding GET Handlers The `api_get()` function adds a handler for GET requests at a specified path with optional serializers and parsers. ```r # Simple GET handler returning JSON pa <- api() |> api_get("/hello", function() { list(message = "Hello, World!") }) # GET handler with path parameters (typed) pa <- api() |> api_get("/user/", function(id) { list(user_id = id, name = paste("User", id)) }) # GET handler with multiple path parameters pa <- api() |> api_get("/user//posts/", function(username, post_id) { list( username = username, post_id = post_id, content = "Post content here" ) }) # GET handler accessing query parameters pa <- api() |> api_get("/search", function(query) { list( search_term = query$q %||% "", page = query$page %||% 1, results = list() ) }) ``` ``` -------------------------------- ### Configure API Logging Source: https://context7.com/posit-dev/plumber2/llms.txt Demonstrates how to configure logging for a Plumber2 API server. It shows examples for using console, file, and null loggers, as well as custom logging within handler functions. ```R # Use console logger (default) pa <- api() | api_logger( logger = logger_console(), access_log_format = combined_log_format ) # Log to file pa <- api() | api_logger( logger = logger_file("api.log"), access_log_format = common_log_format ) # Disable logging pa <- api() | api_logger(logger = logger_null()) # Custom logging in handlers #* @get /action function(server) { server$log("message", "Action endpoint called") server$log("warning", "This is a warning") list(logged = TRUE) } ``` -------------------------------- ### GET /compute Source: https://context7.com/posit-dev/plumber2/llms.txt Demonstrates an asynchronous endpoint for long-running computations. ```APIDOC ## GET /compute ### Description Executes a long-running computation asynchronously to avoid blocking the main API thread. ### Method GET ### Endpoint /compute ### Parameters None ### Request Example GET /compute ### Response #### Success Response (200) - **result** (integer) - The computed value #### Response Example { "result": 42 } ``` -------------------------------- ### GET /complete/ Source: https://context7.com/posit-dev/plumber2/llms.txt Demonstrates how to access various request components including path parameters, query strings, headers, and server objects. ```APIDOC ## GET /complete/ ### Description An example handler showing how to access the full request context, including path parameters, query parameters, headers, and cookies. ### Method GET ### Endpoint /complete/{path_param} ### Parameters #### Path Parameters - **path_param** (string) - Required - A dynamic path segment. ### Request Example GET /complete/example-value?page=2 ### Response #### Success Response (200) - **path_param** (string) - The value from the URL path. - **page** (integer) - The page number from query parameters. - **client** (string) - The unique client identifier. #### Response Example { "path_param": "example-value", "page": 2, "client": "user_123" } ``` -------------------------------- ### Run and Stop Plumber2 API Server Source: https://context7.com/posit-dev/plumber2/llms.txt Manage the lifecycle of a Plumber2 API server. Start the server with specified host, port, and options like blocking execution or opening the browser to documentation. The server can run in the background. Event handlers can be added for 'start' and 'end' events, and existing handlers can be removed. ```r # Create and run an API pa <- api() | api_get("/", function() list(status = "ok")) | api_run( host = "0.0.0.0", port = 8080, block = TRUE, # Block console (FALSE for background) showcase = TRUE # Open browser to docs ) # Run in background (interactive sessions) pa <- api() | api_get("/health", function() list(healthy = TRUE)) | api_run(block = FALSE) # Stop a running server pa |> api_stop() # Add event handlers for lifecycle events pa <- api() | api_on("start", function(server) { server$log("message", "Server started!") }, id = "startup_log") | api_on("end", function(server) { server$log("message", "Server stopped!") }, id = "shutdown_log") # Remove an event handler pa |> api_off("startup_log") ``` -------------------------------- ### Server Lifecycle Management Source: https://context7.com/posit-dev/plumber2/llms.txt Commands to start, stop, and configure lifecycle event handlers for the Plumber2 server. ```APIDOC ## POST /api/run ### Description Starts the Plumber2 server instance with specified host and port configurations. ### Method POST ### Parameters #### Request Body - **host** (string) - Optional - Server host address (default: 0.0.0.0). - **port** (integer) - Optional - Server port (default: 8080). - **block** (boolean) - Optional - Whether to block the console. ### Response #### Success Response (200) - **status** (string) - Server status confirmation. ``` -------------------------------- ### Plumber2 Handler Arguments Reference Source: https://context7.com/posit-dev/plumber2/llms.txt Provides a comprehensive example of a Plumber2 handler function, illustrating how to access various request components like path parameters, query strings, request body, and server objects. It also shows how to modify the response. ```R #* Complete handler example showing all available arguments #* #* @get /complete/ function( path_param, # Path parameters are direct arguments query, # List of query string parameters body, # Parsed request body request, # reqres::Request object response, # reqres::Response object server, # Plumber2 API object client_id # Unique client identifier ) { # Access query parameters page <- query$page %||% 1 # Access request headers auth_header <- request$get_header("Authorization") # Access cookies session_cookie <- request$cookies$session_id # Modify response response$set_header("X-Custom-Header", "value") response$set_cookie("visited", "true", max_age = 3600) # Use server logging server$log("message", paste("Request from", client_id)) # Access server data store cached <- server$get_data("cached_value") list( path_param = path_param, page = page, client = client_id ) } ``` -------------------------------- ### GET /protected Source: https://context7.com/posit-dev/plumber2/llms.txt An endpoint protected by an API key authentication guard. ```APIDOC ## GET /protected ### Description Access to this endpoint requires a valid API key provided in the request headers. ### Method GET ### Endpoint /protected ### Parameters #### Header Parameters - **X-API-Key** (string) - Required - The secret API key for authentication ### Request Example GET /protected Header: X-API-Key: secret ### Response #### Success Response (200) - **secret** (string) - The protected data #### Response Example { "secret": "data" } ``` -------------------------------- ### GET /echo/ Source: https://github.com/posit-dev/plumber2/blob/main/README.md Echoes back a message provided as a path parameter. ```APIDOC ## GET /echo/ ### Description Echoes back the message provided in the URL path. ### Method GET ### Endpoint /echo/ ### Parameters #### Path Parameters - **msg** (string) - Required - The message to echo back. ### Request Example GET /echo/hello ### Response #### Success Response (200) - **msg** (string) - A string containing the input message. #### Response Example { "msg": "The message is: 'hello'" } ``` -------------------------------- ### plumber2 API with Plotting and Content Negotiation Source: https://github.com/posit-dev/plumber2/blob/main/README.md An example of a plumber2 API endpoint that generates a plot from the 'palmerpenguins' dataset. It demonstrates query parameters for filtering, multiple serializers (PNG, JPEG) for content negotiation, and the @async tag for asynchronous handling. ```r #* Plot out data from the palmer penguins dataset #* #* @get /plot #* #* @query spec:enum|Adelie, Chinstrap, Gentoo| If provided, filter the #* data to only this species #* #* @serializer png{width = 700, height = 500} #* @serializer jpeg{width = 700, height = 500} #* #* @async function(query) { myData <- penguins title <- "All Species" # Filter if the species was specified if (!is.null(query$spec)){ title <- paste0("Only the '", query$spec, "' Species") myData <- subset(myData, species == query$spec) if (nrow(myData) == 0) { abort_internal_error("Missing data for {query$spec}") } } plot( myData$flipper_len, myData$bill_len, main=title, xlab="Flipper Length (mm)", ylab="Bill Length (mm)" ) } ``` -------------------------------- ### GET /users/ Source: https://context7.com/posit-dev/plumber2/llms.txt Retrieves user information by ID with custom OpenAPI documentation metadata. ```APIDOC ## GET /users/ ### Description Retrieves a user's information by their unique integer ID. ### Method GET ### Endpoint /users/{id} ### Parameters #### Path Parameters - **id** (integer) - Required - The unique identifier of the user ### Request Example GET /users/1 ### Response #### Success Response (200) - **id** (integer) - User ID - **name** (string) - User name #### Response Example { "id": 1, "name": "John" } ``` -------------------------------- ### GET /get_parsers Source: https://github.com/posit-dev/plumber2/blob/main/tests/testthat/_snaps/parsers.md Retrieves information about registered parsers based on the provided criteria. ```APIDOC ## GET /get_parsers ### Description Retrieves the configuration or details of registered parsers. Throws an error if the requested parser does not exist. ### Method GET ### Endpoint /get_parsers ### Parameters #### Query Parameters - **name** (string) - Optional - The name of the specific parser to retrieve. ### Request Example GET /get_parsers?name=json_custom ### Response #### Success Response (200) - **parser** (object) - The details of the requested parser. #### Error Response (404) - **error** (string) - Error message if the parser is not found. ``` -------------------------------- ### GET /plot Source: https://context7.com/posit-dev/plumber2/llms.txt Returns a graphical plot as a downloadable file using specified serializers. ```APIDOC ## GET /plot ### Description Returns a plot generated by R, serialized as a downloadable image file (png or jpeg). ### Method GET ### Endpoint /plot ### Parameters None ### Request Example GET /plot ### Response #### Success Response (200) - **Content-Type** (string) - image/png or image/jpeg #### Response Example [Binary Image Data] ``` -------------------------------- ### GET /plot Source: https://github.com/posit-dev/plumber2/blob/main/README.md Generates a plot from the palmer penguins dataset with optional filtering by species. ```APIDOC ## GET /plot ### Description Generates a plot of flipper length versus bill length for the palmer penguins dataset. Supports filtering by species and content negotiation for image formats. ### Method GET ### Endpoint /plot ### Parameters #### Query Parameters - **spec** (enum: Adelie, Chinstrap, Gentoo) - Optional - Filter the data to only this species. ### Request Example GET /plot?spec=Adelie ### Response #### Success Response (200) - **image** (binary) - Returns a PNG or JPEG image based on the Accept header. #### Response Example [Binary Image Data] ``` -------------------------------- ### GET /reports/sales Source: https://context7.com/posit-dev/plumber2/llms.txt Generates a sales report based on the provided year and region parameters. ```APIDOC ## GET /reports/sales ### Description Generates a sales report from an RMarkdown file based on query parameters. ### Method GET ### Endpoint /reports/sales ### Parameters #### Query Parameters - **year** (integer) - Required - The fiscal year for the report. - **region** (string) - Optional - The sales region to filter by. ### Request Example GET /reports/sales?year=2023®ion=North ### Response #### Success Response (200) - **report** (binary) - The generated report file content. #### Response Example { "report": "...binary_data..." } ``` -------------------------------- ### Configure API via Annotated R Files Source: https://context7.com/posit-dev/plumber2/llms.txt Demonstrates the declarative approach using #* annotations to define routes, parameters, and documentation directly within R source files. ```R #* Get a greeting message #* @param name:string The name to greet #* @get /hello/ #* @response 200:{message:string} A greeting message function(name) { list(message = paste0("Hello, ", name, "!")) } #* Create a new user #* @body name:string* The user's name #* @body email:string* The user's email address #* @body age:integer(18) The user's age (default 18) #* @post /users #* @serializer json #* @parser json function(body) { list( success = TRUE, user = list( name = body$name, email = body$email, age = body$age ) ) } ``` -------------------------------- ### Initialize Plumber2 API Objects Source: https://context7.com/posit-dev/plumber2/llms.txt Demonstrates how to instantiate a new API object programmatically, including loading from directories and configuring server settings like host, port, and documentation types. ```R library(plumber2) # Create an empty API programmatically pa <- api() # Create an API from a directory containing annotated R files pa <- api(system.file("plumber2", "quickstart", package = "plumber2")) # Create an API with custom settings pa <- api( host = "0.0.0.0", port = 8080, doc_type = "rapidoc", doc_path = "__docs__", ignore_trailing_slash = TRUE, max_request_size = 10 * 1024 * 1024, compression_limit = 1000 ) ``` -------------------------------- ### OpenAPI Object Creation Source: https://github.com/posit-dev/plumber2/blob/main/tests/testthat/_snaps/spec_constructor.md Demonstrates the creation of an OpenAPI object and its associated components, highlighting required parameters and error conditions. ```APIDOC ## POST /openapi ### Description Creates a valid OpenAPI object. ### Method POST ### Endpoint /openapi ### Parameters #### Query Parameters - **info** (openapi_info) - Required - Information about the API. - **paths** (list) - Required - A named list of API paths. ### Request Example ```json { "info": { "title": "My API", "version": "1.0.0" }, "paths": { "/users": { "get": { "summary": "Get a list of users" } } } } ``` ### Response #### Success Response (200) - **openapi_object** (object) - A valid OpenAPI object. #### Response Example ```json { "openapi": "3.0.0", "info": { "title": "My API", "version": "1.0.0" }, "paths": { "/users": { "get": { "summary": "Get a list of users" } } } } ``` ``` ```APIDOC ## POST /openapi_info ### Description Creates a valid OpenAPI info object. ### Method POST ### Endpoint /openapi_info ### Parameters #### Query Parameters - **title** (string) - Required - The title of the API. - **version** (string) - Required - The version of the API. - **description** (string) - Optional - A description of the API. - **termsOfService** (string) - Optional - A URL to the terms of service. - **contact** (object) - Optional - Contact information for the API. - **license** (object) - Optional - Licensing information for the API. ### Request Example ```json { "title": "My API", "version": "1.0.0", "description": "An example API" } ``` ### Response #### Success Response (200) - **info_object** (object) - A valid OpenAPI info object. #### Response Example ```json { "title": "My API", "version": "1.0.0", "description": "An example API" } ``` ``` ```APIDOC ## POST /openapi_license ### Description Creates a valid OpenAPI license object. ### Method POST ### Endpoint /openapi_license ### Parameters #### Query Parameters - **name** (string) - Required - The name of the license. - **url** (string) - Optional - A URL to the license text. ### Request Example ```json { "name": "Apache 2.0", "url": "https://www.apache.org/licenses/LICENSE-2.0.html" } ``` ### Response #### Success Response (200) - **license_object** (object) - A valid OpenAPI license object. #### Response Example ```json { "name": "Apache 2.0", "url": "https://www.apache.org/licenses/LICENSE-2.0.html" } ``` ``` ```APIDOC ## POST /openapi_operation ### Description Creates a valid OpenAPI operation object. ### Method POST ### Endpoint /openapi_operation ### Parameters #### Query Parameters - **summary** (string) - Optional - A short summary of what the operation does. - **description** (string) - Optional - A verbose explanation of the operation. - **operationId** (string) - Optional - Unique identifier for the operation. - **tags** (array) - Optional - A list of tags for grouping operations. - **parameters** (array) - Optional - A list of parameters for the operation. - **requestBody** (object) - Optional - Describes the request body. - **responses** (named list) - Required - A map of response codes to response objects. ### Request Example ```json { "summary": "Get item by ID", "operationId": "getItem", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "format": "int64" } } ], "responses": { "200": { "description": "Item found" } } } ``` ### Response #### Success Response (200) - **operation_object** (object) - A valid OpenAPI operation object. #### Response Example ```json { "summary": "Get item by ID", "operationId": "getItem", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "format": "int64" } } ], "responses": { "200": { "description": "Item found" } } } ``` ``` ```APIDOC ## POST /openapi_parameter ### Description Creates a valid OpenAPI parameter object. ### Method POST ### Endpoint /openapi_parameter ### Parameters #### Query Parameters - **name** (string) - Required - The name of the parameter. - **location** (string) - Required - The location of the parameter (e.g., `query`, `header`, `path`, `cookie`). - **description** (string) - Optional - A description of the parameter. - **required** (boolean) - Optional - Indicates if the parameter is required. Path parameters must be required. - **schema** (object) - Optional - The schema defining the parameter's type. - **content** (object) - Optional - A map of media types to schema objects for request body parameters. ### Request Example ```json { "name": "userId", "in": "path", "required": true, "schema": { "type": "string" } } ``` ### Response #### Success Response (200) - **parameter_object** (object) - A valid OpenAPI parameter object. #### Response Example ```json { "name": "userId", "in": "path", "required": true, "schema": { "type": "string" } } ``` ``` ```APIDOC ## POST /openapi_schema ### Description Creates a valid OpenAPI schema object. ### Method POST ### Endpoint /openapi_schema ### Parameters #### Query Parameters - **x** (any) - Required - The schema definition. Can be a single value, a named list for an object, or an un-named list with a single element. - **required** (array) - Optional - A list of required fields for object schemas. ### Request Example ```json { "type": "object", "properties": { "field1": { "type": "string" }, "field2": { "type": "integer" } }, "required": ["field1"] } ``` ### Response #### Success Response (200) - **schema_object** (object) - A valid OpenAPI schema object. #### Response Example ```json { "type": "object", "properties": { "field1": { "type": "string" }, "field2": { "type": "integer" } }, "required": ["field1"] } ``` ``` ```APIDOC ## POST /openapi_content ### Description Creates a valid OpenAPI content object, mapping media types to schema objects. ### Method POST ### Endpoint /openapi_content ### Parameters #### Query Parameters - **...** (named list) - Required - A named list where keys are MIME types (e.g., `application/json`) and values are OpenAPI schema objects. ### Request Example ```json { "application/json": { "type": "object", "properties": { "message": { "type": "string" } } } } ``` ### Response #### Success Response (200) - **content_object** (object) - A valid OpenAPI content object. #### Response Example ```json { "application/json": { "type": "object", "properties": { "message": { "type": "string" } } } } ``` ``` ```APIDOC ## POST /openapi_request_body ### Description Creates a valid OpenAPI request body object. ### Method POST ### Endpoint /openapi_request_body ### Parameters #### Query Parameters - **description** (string) - Optional - A brief description of the request body. - **content** (named list) - Required - A map of media types to schema objects. - **required** (boolean) - Optional - Indicates if the request body is required. ### Request Example ```json { "description": "User data to create", "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "name": { "type": "string" }, "email": { "type": "string" } } } } } } ``` ### Response #### Success Response (200) - **request_body_object** (object) - A valid OpenAPI request body object. #### Response Example ```json { "description": "User data to create", "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "name": { "type": "string" }, "email": { "type": "string" } } } } } } ``` ``` ```APIDOC ## POST /openapi_response ### Description Creates a valid OpenAPI response object. ### Method POST ### Endpoint /openapi_response ### Parameters #### Query Parameters - **description** (string) - Required - A description of the response. - **headers** (named list) - Optional - A map of headers to their definitions. - **content** (named list) - Optional - A map of media types to schema objects for the response body. ### Request Example ```json { "description": "Successfully created resource", "content": { "application/json": { "schema": { "type": "object", "properties": { "id": { "type": "string" } } } } } } ``` ### Response #### Success Response (200) - **response_object** (object) - A valid OpenAPI response object. #### Response Example ```json { "description": "Successfully created resource", "content": { "application/json": { "schema": { "type": "object", "properties": { "id": { "type": "string" } } } } } } ``` ``` ```APIDOC ## POST /openapi_tag ### Description Creates a valid OpenAPI tag object. ### Method POST ### Endpoint /openapi_tag ### Parameters #### Query Parameters - **name** (string) - Required - The name of the tag. - **description** (string) - Optional - A description of the tag. ### Request Example ```json { "name": "users", "description": "Operations related to user management" } ``` ### Response #### Success Response (200) - **tag_object** (object) - A valid OpenAPI tag object. #### Response Example ```json { "name": "users", "description": "Operations related to user management" } ``` ``` -------------------------------- ### Creating an API Source: https://context7.com/posit-dev/plumber2/llms.txt Demonstrates how to create a new Plumber2 API object, either programmatically or by parsing annotated R files. ```APIDOC ## Creating an API The `api()` function creates a new Plumber2 API object, optionally parsing annotated R files or directories. ```r library(plumber2) # Create an empty API programmatically pa <- api() # Create an API from a directory containing annotated R files pa <- api(system.file("plumber2", "quickstart", package = "plumber2")) # Create an API with custom settings pa <- api( host = "0.0.0.0", port = 8080, doc_type = "rapidoc", # "rapidoc", "redoc", "swagger", or NULL doc_path = "__docs__", ignore_trailing_slash = TRUE, max_request_size = 10 * 1024 * 1024, # 10MB limit compression_limit = 1000 ) ``` ``` -------------------------------- ### Plumber dots_to_plumber_files Warning and Output Source: https://github.com/posit-dev/plumber2/blob/main/tests/testthat/_snaps/api.md Shows scenarios where dots_to_plumber_files issues warnings, such as ignoring '_server.yml' files when other files are also provided, or when prefer_yml is set to FALSE. It also demonstrates the expected output in these cases. ```R dots_to_plumber_files("fixtures/server1/_server.yml", prefer_yml = FALSE) # Condition: # Warning: # Ignoring '_server.yml' files in `...` # Output: # character(0) ``` ```R dots_to_plumber_files("fixtures/server1/_server.yml", "fixtures/minimal_api.R") # Condition: # Warning: # '_server.yml' found. Ignoring all other files provided in `...` # Output: # [1] "fixtures/server1/_server.yml" ``` -------------------------------- ### Configure Authentication Guards and Flows Source: https://context7.com/posit-dev/plumber2/llms.txt Explains how to secure API endpoints using API keys or basic authentication guards, and how to combine them into complex logical flows. ```r pa <- api() |> api_datastore(storr::driver_environment()) |> api_auth_guard( fireproof::guard_key(key_name = "X-API-Key", validate = "secret"), name = "key" ) |> api_get( "/protected", function() { list(secret = "data") }, auth_flow = key ) #* @get /secure/ #* @auth api_key || basic_auth #* @authScope read, write function(id) { get_secure_data(id) } ``` -------------------------------- ### Generate OpenAPI Documentation Source: https://context7.com/posit-dev/plumber2/llms.txt Details how to configure documentation UI settings, add global API metadata, and define detailed endpoint-level OpenAPI specifications. ```r pa <- api() |> api_doc_setting(doc_type = "swagger", doc_path = "/api-docs") pa <- api() |> api_get( "/users/", function(id) { list(id = id, name = "John") }, doc = openapi_operation( summary = "Get user by ID", parameters = list(openapi_parameter(name = "id", location = "path", required = TRUE, schema = openapi_schema(integer()))) ) ) ``` -------------------------------- ### Manage Serializers and Parsers Source: https://context7.com/posit-dev/plumber2/llms.txt Explains how to retrieve and configure serializers and parsers for transforming request/response data formats. ```R serializers <- get_serializers() json_xml <- get_serializers(c("json", "xml")) image_serializers <- get_serializers(c("png", "jpeg", "svg")) ``` -------------------------------- ### Serve Static Files with Plumber2 Source: https://context7.com/posit-dev/plumber2/llms.txt Configure Plumber2 to serve static assets either through R handlers (allowing middleware) or directly via httpuv for improved performance. Supports specifying mount points, directory paths, default files, and extensions. Can also exclude specific paths from being served. ```r # Serve static assets through R (allows middleware processing) pa <- api() | api_assets( at = "/static", path = "./public", default_file = "index.html", default_ext = "html" ) # Serve static files directly (faster, bypasses R) pa <- api() | api_statics( at = "/files", path = "./static-files", except = c("/files/private") # Exclude certain paths ) # Using annotations #* @assets ./public /static NULL #* @statics ./static-files /files #* @except /private NULL ``` -------------------------------- ### Define API Endpoints with Custom Serializers Source: https://context7.com/posit-dev/plumber2/llms.txt Demonstrates how to define API endpoints using programmatic syntax, including returning plots with specific serializers and applying custom JSON formatting options. ```r pa <- api() |> api_get( "/plot", function() { plot(1:10, (1:10)^2, main = "Square function") }, serializers = get_serializers(c("png", "jpeg")), download = TRUE ) pa <- api() |> api_get( "/data", function() { list(value = 42, nested = list(a = 1, b = 2)) }, serializers = list( "application/json" = format_unboxed() ) ) ``` -------------------------------- ### Using Annotated R Files Source: https://context7.com/posit-dev/plumber2/llms.txt Explains how to use specially annotated R files to define API endpoints, including path parameters, query parameters, request bodies, and responses. ```APIDOC ## Using Annotated R Files Plumber2 parses specially annotated R files to create API endpoints. Place annotations in comments starting with `#*`. ```r # File: api.R #* Get a greeting message #* #* @param name:string The name to greet #* #* @get /hello/ #* #* @response 200:{message:string} A greeting message #* function(name) { list(message = paste0("Hello, ", name, "!")) } #* Create a new user #* #* @body name:string* The user's name #* @body email:string* The user's email address #* @body age:integer(18) The user's age (default 18) #* #* @post /users #* #* @serializer json #* @parser json #* function(body) { list( success = TRUE, user = list( name = body$name, email = body$email, age = body$age ) ) } #* Search for items #* #* @query q:string* The search query #* @query limit:integer(10) Maximum results to return #* @query offset:integer(0) Results offset for pagination #* #* @get /search #* function(query) { list( query = query$q, limit = query$limit, offset = query$offset, results = list() ) } ``` ``` -------------------------------- ### Adding POST Handlers Source: https://context7.com/posit-dev/plumber2/llms.txt Illustrates how to add handlers for POST requests, including receiving data in the request body and specifying custom parsers and serializers. ```APIDOC ## Adding POST Handlers The `api_post()` function adds handlers for POST requests, typically used to receive data in the request body. ```r # POST handler receiving JSON body pa <- api() |> api_post("/users", function(body) { list( created = TRUE, user = list( name = body$name, email = body$email ) ) }) # POST handler with specific parsers pa <- api() |> api_post( "/upload", function(body) { list(received = length(body$file)) }, parsers = get_parsers("multi") # multipart/form-data parser ) # POST handler with custom serializer pa <- api() |> api_post( "/data", function(body) { data.frame(x = body$values, y = body$values^2) }, serializers = get_serializers(c("json", "csv")) ) ``` ``` -------------------------------- ### Define POST Request Handlers Source: https://context7.com/posit-dev/plumber2/llms.txt Illustrates handling POST requests with body parsing, multipart form data, and custom response serializers. ```R pa <- api() |> api_post("/users", function(body) { list( created = TRUE, user = list( name = body$name, email = body$email ) ) }) pa <- api() |> api_post( "/upload", function(body) { list(received = length(body$file)) }, parsers = get_parsers("multi") ) pa <- api() |> api_post( "/data", function(body) { data.frame(x = body$values, y = body$values^2) }, serializers = get_serializers(c("json", "csv")) ) ``` -------------------------------- ### Static File Serving Source: https://context7.com/posit-dev/plumber2/llms.txt Endpoints and methods for serving static assets either through R handlers for middleware processing or directly via httpuv for performance. ```APIDOC ## GET /static/* ### Description Serves static files from a local directory through R handlers, allowing for custom middleware processing. ### Method GET ### Endpoint /static/* ### Parameters #### Path Parameters - **at** (string) - Required - The URL mount point. - **path** (string) - Required - The local directory path. ### Response #### Success Response (200) - **file** (binary) - The requested static file content. ``` -------------------------------- ### Implement Asynchronous Request Handling Source: https://context7.com/posit-dev/plumber2/llms.txt Shows how to handle long-running operations in Plumber2 using the @async annotation or programmatic configuration with mirai evaluators and post-processing chains. ```r #* @get /compute #* @async function() { Sys.sleep(2) list(result = 42) } pa <- api() |> api_get( "/slow-operation", function() { Sys.sleep(3) list(status = "complete", data = rnorm(100)) }, async = TRUE ) pa <- api() |> api_get( "/process", function() { heavy_computation() }, async = TRUE, then = list( function(result, response, server) { server$log("message", "Processing complete") response$set_header("X-Processing-Time", "3s") Next } ) ) ``` -------------------------------- ### Serve Reports with Plumber2 Source: https://context7.com/posit-dev/plumber2/llms.txt Configure Plumber2 to serve dynamic reports generated by Quarto or RMarkdown. The `api_report` function allows specifying the report file path, caching options (max age, cache by ID), and asynchronous rendering to improve performance and user experience. ```r # Serve a Quarto/RMarkdown report pa <- api() | api_report( path = "/reports/quarterly", report = "reports/quarterly.qmd", max_age = 3600, # Cache for 1 hour async = TRUE, # Render asynchronously cache_by_id = TRUE # Cache per user ) ``` -------------------------------- ### Plumber API Constructor Error Handling Source: https://github.com/posit-dev/plumber2/blob/main/tests/testthat/_snaps/api.md Demonstrates how the Plumber API function handles errors when a 'constructor' object is not found. This is crucial for ensuring robust API initialization. ```R api(server_yml) # Condition: # Error: # ! object 'constructor' not found ``` -------------------------------- ### Configure Redirects and Reverse Proxy in Plumber2 Source: https://context7.com/posit-dev/plumber2/llms.txt Set up URL redirects and reverse proxy forwarding for API requests. Supports permanent (308) and temporary (307) redirects, specifying methods, source paths, and destination paths. Reverse proxy can forward requests to external URLs, with options to exclude specific paths from forwarding. ```r # Add a permanent redirect pa <- api() | api_redirect( method = "get", from = "/old-path/", to = "/new-path/", permanent = TRUE # 308 Permanent Redirect ) # Add a temporary redirect pa <- api() | api_redirect("any", "/temp/*", "/stable/*", permanent = FALSE) # 307 # Set up reverse proxy to forward requests pa <- api() | api_forward( path = "/external-api", url = "https://api.example.com", except = c("/external-api/health") # Don't forward health checks ) # Using annotations #* @redirect !get /v1/* /v2/* #* @redirect any /legacy /modern NULL #* @forward /proxy http://127.0.0.1:3000 NULL ``` -------------------------------- ### Retrieve Registered Parsers Source: https://github.com/posit-dev/plumber2/blob/main/tests/testthat/_snaps/parsers.md Demonstrates error handling when retrieving parsers. It validates that the requested parser exists and that reserved keywords are not used improperly in the retrieval list. ```R get_parsers("nonexistent") get_parsers(list(c("...", "..."))) ``` -------------------------------- ### Validate OpenAPI Info and License Objects Source: https://github.com/posit-dev/plumber2/blob/main/tests/testthat/_snaps/spec_constructor.md Shows the mandatory fields for info and license objects, specifically requiring title/version for info and a name for license. ```R openapi_info() openapi_license(url = "https://example.com") ``` -------------------------------- ### Validate OpenAPI Object Construction Source: https://github.com/posit-dev/plumber2/blob/main/tests/testthat/_snaps/spec_constructor.md Demonstrates the validation requirements for the openapi() function, which requires a named list for paths and specific info objects. ```R openapi(info = openapi_info(title = "Test", version = "1.0.0"), paths = "invalid") openapi() ``` -------------------------------- ### Define API Report with Parameters Source: https://context7.com/posit-dev/plumber2/llms.txt Configures an API endpoint to serve a report with query parameters for year and region. It uses Plumber2's declarative syntax for defining OpenAPI documentation, including parameter types and requirements. ```R pa <- api() | api_report( path = "/reports/sales", report = "reports/sales.Rmd", doc = openapi_operation( parameters = list( openapi_parameter( name = "year", location = "query", required = TRUE, schema = openapi_schema(integer()) ), openapi_parameter( name = "region", location = "query", schema = openapi_schema(character()) ) ) ) ) ``` -------------------------------- ### Display Plumber2 Server Info (R) Source: https://github.com/posit-dev/plumber2/blob/main/tests/testthat/_snaps/Plumber2.md The pa$format() function in Plumber2 is used to display information about the Plumber server. It shows the server's address and its current running status. This function is useful for monitoring the server's state. ```R pa$format() ``` -------------------------------- ### Serializers and Parsers Source: https://context7.com/posit-dev/plumber2/llms.txt Details on how to use serializers to convert R objects to response formats and parsers to convert request bodies to R objects. ```APIDOC ## Serializers and Parsers Serializers convert R objects to response formats; parsers convert request bodies to R objects. ```r # Get default serializers (JSON, HTML, XML, text, etc.) serializers <- get_serializers() # Get specific serializers json_xml <- get_serializers(c("json", "xml")) # Get graphics serializers for plot output image_serializers <- get_serializers(c("png", "jpeg", "svg")) ``` ``` -------------------------------- ### Validate Device Formatter Requirements Source: https://github.com/posit-dev/plumber2/blob/main/tests/testthat/_snaps/serializers.md Ensures that a device formatter is correctly initialized by verifying that the provided device object contains a function with the required filename or file argument. ```R device_formatter(bad_device) ``` -------------------------------- ### WebSocket Message Handling Source: https://context7.com/posit-dev/plumber2/llms.txt Configuring real-time bidirectional communication using WebSocket message handlers. ```APIDOC ## WS /message ### Description Registers a handler for incoming WebSocket messages to enable real-time interaction. ### Method WS ### Parameters #### Request Body - **message** (any) - Required - The incoming message payload. - **client_id** (string) - Required - Unique identifier for the connected client. ### Response #### Success Response (200) - **response** (any) - Optional - The message to send back to the client. ``` -------------------------------- ### Redirects and Reverse Proxy Source: https://context7.com/posit-dev/plumber2/llms.txt Configuring URL redirects and reverse proxy forwarding for API requests. ```APIDOC ## ANY /redirect ### Description Sets up permanent or temporary redirects for specific URL patterns. ### Method ANY ### Parameters #### Request Body - **from** (string) - Required - Source path pattern. - **to** (string) - Required - Destination path. - **permanent** (boolean) - Optional - Whether to use 308 (permanent) or 307 (temporary) redirect. ``` -------------------------------- ### Validate OpenAPI Schema and Content Objects Source: https://github.com/posit-dev/plumber2/blob/main/tests/testthat/_snaps/spec_constructor.md Details constraints for schema definitions and content types, ensuring correct list structures and mime-type naming conventions. ```R openapi_schema(list(1, "test")) openapi_schema(list(field1 = 1), required = c("field2")) openapi_content(invalid_name = openapi_schema(character())) ``` -------------------------------- ### Handle WebSocket Messages in Plumber2 Source: https://context7.com/posit-dev/plumber2/llms.txt Implement WebSocket message handling for real-time communication. Supports synchronous and asynchronous message processing. Handlers can log messages, send responses back to clients, and perform actions based on message content. Asynchronous handlers can define a callback function for post-processing. ```r # Add a WebSocket message handler pa <- api() | api_message(function(message, client_id, server) { if (is.character(message)) { server$log("message", paste(client_id, "says:", message)) # Return a message to send back to the client if (message == "ping") { return("pong") } } NULL # No response }) # Async WebSocket handler pa <- api() | api_message( function(message) { # Process message asynchronously process_message(message) }, async = TRUE, then = list( function(result, server, client_id) { server$log("message", "Processed message from " %+% client_id) } ) ) # Using annotations #* @message function(message, client_id, server) { if (message == "subscribe") { return(jsonlite::toJSON(list(status = "subscribed"))) } NULL } ```