- Notifications
You must be signed in to change notification settings - Fork1
Bring data into Shiny on the same port
License
Unknown, MIT licenses found
Licenses found
PawanRamaMali/shinypayload
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
Bring datainto Shiny on the same port 🚀
Seamlessly integratePOST requests andquery parameters into your existing Shiny apps asreactive 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 CRANinstall.packages("shinypayload")# Install development version from GitHubremotes::install_github("PawanRamaMali/shinypayload")# For local developmentdevtools::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 requestsui<- payload_ui(base_ui,path="/api/data",token= Sys.getenv("API_TOKEN","demo-token"))server<-function(input,output,session) {# Get URL parametersoutput$url_params<- renderPrint({params<- params_get(session)if (length(params)>0)paramselse"No URL parameters" })# Show endpoint URLoutput$endpoint_info<- renderText({url<- payload_endpoint_url(session,"/api/data") paste("Send POST requests to:",url,"?token=demo-token") })# React to incoming POST datalive_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 routingshinyApp(ui,server,uiPattern=".*")
# Send JSON datacurl -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 datacurl -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 HeadersPOST/api/dataX-Ingress-Token:your-secret-token# ORAuthorization: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 ininst/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 fieldsif (is.null(data$payload$user_id))return()# Sanitize inputs before useclean_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 pathsui<- payload_ui(base_ui,"/sensors","sensor-token")server<-function(input,output,session) {# Different reactives for different endpointssensor_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 ourContributing Guidelines for details.
# Clone and install dependenciesgitclonehttps://github.com/PawanRamaMali/shinypayload.gitcdshinypayload# Install in development modedevtools::load_all()# Run testsdevtools::test()# Check packagedevtools::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 theMIT License - see the LICENSE file for details.
- Built on the amazingShiny 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
About
Bring data into Shiny on the same port
Resources
License
Unknown, MIT licenses found
Licenses found
Contributing
Uh oh!
There was an error while loading.Please reload this page.
