[go: up one dir, main page]

mockforge-ftp 0.3.4

FTP protocol support for MockForge
Documentation

MockForge FTP

FTP protocol support for MockForge.

This crate provides FTP-specific functionality for creating mock FTP servers, including virtual file systems, fixture-driven responses, and file transfer simulation. Perfect for testing FTP clients, file upload workflows, and FTP-based integrations.

Features

  • FTP Server Mocking: Full FTP protocol support with standard commands
  • Virtual File System: In-memory file storage with configurable content
  • Fixture Management: YAML-based configuration for file structures
  • Upload Handling: Configurable validation and storage for file uploads
  • Template Support: Dynamic content generation using Handlebars templates
  • Protocol Compliance: Supports passive/active modes and authentication

Quick Start

Basic FTP Server

use mockforge_ftp::FtpServer;
use mockforge_core::config::FtpConfig;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create default FTP configuration
    let config = FtpConfig::default();

    // Initialize FTP server
    let server = FtpServer::new(config).await?;

    // Start the server
    server.start().await?;

    Ok(())
}

Server with Custom Configuration

use mockforge_core::config::FtpConfig;
use mockforge_ftp::FtpServer;

let config = FtpConfig {
    host: "127.0.0.1".to_string(),
    port: 2121,
    virtual_root: "/ftp".to_string(),
    ..Default::default()
};

let server = FtpServer::new(config).await?;
server.start().await?;

Virtual File System

MockForge FTP includes a powerful virtual file system for creating realistic file structures:

Static Files

use mockforge_ftp::vfs::{VirtualFileSystem, FileContent, FileMetadata};
use std::path::PathBuf;

let mut vfs = VirtualFileSystem::new("/ftp".to_string());

// Add a static file
let content = FileContent::Static(b"Hello, FTP!".to_vec());
let metadata = FileMetadata {
    size: 11,
    permissions: "644".to_string(),
    owner: "user".to_string(),
    group: "users".to_string(),
};

let file = VirtualFile::new(
    PathBuf::from("/ftp/hello.txt"),
    content,
    metadata
);

vfs.add_file(PathBuf::from("/ftp/hello.txt"), file)?;

Generated Files

use mockforge_ftp::vfs::{FileContent, GenerationPattern};

// Generate a 1MB file with random content
let content = FileContent::Generated {
    size: 1024 * 1024,
    pattern: GenerationPattern::Random,
};

// Generate a file with incremental bytes (0, 1, 2, ...)
let incremental = FileContent::Generated {
    size: 1000,
    pattern: GenerationPattern::Incremental,
};

Template Files

use mockforge_ftp::vfs::FileContent;

// Use Handlebars templates for dynamic content
let content = FileContent::Template(
    "Hello {{name}}! Today is {{date}}.".to_string()
);

Fixture System

Define complete FTP server configurations using YAML fixtures:

identifier: "test-server"
name: "Test FTP Server"
description: "A test FTP server with sample files"

virtual_files:
  - path: "/welcome.txt"
    content:
      type: "static"
      content: "Welcome to MockForge FTP!"
    permissions: "644"
    owner: "ftp"
    group: "ftp"

  - path: "/data.bin"
    content:
      type: "generated"
      size: 1048576  # 1MB
      pattern: "random"
    permissions: "644"
    owner: "ftp"
    group: "ftp"

upload_rules:
  - path_pattern: "/uploads/.*\\.txt"
    auto_accept: true
    validation:
      max_size_bytes: 1048576  # 1MB limit
      allowed_extensions: ["txt"]
    storage:
      type: "memory"

  - path_pattern: "/logs/.*\\.log"
    auto_accept: true
    storage:
      type: "file"
      path: "/tmp/ftp_logs"

Loading Fixtures

use mockforge_ftp::{FtpServer, FtpSpecRegistry};
use mockforge_core::config::FtpConfig;

let config = FtpConfig::default();
let server = FtpServer::new(config).await?;

