Files
ginxsom/docs/FASTCGI.md
2025-10-16 15:24:41 -04:00

369 lines
22 KiB
Markdown

# 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 <fcgiapp.h>
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.