### Verify Silly Installation Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/getting-started.md Checks if the Silly framework has been successfully installed by displaying its version information. ```bash # Check executable ./silly --version ``` -------------------------------- ### Create and Run a 'Hello World' Program in Silly Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/getting-started.md Demonstrates how to create a simple Lua program that uses the Silly framework and then runs it. ```lua -- Import silly core module local silly = require "silly" print("Hello, Silly!") print("Current process ID:", silly.pid) print("Framework version:", silly.version) -- Exit program silly.exit(0) ``` ```bash ./silly hello.lua ``` -------------------------------- ### Install Dependencies on CentOS/RHEL Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/getting-started.md Installs essential build tools and libraries for Silly on CentOS or RHEL-based systems. Requires root privileges. ```shell sudo yum groupinstall "Development Tools" sudo yum install -y git openssl-devel ``` -------------------------------- ### Install Dependencies on Ubuntu/Debian Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/getting-started.md Installs essential build tools and libraries for Silly on Ubuntu or Debian-based systems. Requires root privileges. ```shell sudo apt-get update sudo apt-get install -y build-essential git libssl-dev ``` -------------------------------- ### Start Basic Console Server (Lua) Source: https://github.com/findstr/silly/blob/master/docs/src/en/reference/console.md This example demonstrates how to start the silly.console server with a basic configuration, listening on a specified address and port. It requires the 'silly.console' module. ```lua local console = require "silly.console" console({ addr = "127.0.0.1:8888" }) print("Console started on 127.0.0.1:8888") ``` -------------------------------- ### Run Silly Application Instances (Bash) Source: https://github.com/findstr/silly/blob/master/docs/src/en/guides/http-best-practices.md This command sequence demonstrates how to manually start individual instances of the Silly application, each listening on a specific port. This is useful for testing or simple load-balanced setups where automated scripting is not required. ```bash ./silly main.lua --port=8080 ./silly main.lua --port=8081 ./silly main.lua --port=8082 ./silly main.lua --port=8083 ``` -------------------------------- ### Initialize Git Submodules Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/getting-started.md Initializes and updates git submodules if they were not cloned recursively. ```bash git submodule update --init --recursive ``` -------------------------------- ### Silly Application Server Setup and Request Handling Source: https://github.com/findstr/silly/blob/master/docs/src/en/guides/logging-monitoring.md This Lua code snippet demonstrates the setup of an HTTP server in a Silly application. It includes request handling, error management, and metrics recording for response size, request duration, and total requests. It also logs request details and application startup information. ```lua stream:respond(status_code, {["content-type"] = "application/json"}) stream:closewrite(response_body) end -- Record metrics local duration = os.clock() - start http_requests_in_flight:dec() http_response_size:observe(#response_body) http_request_duration:labels(stream.method, stream.path):observe(duration) http_requests_total:labels(stream.method, stream.path, tostring(status_code)):inc() -- Record log log_request(trace_id, stream.method, stream.path, status_code, duration, req_size, #response_body) end -- ========== Start Service ========== local server = http.listen { addr = "0.0.0.0:8080", handler = function(stream) local ok, err = silly.pcall(handle_request, stream) if not ok then silly.tracespawn() -- Create new trace ID logger.error("Request handling failed:", err) stream:respond(500, {["content-type"] = "application/json"}) stream:closewrite(json.encode({error = "Internal Server Error"})) http_requests_total:labels(stream.method, stream.path, "500"):inc() end end } logger.info("========================================") logger.info("Application started successfully") logger.infof("API Service: http://localhost:8080/api/users") logger.infof("Health Check: http://localhost:8080/health") logger.infof("Monitoring Metrics: http://localhost:8080/metrics") logger.info("========================================") logger.info("Signal Controls:") logger.info(" kill -USR1 # Reopen log file") logger.info(" kill -USR2 # Toggle log level (INFO <-> DEBUG)") logger.info("========================================") ``` -------------------------------- ### Start TLS Server Listener Source: https://github.com/findstr/silly/blob/master/docs/src/en/reference/net/tls.md This example demonstrates how to start a TLS server that listens on a specified address. It includes configuration for certificates and an accept function to handle incoming connections. The `tls.listen` function returns a listener file descriptor on success or nil and an error message on failure. Dependencies include silly, silly.task, and silly.net.tls. ```lua local silly = require "silly" local task = require "silly.task" local tls = require "silly.net.tls" task.fork(function() local listener = tls.listen { certs = {{ cert = "-----BEGIN CERTIFICATE-----\n...", key = "-----BEGIN PRIVATE KEY-----\n...", }}, accept = function(conn) conn:write("Goodbye!\n") local ok, err = conn:close() if not ok then print("Close failed:", err) end end } end) ``` -------------------------------- ### Clone Silly Repository Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/getting-started.md Clones the Silly framework repository, including all necessary submodules, and navigates into the project directory. ```bash # Clone repository (including submodules) git clone --recursive https://github.com/findstr/silly.git cd silly ``` -------------------------------- ### Server Startup Configuration with Silly Source: https://github.com/findstr/silly/blob/master/docs/src/en/reference/env.md A practical example of using the silly.env module to load server configuration and then use that configuration to start an HTTP server. It demonstrates loading settings like port and workers, converting them to numbers, and passing them to the http.listen function. ```lua local env = require "silly.env" local http = require "silly.net.http" env.load("config.lua") local port = tonumber(env.get("server.port")) or 8080 local workers = tonumber(env.get("server.workers")) or 1 http.listen { addr = "0.0.0.0:" .. port, handler = function(stream) stream:respond(200, {["content-type"] = "text/plain"}) stream:closewrite("Hello!") end } print(string.format("HTTP server started on port %d with %d workers", port, workers)) ``` -------------------------------- ### Start HTTP Server with Listen in Lua Source: https://github.com/findstr/silly/blob/master/docs/src/en/reference/net/http.md This example shows how to start an HTTP server using `http.listen`. It configures the server to listen on a specific address and port, and defines a handler function to process incoming requests. The handler responds with 'Hello, World!' and closes the connection. ```lua local silly = require "silly" local task = require "silly.task" local http = require "silly.net.http" task.fork(function() local server, err = http.listen { addr = "127.0.0.1:8080", handler = function(stream) stream:respond(200, { ["content-type"] = "text/plain", ["content-length"] = #"Hello, World!", }) stream:closewrite("Hello, World!") end } if not server then print("Server start failed:", err) return end print("HTTP server listening on 127.0.0.1:8080") end) ``` -------------------------------- ### Start TCP Server with tcp.listen Source: https://github.com/findstr/silly/blob/master/docs/src/en/reference/net/tcp.md This example shows how to start a TCP server using `tcp.listen`. It configures the listening address and provides an asynchronous callback function (`accept`) to handle new client connections. Error handling for listen failures is included. ```lua local tcp = require "silly.net.tcp" local listener, err = tcp.listen { addr = "127.0.0.1:8080", accept = function(conn) print("New connection from:", conn.remoteaddr) -- Handle connection... conn:close() end } if not listener then print("Listen failed:", err) end ``` -------------------------------- ### Running Examples Source: https://github.com/findstr/silly/blob/master/CLAUDE.md Instructions on how to run the example scripts provided with the Silly project, including examples for TCP echo servers and HTTP servers, and how to access custom arguments. ```APIDOC ## Running Examples ### Example Commands ```bash # Basic TCP echo server ./silly examples/tcp_echo.lua # HTTP server on port 8080 ./silly examples/http_server.lua --port=8080 ``` ### Accessing Custom Arguments Custom command-line arguments can be accessed within the Lua scripts using the `silly.env` module. ```lua local env = require "silly.env" local port = env.get("port") -- Retrieves the value of the --port argument, e.g., "8080" ``` ``` -------------------------------- ### Install MySQL on Ubuntu/Debian Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/database-app.md Installs the MySQL server on Ubuntu or Debian-based systems using apt-get. This is a prerequisite for database operations. ```bash sudo apt-get update sudo apt-get install mysql-server sudo systemctl start mysql ``` -------------------------------- ### Install Dependencies on macOS Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/getting-started.md Installs necessary tools for Silly on macOS, including Xcode Command Line Tools. OpenSSL can be optionally installed via Homebrew. ```shell # Install Xcode Command Line Tools xcode-select --install # Install OpenSSL (optional) brew install openssl ``` -------------------------------- ### Running and Testing Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/echo-server.md Instructions on how to start the echo server, test it using telnet, and use the provided client code for testing. ```APIDOC ## Running and Testing ### Start the Server ```bash cd /path/to/silly ./silly echo-server.lua ``` You will see output similar to: ``` Accept connection 4 127.0.0.1:xxxxx Client 1 connected, fd: 5 Send [fd: 5] -> AbCdE Receive [fd: 5] -> AbCdE Accept connection 6 127.0.0.1:xxxxx Client 2 connected, fd: 7 ... ``` ### Testing with telnet While the server is running, open another terminal: ```bash telnet 127.0.0.1 9999 ``` Then type any text and press Enter: ``` Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. Hello Silly! Hello Silly! This is a test This is a test ``` The server will immediately echo what you typed. ### Testing with Client Code The complete code above already includes test clients. When running, it will automatically create 3 clients, each sending 5 messages. If you want to write a separate client: ```lua local silly = require "silly" local task = require "silly.task" local socket = require "silly.net.tcp" task.fork(function() -- Connect to server local conn, err = socket.connect("127.0.0.1:9999") if not conn then print("Connect failed:", err) return end print("Connected to server:", conn.remoteaddr) -- Send message conn:write("Hello from client\n") -- Receive echo local msg, rerr = conn:read("\n") if msg then print("Received echo:", msg) else print("Receive failed:", rerr) end -- Close connection conn:close() end) ``` ``` -------------------------------- ### Install Redis on macOS Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/database-app.md Installs Redis on macOS using Homebrew. This sets up the Redis server, which will be used for caching in the tutorial. ```bash brew install redis brew services start redis ``` -------------------------------- ### Silly Coroutine Style Example Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/getting-started.md Illustrates Silly's coroutine-based asynchronous programming model for network operations, contrasting it with a traditional callback style. ```lua -- Silly's coroutine approach local tcp = require "silly.net.tcp" local task = require "silly.task" task.fork(function() local conn = tcp.connect("127.0.0.1:8080") local data1 = conn:read(1024) conn:write(data1) local data2 = conn:read(1024) conn:write(data2) conn:close() end) ``` -------------------------------- ### Install MySQL on macOS Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/database-app.md Installs the MySQL server on macOS using Homebrew. This command is used to set up the database environment for the tutorial. ```bash brew install mysql brew services start mysql ``` -------------------------------- ### Main Application: Setup and Server Initialization in Lua Source: https://github.com/findstr/silly/blob/master/docs/src/en/guides/http-best-practices.md This Lua code sets up the main application by requiring necessary modules (silly, http, and route modules) and defining the routing table. It then starts an HTTP server listening on port 8080, handling incoming requests by matching them to defined routes. ```lua -- main.lua local silly = require "silly" local http = require "silly.net.http" local UserRoutes = require "routes.users" local ProductRoutes = require "routes.products" -- Route definitions local routes = { {method = "GET", pattern = "^/api/users$", handler = UserRoutes.list}, {method = "GET", pattern = "^/api/users/(%d+)$", handler = UserRoutes.get}, {method = "POST", pattern = "^/api/users$", handler = UserRoutes.create}, {method = "GET", pattern = "^/api/products$", handler = ProductRoutes.list}, {method = "GET", pattern = "^/api/products/(%d+)$", handler = ProductRoutes.get}, } -- Start server http.listen { addr = ":8080", handler = function(stream) local handler, matches = match_route(stream.method, stream.path) if handler then handler(stream, table.unpack(matches)) else send_error(stream, 404, "NOT_FOUND", "Endpoint not found") end end } ``` -------------------------------- ### Troubleshoot Lua Compilation: lua.h Not Found Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/getting-started.md Provides a solution for the common compilation error 'fatal error: lua.h: No such file or directory'. This issue typically arises when the Lua development files are not properly installed or accessible. The fix involves initializing and updating Git submodules. ```bash # Ensure submodules are initialized git submodule update --init --recursive ``` -------------------------------- ### Build a Timer Demo with Concurrent Tasks in Lua Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/getting-started.md A complete example demonstrating the use of `task.fork()` and `time.sleep()` to create a timer program. This program features two tasks that print messages at different intervals, and a main task that ensures the program runs for a specific duration before exiting. The `silly.exit(0)` function is used to terminate the application gracefully. ```lua local silly = require "silly" local task = require "silly.task" local time = require "silly.time" print("Timer demo started") -- Task 1: Print every second task.fork(function() for i = 1, 5 do print(string.format("[Task1] Second %d", i)) time.sleep(1000) end end) -- Task 2: Print every 0.5 seconds task.fork(function() for i = 1, 10 do print(string.format(" [Task2] Iteration %d (%.1fs)", i, i * 0.5)) time.sleep(500) end end) -- Main task: Exit after 6 seconds task.fork(function() time.sleep(6000) print("Demo ended") silly.exit(0) end) ``` -------------------------------- ### Benchmark Silly HTTP Server Performance (Bash) Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/http-server.md This example shows how to benchmark the performance of the Silly HTTP server using the `wrk` tool. It covers installation instructions for Debian/Ubuntu systems and provides a command to run a load test against a local API endpoint. The benchmark tests server responsiveness under simulated traffic. ```bash # Install wrk (Ubuntu/Debian) sudo apt-get install wrk # Benchmark test wrk -t4 -c100 -d30s http://127.0.0.1:8080/api/status ``` -------------------------------- ### Install Redis on Ubuntu/Debian Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/database-app.md Installs the Redis server on Ubuntu or Debian-based systems. This command is used to set up the caching mechanism for the application. ```bash sudo apt-get install redis-server sudo systemctl start redis ``` -------------------------------- ### Start HTTPS Server with Self-Signed Certificates Source: https://github.com/findstr/silly/blob/master/docs/src/en/guides/tls-configuration.md Configures and starts an HTTPS server using provided certificate and private key files. This function demonstrates how to load certificate data and listen for incoming TLS connections. ```lua local silly = require "silly" local tls = require "silly.net.tls" local io = io -- Read certificate and private key files local cert_file = io.open("server-cert.pem", "r") local cert_pem = cert_file:read("*a") cert_file:close() local key_file = io.open("server-key.pem", "r") local key_pem = key_file:read("*a") key_file:close() -- Start HTTPS server local listenfd = tls.listen { addr = "0.0.0.0:8443", certs = { { cert = cert_pem, key = key_pem, } }, accept = function(conn) conn:write( "HTTP/1.1 200 OK\r\n\r\nHello HTTPS!\n") conn:close() end } print("HTTPS server running at https://localhost:8443") ``` -------------------------------- ### Running Silly Framework Examples (Bash) Source: https://github.com/findstr/silly/blob/master/CLAUDE.md This snippet shows how to execute example scripts provided with the Silly framework using the './silly' command. It includes examples for a TCP echo server, an HTTP server with custom ports, and accessing command-line arguments. ```bash # Basic TCP echo server ./silly examples/tcp_echo.lua # HTTP server on port 8080 ./silly examples/http_server.lua --port=8080 # Access custom arguments in Lua local env = require "silly.env" local port = env.get("port") -- "8080" ``` -------------------------------- ### Compile Silly Framework Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/getting-started.md Compiles the Silly framework using the Make build tool. This is the standard compilation command. ```bash # Standard compilation make ``` -------------------------------- ### Verify Redis Installation Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/database-app.md Checks if the Redis server is running and accessible by sending a PING command. A PONG response indicates a successful connection. ```bash redis-cli ping # Should return PONG ``` -------------------------------- ### Obtain Let's Encrypt Certificates using Certbot Source: https://github.com/findstr/silly/blob/master/docs/src/en/guides/tls-configuration.md Guides on installing Certbot and obtaining free, trusted TLS certificates from Let's Encrypt for production environments. This process requires a domain name and access to port 80 for validation. ```bash # Install Certbot # Ubuntu/Debian sudo apt-get install certbot # CentOS/RHEL sudo yum install certbot # macOS brew install certbot # Obtain certificate (requires domain name and port 80 access) sudo certbot certonly --standalone -d yourdomain.com -d www.yourdomain.com # Certificate file locations # Certificate: /etc/letsencrypt/live/yourdomain.com/fullchain.pem # Private key: /etc/letsencrypt/live/yourdomain.com/privkey.pem ``` -------------------------------- ### Start HTTP Server with Configured Handler (Lua) Source: https://github.com/findstr/silly/blob/master/docs/src/en/guides/http-best-practices.md This snippet demonstrates starting an HTTP server using the Silly framework. It configures the server to listen on a specified address and port, utilizing a middleware chain for request handling. Dependencies include CONFIG, http.listen, logger, and defined middleware functions. ```lua -- Start server local handler = chain({ logging_middleware, rate_limit_middleware, body_size_middleware, }, main_handler) http.listen { addr = "0.0.0.0:" .. CONFIG.port, handler = handler } logger.info("HTTP server started on port", CONFIG.port) ``` -------------------------------- ### Start Server Command Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/database-app.md This bash command initiates the Lua HTTP API server. It executes the specified Lua script, which in turn starts listening for incoming HTTP requests on the configured address and port. ```bash ./silly user_api.lua ``` -------------------------------- ### Distributed Tracing Setup with silly.trace Source: https://github.com/findstr/silly/blob/master/docs/src/en/reference/task.md This example shows the basic setup for distributed tracing using the 'silly.trace' module. It covers setting the node ID, creating a new trace, propagating it to downstream services, and attaching an upstream trace. ```lua local trace = require "silly.trace" -- Set node ID (at service startup) trace.setnode(1) -- Create new trace (when handling new request) trace.spawn() -- Propagate trace to downstream (when calling other services) local traceid = trace.propagate() -- Attach upstream trace (when receiving request) trace.attach(upstream_traceid) ``` -------------------------------- ### Create Basic HTTP Server with Silly Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/http-server.md This snippet demonstrates how to create a basic HTTP server that listens on a specified address and responds with 'Hello, World!' to all incoming requests. It utilizes the `silly.net.http` module for server creation and request handling. The handler function is responsible for sending the HTTP response status, headers, and body. ```lua local silly = require "silly" local http = require "silly.net.http" http.listen { addr = "127.0.0.1:8080", handler = function(stream) local response_body = "Hello, World!" stream:respond(200, { ["content-type"] = "text/plain", ["content-length"] = #response_body, }) stream:closewrite(response_body) end } print("HTTP server listening on http://127.0.0.1:8080") ``` -------------------------------- ### Silly Project Development Setup Source: https://github.com/findstr/silly/blob/master/README.md Provides instructions for setting up the development environment for the Silly project, including cloning the repository with submodules, building the project in debug mode, and formatting the code. ```bash # Clone with submodules git clone --recursive https://github.com/findstr/silly.git # Build in debug mode make test # Format code make fmt ``` -------------------------------- ### Get Current Coroutine with task.running() Source: https://github.com/findstr/silly/blob/master/docs/src/en/reference/task.md Retrieves the currently executing coroutine. This is useful for introspection or when a coroutine needs a reference to itself, for example, when it needs to be woken up later. ```lua local task = require "silly.task" local current_task = task.running() ``` -------------------------------- ### HTTP Server and Client Implementation (Lua) Source: https://github.com/findstr/silly/blob/master/CLAUDE.md This snippet demonstrates how to set up an HTTP server and client using the 'silly.net.http' module. It covers listening for connections, handling requests, sending responses, and making client requests with various options like GET, POST, and streaming. ```lua local http = require "silly.net.http" -- Server: listen accepts a table with addr and handler callback local server = http.listen { addr = "0.0.0.0:8080", handler = function(stream) -- Access request properties local method = stream.method local path = stream.path local headers = stream.header local query = stream.query -- Read request body local body = stream:readall() -- Send response (Method 1: separate write and close) stream:respond(200, { ["content-type"] = "application/json", ["content-length"] = #response_data, }) stream:write(response_data) -- Send response (Method 2: closewrite with data - RECOMMENDED) -- Reduces function calls and for HTTP/2 can reduce packet count stream:respond(200, { ["content-type"] = "application/json", ["content-length"] = #response_data, }) stream:closewrite(response_data) -- For chunked with trailers stream:respond(200, { ["transfer-encoding"] = "chunked", }) stream:write("data1") stream:closewrite(nil, { -- nil for no final data, table for trailer headers ["x-checksum"] = "abc123", }) end } -- Client: create client with newclient(), then use methods local httpc = http.newclient({ max_idle_per_host = 10, idle_timeout = 30000, }) -- Simple GET/POST local response = httpc:get("http://example.com/api") local response = httpc:post("http://example.com/api", headers, body) -- Streaming request/response local stream = httpc:request("POST", "http://example.com/api", { ["content-length"] = 1024, }) stream:write("part1") stream:write("part2") stream:closewrite() -- Close write side local response_body = stream:readall() -- Or send all data with closewrite (more efficient) local stream = httpc:request("POST", "http://example.com/api", { ["content-length"] = 1024, }) stream:closewrite(request_data) -- Write data and close in one call local response_body = stream:readall() ``` -------------------------------- ### Example: Performance Measurement Source: https://github.com/findstr/silly/blob/master/docs/src/en/reference/time.md Shows how to measure the execution time of a block of code using `time.monotonic()`. It records the start time, performs some operations, and then calculates the elapsed time. ```lua local time = require "silly.time" local start = time.monotonic() -- Execute some operations local sum = 0 for i = 1, 1000000 do sum = sum + i end local elapsed = time.monotonic() - start print("Processing took", elapsed, "ms") ``` -------------------------------- ### Test JSON API with cURL Commands Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/http-server.md This section provides example cURL commands to interact with the previously defined JSON API. It demonstrates how to fetch all users, create a new user via POST with a JSON payload, and query users using URL parameters. These commands are essential for testing the API's functionality and validating its responses. ```bash # Get all users curl http://127.0.0.1:8080/api/users # Create new user curl -X POST http://127.0.0.1:8080/api/users \ -H "Content-Type: application/json" \ -d '{"name":"Charlie","age":35}' # Query users curl "http://127.0.0.1:8080/api/users?name=Alice" ``` -------------------------------- ### Compile Silly with OpenSSL Support Source: https://github.com/findstr/silly/blob/master/docs/src/en/guides/tls-configuration.md Ensures the Silly framework is compiled with OpenSSL support, which is necessary for TLS functionality. This involves installing the OpenSSL development library and recompiling Silly with the `OPENSSL=ON` flag. ```bash # Install OpenSSL development library # Ubuntu/Debian sudo apt-get install libssl-dev # CentOS/RHEL sudo yum install openssl-devel # macOS brew install openssl # Compile Silly (with OpenSSL enabled) make OPENSSL=ON ``` -------------------------------- ### Complete HTTP Service Monitoring in Lua Source: https://github.com/findstr/silly/blob/master/docs/src/en/guides/logging-monitoring.md Provides a comprehensive example of an HTTP service in Lua that integrates various Prometheus metrics: counters, gauges, and histograms. It includes a request handler that exposes metrics at the /metrics endpoint and logs request details. This example showcases setting up an HTTP server and handling requests with associated metric collection. ```lua local silly = require "silly" local http = require "silly.net.http" local logger = require "silly.logger" local prometheus = require "silly.metrics.prometheus" -- Define metrics local http_requests_total = prometheus.counter( "myapp_http_requests_total", "Total HTTP requests", {"method", "path", "status"} ) local http_requests_in_flight = prometheus.gauge( "myapp_http_requests_in_flight", "Number of HTTP requests in flight" ) local http_request_duration = prometheus.histogram( "myapp_http_request_duration_seconds", "HTTP request duration (seconds)", {"method", "path"}, {0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 5.0} ) -- HTTP handler function local function handle_request(stream) local start = os.clock() http_requests_in_flight:inc() -- Handle different paths local status_code = 200 local response_body = "" if stream.path == "/metrics" then -- Prometheus metrics endpoint local metrics = prometheus.gather() stream:respond(200, { ["content-type"] = "text/plain; version=0.0.4", }) stream:closewrite(metrics) elseif stream.path == "/api/users" then -- Business API logger.info("Handling user API request:", stream.method) response_body = '{"users": []}' stream:respond(200, {"content-type" = "application/json"}) stream:closewrite(response_body) else -- 404 status_code = 404 response_body = "Not Found" stream:respond(404, {"content-type" = "text/plain"}) stream:closewrite(response_body) end -- Record metrics local duration = os.clock() - start http_requests_in_flight:dec() http_request_duration:labels(stream.method, stream.path):observe(duration) http_requests_total:labels(stream.method, stream.path, tostring(status_code)):inc() -- Record log logger.infof("%s %s %d %.3fs", stream.method, stream.path, status_code, duration) end -- Start service local server = http.listen { addr = "0.0.0.0:8080", handler = function(stream) local ok, err = silly.pcall(handle_request, stream) if not ok then logger.error("Request handling failed:", err) stream:respond(500, {"content-type" = "text/plain"}) stream:closewrite("Internal Server Error") end end } logger.info("Server started on 0.0.0.0:8080") logger.info("Prometheus metrics: http://localhost:8080/metrics") ``` -------------------------------- ### Advanced Silly Compilation Options Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/getting-started.md Provides advanced compilation options for Silly, including enabling OpenSSL, using different memory allocators, compiling test versions, and cleaning build artifacts. ```bash # Enable OpenSSL support make OPENSSL=ON # Use glibc memory allocator (for debugging) make MALLOC=glibc # Compile test version (with address sanitizer) make test # Clean build artifacts make clean ``` -------------------------------- ### Multi-Process Deployment Script for Silly Application (Bash) Source: https://github.com/findstr/silly/blob/master/docs/src/en/guides/http-best-practices.md This bash script automates the startup of multiple instances of the Silly application. It launches a specified number of processes, each listening on a different port, to enable load balancing and fully utilize multi-core CPUs. This approach is suitable for distributed deployments. ```bash #!/bin/bash # start_cluster.sh INSTANCES=4 BASE_PORT=8080 for i in $(seq 1 $INSTANCES); do PORT=$((BASE_PORT + i - 1)) ./silly main.lua --port=$PORT & echo "Started instance $i on port $PORT" done echo "All instances started" ``` -------------------------------- ### Lua Connection Pooling Example Source: https://github.com/findstr/silly/blob/master/docs/src/en/guides/mysql-connection-pool.md Demonstrates the performance difference between establishing a new MySQL connection for each request versus reusing connections from a pool. Using a connection pool significantly reduces overhead. ```lua -- Without connection pool: Establish new connection per request (slow) function handle_request() local db = mysql.open{...} -- 100ms connection overhead local result = db:query("SELECT * FROM users") -- 10ms query db:close() return result end -- With connection pool: Reuse connections (fast) local pool = mysql.open{...} -- Establish once function handle_request() local result = pool:query("SELECT * FROM users") -- 10ms query return result end ``` -------------------------------- ### POST /api/users - Create User Source: https://github.com/findstr/silly/blob/master/docs/src/en/tutorials/database-app.md Creates a new user with the provided name, email, and age. Returns the created user's details upon success. ```APIDOC ## POST /api/users ### Description Creates a new user with the provided name, email, and age. Returns the created user's details upon success. ### Method POST ### Endpoint /api/users #### Request Body - **name** (string) - Required - The name of the user. - **email** (string) - Required - The email address of the user. - **age** (number) - Optional - The age of the user. ### Request Example ```json { "name": "Emma", "email": "emma@example.com", "age": 27 } ``` ### Response #### Success Response (201) - **success** (boolean) - Indicates if the operation was successful. - **data** (object) - Contains the details of the created user. - **id** (number) - The unique identifier of the user. - **name** (string) - The name of the user. - **email** (string) - The email address of the user. - **age** (number) - The age of the user. #### Response Example ```json { "success": true, "data": { "id": 3, "name": "Emma", "email": "emma@example.com", "age": 27 } } ``` ``` -------------------------------- ### Lua Modules to Avoid Hot Reloading Source: https://github.com/findstr/silly/blob/master/docs/src/en/guides/hot-reload.md Provides examples of Lua module types that are generally not suitable for hot reloading, including core systems, low-level network modules, and modules with complex, difficult-to-migrate state. ```lua -- ❌ Core event loop local silly = require "silly" -- ❌ Low-level network modules local tcp = require "silly.net.tcp" -- ❌ Modules with complex state local M = {} local state_machine = create_complex_state() -- State machine difficult to migrate -- ✅ Business logic modules (suitable for hot reload) local M = {} function M.handle_user_request(req) -- Pure business logic, easy to hot reload end ``` -------------------------------- ### Basic Configuration Management Example - silly.env Source: https://github.com/findstr/silly/blob/master/docs/src/en/reference/env.md A comprehensive example showing how to load a configuration file and then access its values using `env.get()`. It demonstrates reading server host and port, providing default values if not found. ```lua local env = require "silly.env" -- Load configuration file env.load("config.lua") -- Read configuration local server_port = tonumber(env.get("server.port")) or 8080 local server_host = env.get("server.host") or "0.0.0.0" print(string.format("Server will listen on %s:%d", server_host, server_port)) ``` -------------------------------- ### gRPC Client and Server Example Source: https://github.com/findstr/silly/blob/master/docs/src/en/reference/net/grpc.md Demonstrates the setup and usage of a gRPC client and server for unary RPC calls using the Silly library. This includes defining protobuf messages, registering services, and making client calls. ```APIDOC ## Greeter Service Example ### Description This example showcases how to implement a simple gRPC server and client for a 'Greeter' service. It defines two RPC methods: `SayHello` and `SayGoodbye`, demonstrating basic unary request-response patterns. ### Method - **Server**: `grpc.listen(options)` - **Client**: `grpc.newclient(options)` ### Endpoint - **Server**: `127.0.0.1:50051` (configurable) - **Client**: Connects to the specified server endpoint. ### Parameters #### Server Options (`grpc.listen`) - **addr** (string) - The address and port to listen on (e.g., "127.0.0.1:50051"). - **registrar** (object) - A registrar object containing service implementations. #### Client Options (`grpc.newclient`) - **service** (string) - The name of the gRPC service to connect to. - **endpoints** (table) - A list of server endpoint addresses. - **proto** (object) - The loaded protobuf definitions. - **timeout** (number) - Optional - Client-side timeout for RPC calls in milliseconds. ### Request Example (Client Call) ```lua -- Assuming client is already initialized local resp1 = client.SayHello({name = "Alice"}) print(resp1.greeting) local resp2 = client.SayGoodbye({name = "Bob"}) print(resp2.greeting) ``` ### Response #### Success Response (200) - **greeting** (string) - The greeting message returned by the server. #### Response Example (Client) ```lua -- For SayHello: -- { -- "greeting": "Hello, Alice!" -- } -- For SayGoodbye: -- { -- "greeting": "Goodbye, Bob!" -- } ``` ```