• Implement Client-Server Model

    2 Open
    0 Closed

    Overview

    Separate the CgiApplication class into two classes:

    • CgiRequestServer
    • CgiRequestClient

    Rather than using an open standard like FastCGI, with very advanced capabilities, I think I'd rather keep this project simple and re-use my existing code.

    Requirements:

    CgiRequestClient

    • Initialized by HTTP server with environment containing REQUEST_URI
    • Does not need to call ::ImportRoutes() or worry about handling routes.
    • Log file: /var/log/CgiRequestClient.log

    Program Flow

    1. Launched by HTTP Server with environment data
    2. Check for server .PID file and .socket.
      1. log all errors
      2. if .pid file is missing, and socket is still there, log it too!
      3. exit if things look fishy, and return an error!
      4. (optional) output something on stdout instead of just returning an error
    3. Create objects and call methods to process the environment information
    4. connect to the server socket and send envp information, including REQUEST_URI
    5. Wait for result.
    6. Spit result back at HTTP server.

    CgiRequestServer

    • Socket Path: /tmp/CgiRequestServer.sock
    • PID File Path: /tmp/CgiRequestServer.pid
    • Log file: /var/log/CgiRequestServer.log

    Program Flow

    1. Check for a .pid file to prevent duplicate launches
      • (optional) also search for processes by name
    2. Check for a stale socket and remove if needed.
    3. Create named socket at /tmp
    4. Daemonize self
      • Parent Process:
        1. Calls fork(), exec() and daemon() as required
        2. Close all file descriptors
        3. Log all errors and successes, flush file, close it.
      • Child Process:
        1. Write to log as soon as forked.
        2. Registers signal handlers (maybe optional)
        3. Redirect stdout and stderr to /dev/null
        4. Write a .PID file in same dir as socket
        5. Write PID to log.
        6. Normal CgiApplication initialization.
        • Scan markdown content directory with MarkdownRouteHandler::GenerateRoutes()
        1. Creates infinite loop listening on socket
        2. On accept:
          1. Create a thread containing the new accept socket
          2. Associate the thread with REQUEST_URI in a Dictionary object.
          3. Process the REQUEST_URI using the cached routes and IRouteHandler objects in memory

    Implementation Proposal

    • Can re-use the app initialization code form CgiApplication
      • Proposed split:
      • CgiApplication -> ICgiApplication + ICgiRequestHandler, CgiApplicationBase, CgiRequestHandler
      • CGiApplicationBase: initializes args, env etc
      • CgiRequestHandlerBase: Route-Handling functionality
    • Final implementation classes can handle daemonizing, thread-management, etc.