This implementation adds a comprehensive HTTP request proxying system that allows the server to request web content through mod users. Users can opt in/out of proxying, and requests can be filtered by user locale.
- Cassandra table model for storing proxy responses
- Fields: Id, RequestUrl, ResponseBody, StatusCode, Headers, UserId, Locale, CreatedAt
- TTL: 1 hour (automatic expiration)
- Uses CQL LINQ pattern like CounterService
- Socket Management: Maintains queues of available proxy users by locale
- Request Routing: Routes proxy requests to users based on locale preference with fallback
- Response Storage: Stores proxied responses using Cassandra LINQ
- Response Retrieval: Fetches stored responses by ID
- Statistics: Provides counts of available sockets by locale
Key Methods:
RegisterSocket(socket): Registers a user for proxy requestsUnregisterSocket(socket): Removes a user from proxy poolRequestProxy(url, uploadTo, locale, regex): Sends proxy request to a userStoreProxyResponse(...): Saves proxied content to databaseGetProxyResponse(id): Retrieves stored proxy response
User-facing command to manage proxy opt-in status:
/cofl proxy- Show current status/cofl proxy on- Enable proxying/cofl proxy off- Disable proxying
The command:
- Updates
AccountInfo.ProxyOptInin database - Updates
SessionInfo.ProxyOptInin memory - Registers/unregisters socket with ProxyService
Three HTTP endpoints:
Request a proxy for a URL
{
"url": "https://example.com",
"uploadTo": "https://yourserver.com/api/proxy/response",
"locale": "en_US", // optional
"regex": "pattern" // optional
}Response:
{
"id": "request-uuid",
"message": "Proxy request sent"
}Submit a proxied response (called by mod)
{
"id": "request-uuid",
"requestUrl": "https://example.com",
"responseBody": "HTML content...",
"statusCode": 200,
"headers": "{...}",
"userId": "user-id",
"locale": "en_US"
}Retrieve a stored proxy response Returns the full ProxyResponseTable object
Get statistics about available proxy users
{
"totalAvailable": 42,
"byLocale": {
"en_US": 20,
"de_DE": 15,
"fr_FR": 7
}
}Added fields:
ProxyOptIn(bool): Persistent opt-in status
Added fields:
ProxyOptIn(bool): Current session proxy statusLocale(string?): User's locale for location-based requests
In UpdateAccountInfo method:
- Syncs
ProxyOptInfrom AccountInfo to SessionInfo - Syncs
Localefrom AccountInfo to SessionInfo - Registers/unregisters socket with ProxyService based on opt-in status
In Dispose method:
- Unregisters socket from ProxyService on disconnect
Registered ProxyService as singleton:
services.AddSingleton<ProxyService>();- User runs
/cofl proxy on - Command updates
AccountInfo.ProxyOptIn = truein database - Command updates
SessionInfo.ProxyOptIn = truein memory - Command calls
ProxyService.RegisterSocket(socket) - Socket is added to locale-specific queue
- External service calls
POST /api/proxy/requestwith URL and optional locale - ProxyService finds an available socket (prefer matching locale)
- ProxyService sends
proxymessage to mod client with request details - Mod client fetches the URL
- Mod client POSTs response to configured
uploadToendpoint - Response is stored in Cassandra with 1-hour TTL
- External service retrieves response via
GET /api/proxy/{id}
- Sockets are automatically registered when users opt in
- Sockets are re-queued after handling a request (round-robin)
- Sockets are unregistered on disconnect or opt-out
- Locale-based routing with fallback to any available socket
CREATE TABLE proxy_responses (
id text PRIMARY KEY,
request_url text,
response_body text,
status_code int,
headers text,
user_id text,
locale text,
created_at timestamp
) WITH default_time_to_live = 3600;- Users must explicitly opt in
- Proxy requests are only sent to opted-in users
- 1-hour TTL ensures data doesn't persist indefinitely
- User ID is tracked for accountability
- Users can opt out at any time
To test the implementation:
-
User opt-in:
/cofl proxy on -
Request a proxy (from external service):
curl -X POST http://localhost:5000/api/proxy/request \ -H "Content-Type: application/json" \ -d '{"url": "https://example.com", "uploadTo": "http://yourserver.com/api/proxy/response"}'
-
Check stats:
curl http://localhost:5000/api/proxy/stats
-
Retrieve response:
curl http://localhost:5000/api/proxy/{id}
- The implementation uses CQL LINQ throughout, following the CounterService pattern
- Automatic TTL (1 hour) handles cleanup without manual intervention
- Socket queues are managed in-memory for performance
- Locale-based routing allows for region-specific content fetching
- The system is resilient to socket disconnections and user opt-outs