# FastCGI Protocol Flow Documentation This document provides ASCII flow charts to understand how FastCGI works with nginx for the ginxsom blossom server. ## FastCGI Overview FastCGI is a binary protocol that allows web servers (like nginx) to communicate with application servers efficiently. Unlike CGI which spawns a new process per request, FastCGI applications are persistent and can handle multiple concurrent requests. ## 1. FastCGI Connection Setup Flow ``` ┌─────────────────┐ Socket ┌─────────────────┐ │ nginx │◄──────────────►│ FastCGI App │ │ Web Server │ Connection │ (ginxsom) │ └─────────────────┘ └─────────────────┘ │ │ │ 1. Create Unix socket │ │ /tmp/ginxsom.sock │ │ │ │ 2. FastCGI app binds & listens │ │◄───────────────────────────────────│ │ │ │ 3. nginx connects when needed │ │───────────────────────────────────►│ │ │ │ 4. Connection established │ │◄──────────────────────────────────►│ ``` ## 2. HTTP Request Processing Flow ``` ┌─────────┐ HTTP ┌─────────┐ FastCGI ┌─────────┐ │ Client │────────────►│ nginx │─────────────►│ ginxsom │ │Browser │ │ │ │ FastCGI │ └─────────┘ └─────────┘ └─────────┘ │ │ │ │ HTTP Request │ │ │ PUT /upload │ │ │────────────────────────► │ │ │ │ │ │ FCGI_BEGIN_REQUEST │ │ │───────────────────────►│ │ │ │ │ │ FCGI_PARAMS │ │ │ (HTTP headers, etc) │ │ │───────────────────────►│ │ │ │ │ │ FCGI_STDIN │ │ │ (Request body) │ │ │───────────────────────►│ │ │ │ │ │ Process │ │ │◄───────Request─────────│ │ │ │ │ │ FCGI_STDOUT │ │ │ (Response headers) │ │ │◄───────────────────────│ │ │ │ │ │ FCGI_STDOUT │ │ │ (Response body) │ │ │◄───────────────────────│ │ │ │ │ │ FCGI_END_REQUEST │ │ │◄───────────────────────│ │ │ │ │ HTTP Response │ │ │◄──────────────────────│ │ ``` ## 3. FastCGI Record Structure ``` FastCGI Record Format: ┌─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐ │ Version │ Type │RequestID│RequestID│ Length │ Length │ Padding │Reserved │ │ (1) │ (1) │ Hi │ Lo │ Hi │ Lo │ Length │ (1) │ │ │ │ (1) │ (1) │ (1) │ (1) │ (1) │ │ └─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘ │◄────────────────── 8 bytes header ──────────────────────►│ │ │ │◄─────────────────── Content (Length bytes) ─────────────►│ │ │ │◄───── Padding (Padding Length bytes) ────►│ Record Types: - FCGI_BEGIN_REQUEST (1) - Start new request - FCGI_PARAMS (4) - Environment variables - FCGI_STDIN (5) - Request body data - FCGI_STDOUT (6) - Response data - FCGI_END_REQUEST (3) - End of request ``` ## 4. Ginxsom Endpoint Handling Flow ### 4a. Static File Request (Direct nginx) ``` ┌─────────┐ ┌─────────┐ │ Client │ │ nginx │ └─────────┘ └─────────┘ │ │ │ GET /{sha256hash} │ │───────────────────────►│ │ │ │ │ Check file exists: │ │ /var/lib/ginxsom/files/ │ │ {first2}/{remaining} │ │ │ │ ┌─ File exists? ─┐ │ │ │ YES │ │ │ └────────────────┘ │ │ │ │ HTTP 200 + File │ │ Serve directly │◄──────────────────────│◄──────┘ │ │ Alternative flow: │ │ ┌─ File exists? ─┐ │ │ │ NO │ │ │ └────────────────┘ │ │ │ │ HTTP 404 Not Found │ │ │◄──────────────────────│◄──────┘ ``` ### 4b. Upload Request (FastCGI) ``` ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ Client │ │ nginx │ │ ginxsom │ │ File │ │ │ │ │ │ FastCGI │ │ System │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │ │ │ │ PUT /upload │ │ │ │ Auth: xyz │ │ │ │ Body: file │ │ │ │─────────────►│ │ │ │ │ │ │ │ │ FCGI_PARAMS │ │ │ │ METHOD=PUT │ │ │ │ URI=/upload │ │ │ │ AUTH=xyz │ │ │ │─────────────►│ │ │ │ │ │ │ │ FCGI_STDIN │ │ │ │ (file data) │ │ │ │─────────────►│ │ │ │ │ │ │ │ │ Verify Auth │ │ │ │ (nostr sig) │ │ │ │ │ │ │ │ Calculate │ │ │ │ SHA-256 │ │ │ │ │ │ │ │ Write file │ │ │ │─────────────►│ │ │ │ │ │ │ │ Store │ │ │ │ metadata │ │ │ │────────────────────► │ │ │ │ DB │ │ │ │ │ │ FCGI_STDOUT │ │ │ │ 200 OK │ │ │ │ {sha256} │ │ │ │◄─────────────│ │ │ │ │ │ │ HTTP 200 OK │ │ │ │ {sha256} │ │ │ │◄─────────────│ │ │ ``` ### 4c. HEAD Request for Metadata (FastCGI) ``` ┌─────────┐ ┌─────────┐ ┌─────────┐ │ Client │ │ nginx │ │ ginxsom │ │ │ │ │ │ FastCGI │ └─────────┘ └─────────┘ └─────────┘ │ │ │ │ HEAD /{sha256} │ │ │──────────────────►│ │ │ │ │ │ │ FCGI_PARAMS │ │ │ METHOD=HEAD │ │ │ BLOSSOM_HASH=... │ │ │──────────────────►│ │ │ │ │ │ │ Query DB for │ │ │ file metadata │ │ │ │ │ FCGI_STDOUT │ │ │ Content-Length: X │ │ │ Content-Type: Y │ │ │ x-sha256: hash │ │ │◄──────────────────│ │ │ │ │ HTTP Headers Only │ │ │◄──────────────────│ │ ``` ## 5. Development vs Production Deployment ### Development Mode ``` ┌─────────────┐ ┌─────────────┐ │ Terminal │ │ nginx │ │ │ │ │ │ ./ginxsom │◄──────────────►│ Config: │ │ --fastcgi │ Unix Socket │ fastcgi_pass│ │ --socket │ /tmp/ginxsom │ unix:/tmp/ │ │ /tmp/... │ .sock │ ginxsom.sock│ └─────────────┘ └─────────────┘ │ │ │ Direct execution │ sudo systemctl │ Easy debugging │ reload nginx │ Ctrl+C to stop │ (config changes) │ Real-time logs │ ``` ### Production Mode ``` ┌─────────────┐ ┌─────────────┐ │ systemd │ │ nginx │ │ │ │ │ │ ginxsom │◄──────────────►│ Config: │ │ .service │ Unix Socket │ fastcgi_pass│ │ │ /run/ginxsom/ │ unix:/run/ │ │ Auto-start │ ginxsom.sock │ ginxsom/... │ │ Auto-restart│ │ │ │ Log to file │ │ │ └─────────────┘ └─────────────┘ ``` ## 6. Complete nginx + FastCGI Request Flow ``` ┌───────┐ ┌─────────────────────────────────────────────────┐ ┌─────────┐ │Client │ │ nginx │ │ginxsom │ └───────┘ └─────────────────────────────────────────────────┘ │FastCGI │ │ │ └─────────┘ │ GET /abc123...def │ │ │───────────────────────►│ │ │ │ │ │ │ location ~ ^/([a-f0-9]{64})$ { │ │ │ # Check if static file exists │ │ │ try_files /$prefix/$suffix =404 │ │ │ } │ │ │ │ │ │ ┌─ File exists? ─┐ │ │ │ │ YES │ │ │ │ └────────────────┘ │ │ │ │ │ │ │ │ Serve directly (fast!) │ │ HTTP 200 + File │ │ │ │◄──────────────────────│◄──────┘ │ │ │ │ │ │ │ │ PUT /upload │ │ │ Authorization: xyz │ │ │───────────────────────►│ │ │ │ │ │ │ location /upload { │ │ │ fastcgi_pass unix:/tmp/ │ │ │ ginxsom.sock; │ │ │ } │ │ │ │ │ │ ┌─ FastCGI Protocol ─┐ │ │ │ │ FCGI_BEGIN_REQUEST │─────────────►│ │ │ │ FCGI_PARAMS │─────────────►│ │ │ │ FCGI_STDIN │─────────────►│ │ │ └─────────────────────┘ │ │ │ │ │ │ │ Verify │ │ │ nostr │ │ │ signature │ │ │ │ │ │ Calculate │ │ │ SHA-256 │ │ │ │ │ │ Store file │ │ │ & metadata │ │ │ │ │ ┌─ FastCGI Response ─┐ │ │ │ │ FCGI_STDOUT │◄─────────────│ │ │ │ FCGI_END_REQUEST │◄─────────────│ │ │ └─────────────────────┘ │ │ │ │ │ HTTP 200 OK │ │ │ {"sha256": "..."} │ │ │◄──────────────────────│ │ ``` ## 7. libfcgi Library Usage ### Basic FastCGI Application Structure ```c #include int main() { FCGX_Request request; // Initialize FastCGI library FCGX_Init(); FCGX_InitRequest(&request, 0, 0); // Main request processing loop while (FCGX_Accept_r(&request) == 0) { // Read environment variables (HTTP headers, etc) char* method = FCGX_GetParam("REQUEST_METHOD", request.envp); char* uri = FCGX_GetParam("REQUEST_URI", request.envp); char* auth = FCGX_GetParam("HTTP_AUTHORIZATION", request.envp); // Route requests if (strcmp(uri, "/health") == 0) { handle_health(&request); } else if (strcmp(uri, "/upload") == 0) { handle_upload(&request); } else if (strncmp(uri, "/head/", 6) == 0) { handle_head(&request); } // Finish this request FCGX_Finish_r(&request); } return 0; } ``` ### Reading Request Data ``` ┌─────────────────┐ ┌─────────────────┐ │ nginx sends: │ │ ginxsom reads: │ ├─────────────────┤ ├─────────────────┤ │ FCGI_PARAMS │────────►│ FCGX_GetParam() │ │ REQUEST_METHOD │ │ "PUT" │ │ REQUEST_URI │ │ "/upload" │ │ CONTENT_LENGTH │ │ "1024" │ │ HTTP_* │ │ headers │ ├─────────────────┤ ├─────────────────┤ │ FCGI_STDIN │────────►│ FCGX_GetStr() │ │ (request body) │ │ file data │ └─────────────────┘ └─────────────────┘ ``` ### Writing Response Data ``` ┌─────────────────┐ ┌─────────────────┐ │ ginxsom writes: │ │ nginx sends: │ ├─────────────────┤ ├─────────────────┤ │ FCGX_PutS() │────────►│ HTTP Response │ │ "Content-Type: │ │ Headers │ │ application/ │ │ │ │ json\r\n\r\n" │ │ │ ├─────────────────┤ ├─────────────────┤ │ FCGX_PutS() │────────►│ HTTP Response │ │ '{"status": │ │ Body │ │ "ok"}' │ │ │ └─────────────────┘ └─────────────────┘ ``` This documentation shows how FastCGI enables nginx to efficiently serve static blossom files directly while delegating authenticated operations to the ginxsom FastCGI application.