// Load fixture from file
server.spec_registry().load_fixture_from_file("ftp-fixture.yaml").await?;

// Or create fixture programmatically
use mockforge_ftp::fixtures::{FtpFixture, VirtualFileConfig, UploadRule};

let fixture = FtpFixture {
    identifier: "programmatic".to_string(),
    name: "Programmatic Fixture".to_string(),
    description: Some("Created in code".to_string()),
    virtual_files: vec![/* ... */],
    upload_rules: vec![/* ... */],
};

server.spec_registry().add_fixture(fixture)?;

Upload Handling

Configure how the server handles file uploads:

Upload Rules

use mockforge_ftp::fixtures::{UploadRule, FileValidation, UploadStorage};
use regex::Regex;

let rule = UploadRule {
    path_pattern: r"/uploads/.*".to_string(),
    auto_accept: true,
    validation: Some(FileValidation {
        max_size_bytes: Some(10 * 1024 * 1024), // 10MB
        allowed_extensions: Some(vec!["txt".to_string(), "csv".to_string()]),
        mime_types: Some(vec!["text/plain".to_string(), "text/csv".to_string()]),
    }),
    storage: UploadStorage::Memory, // Store in VFS
};

Storage Options

  • Memory: Store uploaded files in the virtual file system
  • File: Write to the local file system
  • Discard: Accept uploads but don't store them

FTP Protocol Support

MockForge FTP supports standard FTP commands:

  • Connection: USER, PASS, QUIT
  • Navigation: CWD, CDUP, PWD
  • Directory: LIST, NLST, MKD, RMD
  • File Operations: RETR, STOR, DELE, RNFR/RNTO
  • System: SYST, FEAT, OPTS
  • Transfer Modes: Passive and active mode support

Testing FTP Clients

Use MockForge FTP to test FTP client applications:

use suppaftp::FtpStream; // FTP client library
use mockforge_ftp::FtpServer;
use mockforge_core::config::FtpConfig;
use tokio::task;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Start FTP server in background
    let config = FtpConfig {
        host: "127.0.0.1".to_string(),
        port: 2121,
        ..Default::default()
    };

    let server = FtpServer::new(config.clone()).await?;
    task::spawn(async move {
        server.start().await.unwrap();
    });

    // Give server time to start
    tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;

    // Test FTP client
    let mut ftp_stream = FtpStream::connect(format!("{}:{}", config.host, config.port))?;
    ftp_stream.login("anonymous", "anonymous")?;

    // List files
    let files = ftp_stream.list(None)?;
    println!("Files: {:?}", files);

    // Download a file
    let mut reader = ftp_stream.get("welcome.txt")?;
    // ... process file content ...

    ftp_stream.quit()?;

    Ok(())
}

Configuration

FtpConfig

use mockforge_core::config::FtpConfig;

let config = FtpConfig {
    host: "0.0.0.0".to_string(),     // Bind address
    port: 21,                        // FTP port
    virtual_root: "/".to_string(),    // Virtual filesystem root
    greeting: "MockForge FTP".to_string(), // Server greeting
    max_connections: 100,            // Connection limit
    ..Default::default()
};

Integration with MockForge

MockForge FTP integrates seamlessly with the MockForge ecosystem:

  • MockForge Core: Shared configuration and logging
  • MockForge CLI: Command-line interface for FTP server management
  • MockForge Plugins: Extend FTP functionality with custom plugins

Performance

MockForge FTP is optimized for testing scenarios:

  • In-Memory Storage: Fast file operations without disk I/O
  • Lazy Content Generation: Files generated on-demand
  • Concurrent Connections: Handle multiple simultaneous FTP clients
  • Low Memory Footprint: Efficient storage for large file simulations

Examples

See the examples directory for complete working examples including:

  • Basic FTP server setup
  • Fixture-driven configurations
  • Upload handling scenarios
  • Integration testing patterns

Related Crates

License

Licensed under MIT OR Apache-2.0