NAME

LightTCP::Server - A configurable TCP/HTTP server with file uploads, rate limiting, and threading support (Pure Perl OOP)

SYNOPSIS

use LightTCP::Server;

# Basic HTTP server
my $server = LightTCP::Server->new(
    server_addr => '0.0.0.0:8080',
    server_name => 'MyServer',
    verbose     => 1,
);
$server->start();

# Threaded server with custom handler
my $server = LightTCP::Server->new(
    server_addr => '127.0.0.1:8881',
    server_type => 'thread',
    max_threads => 5,
    func_perl   => sub {
        my ($self, $client, $preq) = @_;
        print $client "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 5\r\n\r\nHello";
        return (200, 5);
    },
);
$server->start();

# Server with file uploads and rate limiting
my $server = LightTCP::Server->new(
    server_addr            => '0.0.0.0:8080',
    upload_dir             => '/var/www/uploads',
    upload_max_size        => 10 * 1024 * 1024,  # 10MB
    upload_allowed_types   => [qw(image/jpeg image/png application/pdf)],
    rate_limit_enabled     => 1,
    rate_limit_requests    => 100,
    rate_limit_window      => 60,
    rate_limit_block_duration => 300,
    func_upload            => \&handle_upload,
);
$server->start();

sub handle_upload {
    my ($server, $results) = @_;
    # $results is arrayref of upload info
    return (201, 'Upload successful');
}

DESCRIPTION

LightTCP::Server is a pure Perl OOP module implementing a flexible TCP/HTTP server. It handles HTTP requests, serves static files, executes CGI scripts, and supports custom logic via callbacks. Features include:

  • Single-threaded, forked, or threaded operation modes

  • File upload handling with size limits and type validation

  • Configurable rate limiting with IP blocking

  • HTTP authentication (API keys and Basic Auth)

  • Host-based access control (allow/deny lists)

  • CGI script execution

  • Comprehensive logging and verbose output levels

ATTRIBUTES

Server Configuration

server_addr (required, default: '0.0.0.0:8881')

IP address and port to listen on. Must be in format IP:port (e.g., '0.0.0.0:8080').

server_name (default: 'tcpsname')

Server name used in HTTP headers and logging.

server_type (default: 'single')

Execution mode: 'single' (single process), 'fork' (fork per connection), or 'thread' (threaded).

max_threads (default: 10)

Maximum concurrent threads when server_type is 'thread'.

server_timeout (default: -1)

Connection timeout in seconds. -1 means no timeout, 0 means daily timeout check, 1+ sets explicit timeout.

verbose (default: 0)

Verbosity level: 0 (minimal), 1 (important), 2 (info), 3 (debug).

logfn (default: '')

Path to log file. If empty, logs go to stderr.

server_autostop (default: 0)

If set to 1, server stops after first request.

Directory and File Handling

server_dir (default: '/var/www')

Root directory for serving static files.

server_etc (default: '.')

Directory for configuration files (allow/deny lists).

server_fnext (default: 'html css js ico gif jpg png')

Space-separated list of file extensions to serve statically.

server_perlonly (default: 1)

If 1, only custom handlers serve content; static files are disabled.

server_cgi (default: 0)

Enable CGI script execution.

server_cgiext (default: 'cgi php')

Space-separated list of CGI file extensions.

http_postlimit (default: 0)

Maximum POST body size in bytes. 0 means unlimited.

Security and Authentication

server_deny (default: 0)

Enable host-based access control using allow/deny files.

server_secure (default: 0)

If 1, deny by default and require explicit allow files.

server_auth (default: 0)

Enable authentication via API key or Basic Auth.

server_keys (default: [])

Arrayref of valid lowercase API key strings.

runas_user (default: '')

Run server as this user (after binding to privileged port).

runas_group (default: '')

Run server as this group.

File Upload Configuration

upload_dir (default: '/var/www/uploads')

Directory for storing uploaded files. Must be writable.

upload_max_size (default: 10MB)

Maximum file size in bytes for uploads.

upload_allowed_types (default: see below)

Arrayref of allowed MIME types. Defaults include: image/jpeg, image/png, image/gif, image/webp, application/pdf, text/plain, text/csv, text/html, application/zip, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.

func_upload

Optional callback coderef invoked after successful uploads. Signature: sub($server, $upload_results) where $upload_results is an arrayref of: { filename, size, mime_type, saved_path, success, error }. Should return ($status, $message).

