Bring data into Shiny on the same port 🚀
Seamlessly integrate POST requests and query parameters into your existing Shiny apps as reactive values. Zero configuration - works with your current UI on the same port.
- 🔌 Same-port integration - No need for separate servers or ports
- 📡 RESTful API endpoints - Accept POST requests alongside your Shiny UI
- 🔄 Reactive data streams - POST data automatically becomes reactive values
- 🛡️ Built-in authentication - Token-based security for your endpoints
- 📱 Multiple data formats - JSON, form data, query parameters
- 🌐 Cross-session sharing - Data shared across all connected clients
- 🚦 Production ready - Comprehensive testing and CRAN-quality code
# Install from CRAN (when available)
install.packages("shinypayload")
# Install development version from GitHub
remotes::install_github("PawanRamaMali/shinypayload")
# For local development
devtools::load_all()
library(shiny)
library(shinypayload)
# Your regular UI - no changes needed!
base_ui <- fluidPage(
titlePanel("🚀 shinypayload Demo"),
fluidRow(
column(6,
h4("📊 Live Data"),
verbatimTextOutput("live_data")
),
column(6,
h4("🔗 URL Parameters"),
verbatimTextOutput("url_params")
)
),
hr(),
h4("📡 POST Endpoint"),
verbatimTextOutput("endpoint_info")
)
# Wrap your UI to handle POST requests
ui <- payload_ui(
base_ui,
path = "/api/data",
token = Sys.getenv("API_TOKEN", "demo-token")
)
server <- function(input, output, session) {
# Get URL parameters
output$url_params <- renderPrint({
params <- params_get(session)
if (length(params) > 0) params else "No URL parameters"
})
# Show endpoint URL
output$endpoint_info <- renderText({
url <- payload_endpoint_url(session, "/api/data")
paste("Send POST requests to:", url, "?token=demo-token")
})
# React to incoming POST data
live_data <- payload_last("/api/data", session, intervalMillis = 200)
output$live_data <- renderPrint({
data <- live_data()
if (is.null(data)) {
"Waiting for data... 📡"
} else {
list(
timestamp = data$meta$timestamp,
payload = data$payload,
source = data$meta$remote_addr
)
}
})
}
# IMPORTANT: Use uiPattern = ".*" for POST routing
shinyApp(ui, server, uiPattern = ".*")
# Send JSON data
curl -X POST "http://localhost:3838/api/data?token=demo-token" \\
-H "Content-Type: application/json" \\
-d '{"sensor": "temperature", "value": 23.5, "unit": "celsius"}'
# Send form data
curl -X POST "http://localhost:3838/api/data?token=demo-token" \\
-d "name=sensor01&status=active&reading=42"
# Response: {"ok": true}
Function | Purpose | Example |
---|---|---|
payload_ui() |
Wrap UI to handle POST requests | payload_ui(my_ui, "/api", "token") |
payload_last() |
Get reactive with latest POST data | data <- payload_last("/api", session) |
params_get() |
Extract URL query parameters | params <- params_get(session) |
payload_endpoint_url() |
Get full endpoint URL | url <- payload_endpoint_url(session, "/api") |
# Query parameter (recommended)
POST /api/data?token=your-secret-token
# HTTP Headers
POST /api/data
X-Ingress-Token: your-secret-token
# OR
Authorization: your-secret-token
application/json
- Parsed withjsonlite::fromJSON()
application/x-www-form-urlencoded
- Parsed withshiny::parseQueryString()
- Fallback: Attempts JSON parsing, returns raw text if failed
- IoT sensor data streaming
- Live monitoring systems
- Real-time analytics
- Webhook receivers
- External service integration
- Microservice communication
- React/Vue.js → Shiny data flow
- Progressive web apps
- Cross-platform integration
- Data ingestion endpoints
- Batch processing triggers
- Workflow automation
Explore our comprehensive examples in inst/examples/
:
basic_example.R
- Core functionality demoreal_time_monitor.R
- Live data monitoringform_handler.R
- Form submission processingexisting_app_integration.R
- Add to existing apps
Each example includes ready-to-run code and curl commands for testing.
-
Always use tokens in production
ui <- payload_ui(base_ui, "/api", Sys.getenv("API_SECRET"))
-
Validate and sanitize input data
observeEvent(payload_last("/api", session), { data <- payload_last("/api", session)() if (!is.null(data)) { # Validate required fields if (is.null(data$payload$user_id)) return() # Sanitize inputs before use clean_data <- DBI::dbQuoteString(pool, data$payload$message) } })
-
Use HTTPS in production
-
Implement rate limiting if needed
-
Monitor and log API usage
# Handle different data types on different paths
ui <- payload_ui(base_ui, "/sensors", "sensor-token")
server <- function(input, output, session) {
# Different reactives for different endpoints
sensor_data <- payload_last("/sensors", session)
user_data <- payload_last("/users", session)
# Process accordingly...
}
# High-frequency updates (100ms)
fast_data <- payload_last("/live", session, intervalMillis = 100)
# Low-frequency updates (5 seconds)
slow_data <- payload_last("/batch", session, intervalMillis = 5000)
We welcome contributions! Please see our Contributing Guidelines for details.
# Clone and install dependencies
git clone https://github.com/PawanRamaMali/shinypayload.git
cd shinypayload
# Install in development mode
devtools::load_all()
# Run tests
devtools::test()
# Check package
devtools::check()
- ✅ 132 tests with comprehensive coverage
- ✅ Cross-platform compatibility (Windows, macOS, Linux)
- ✅ Multiple R versions supported (R ≥ 4.1)
- ✅ CRAN ready - passes all checks
- ✅ Production tested - used in real applications
- R ≥ 4.1
- shiny ≥ 1.7.4
- jsonlite (any version)
This project is licensed under the MIT License - see the LICENSE file for details.
- Built on the amazing Shiny framework
- Inspired by the need for seamless data integration in web applications
- Thanks to the R community for feedback and contributions
- 📖 Documentation: Package website
- 🐛 Bug reports: GitHub Issues
- 💬 Questions: GitHub Issues
- 📧 Email: prm@outlook.in
Made with ❤️ for the R and Shiny community