Rate Limiting Configuration

rate_limit_enabled (default: 0)

Enable rate limiting.

rate_limit_requests (default: 100)

Maximum requests per time window.

rate_limit_window (default: 60)

Time window in seconds.

rate_limit_block_duration (default: 300)

Duration in seconds to block IPs that exceed rate limit.

rate_limit_whitelist (default: [127.0.0.1, ::1, localhost])

Arrayref of IP addresses exempt from rate limiting.

Callback Functions

func_perl

Custom request handler. Signature: sub($self, $client, $preq). $preq contains: METHOD, URI, URI_FN, URI_EXT, URI_VALID, QUERY_STRING, CONTENT_LENGTH, CONTENT_DATA, clip, clport, and HTTP headers. Should return ($status_code, $content_length).

func_timeout

Called on connection timeout. Signature: sub($self).

func_done

Called after request processing. Signature: sub($self, $preq).

func_log

Custom logging handler. Signature: sub($self, $message, $level).

METHODS

new(%config)

Create a new server instance. Accepts either a hash or hashref of configuration.

start()

Start the server and block until shutdown. Returns 1 on clean shutdown, 0 on error.

stop()

Stop the server gracefully.

is_running()

Returns true if server is running.

logit($message, $level)

Log a message at the specified level (0-3). Higher levels are more verbose.

validate_config(\%config)

Class method to validate configuration. Returns undef on success, error message string on failure.

server_addr([$value])

Getter/setter for server address.

server_name([$value])

Getter/setter for server name.

server_type([$value])

Getter/setter for server type.

max_threads([$value])

Getter/setter for max threads.

verbose([$value])

Getter/setter for verbosity level.

upload_dir([$value])

Getter/setter for upload directory.

upload_max_size([$value])

Getter/setter for max upload size.

rate_limit_enabled([$value])

Getter/setter for rate limit enabled flag.

rate_limit_requests([$value])

Getter/setter for rate limit requests.

UPLOAD ENDPOINTS

The server provides built-in upload handling at these endpoints:

GET /upload or GET /upload/

Returns an HTML form for file uploads.

POST /upload

Handles multipart/form-data file uploads.

POST /api/upload

Alternative endpoint for API-based uploads.

Upon successful upload, the func_upload callback is invoked if defined. File names are sanitized to prevent path traversal attacks.

RATE LIMITING

When rate limiting is enabled, the server tracks requests per IP address. Responses include these HTTP headers:

X-RateLimit-Limit - Maximum requests allowed
X-RateLimit-Remaining - Remaining requests in window
X-RateLimit-Reset - Seconds until window resets
Retry-After - Seconds until unblocked (on 429 responses)

When rate limit is exceeded, the server returns HTTP 429 Too Many Requests and closes the connection.

SECURITY

Path Traversal Protection

The server blocks requests containing .. or suspicious characters in URIs.

Upload Security

Uploaded filenames are sanitized: .., /, \, and special characters are removed. Files are written atomically using temp files then renamed.

Access Control

Host-based access control uses files in server_etc directory: ${server_name}_${IP}.allow and ${server_name}_${IP}.deny.

Authentication

Supports X-API-Key header and Basic Auth. Keys are compared case-insensitively.

CGI SUPPORT

When server_cgi is enabled, files with extensions in server_cgiext are executed as CGI scripts. The following environment variables are set:

REQUEST_METHOD, QUERY_STRING, CONTENT_LENGTH, SERVER_PROTOCOL, SCRIPT_NAME, PATH_INFO, and HTTP headers are passed as HTTP_* variables.

CGI scripts should output headers followed by a blank line, then the body.

EXAMPLES

See "demo.pl" in examples for a complete demonstration server.

DEPENDENCIES

  • IO::Socket::INET

  • IPC::Open3

  • threads

  • threads::shared

  • File::Temp

BUGS AND LIMITATIONS

  • No HTTPS/TLS support (plain TCP only)

  • No WebSocket support

  • CGI scripts must be executable and use shebang lines

  • Rate limiting uses in-memory storage (resets on restart)

  • Large file uploads are held in memory

AUTHOR

Hans Harder <hans.harder@atbas.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2026 by Hans Harder.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

LICENSE

This module is free software. You may redistribute it and/or modify it under the same terms as Perl itself.

VERSION

Version 2.04