macOS Web Features Swift Samples

macOS Swift web features examples including URL routing, middleware pipeline, and static file serving

Key Facts

Category
Swift
Items
3
Format Families
audio

Sample Overview

macOS Swift web features examples including URL routing, middleware pipeline, and static file serving This sample set belongs to Swift and can be used to test related workflows inside Elysia Tools.

💻 HTTP Request Routing swift

🟡 intermediate ⭐⭐⭐

Implement flexible HTTP request routing with pattern matching, parameter extraction, and RESTful API support

⏱️ 30 min 🏷️ swift, macos, web, routing, http
Prerequisites: Swift basics, HTTP protocol, Regular expressions
// macOS Swift Web Routing Examples
// Using Foundation and Vapor-inspired routing patterns

import Foundation

// MARK: - HTTP Models

// HTTP Request representation
struct HTTPRequest {
    let method: HTTPMethod
    let path: String
    let headers: [String: String]
    let body: Data?
    var queryParameters: [String: String] = [:]
    var pathParameters: [String: String] = [:]
}

enum HTTPMethod: String {
    case GET = "GET"
    case POST = "POST"
    case PUT = "PUT"
    case DELETE = "DELETE"
    case PATCH = "PATCH"
    case HEAD = "HEAD"
    case OPTIONS = "OPTIONS"
    case ANY = "*"
}

// HTTP Response representation
struct HTTPResponse {
    var statusCode: HTTPStatusCode = .ok
    var headers: [String: String] = [:]
    var body: Data?

    init(statusCode: HTTPStatusCode = .ok, headers: [String: String] = [:], body: Data? = nil) {
        self.statusCode = statusCode
        self.headers = headers
        self.body = body
    }

    func setContentType(_ contentType: String) -> HTTPResponse {
        var response = self
        response.headers["Content-Type"] = contentType
        return response
    }

    func setJSON(_ json: String) -> HTTPResponse {
        var response = self
        response.headers["Content-Type"] = "application/json"
        response.body = json.data(using: .utf8)
        return response
    }

    func setHTML(_ html: String) -> HTTPResponse {
        var response = self
        response.headers["Content-Type"] = "text/html"
        response.body = html.data(using: .utf8)
        return response
    }

    func setText(_ text: String) -> HTTPResponse {
        var response = self
        response.headers["Content-Type"] = "text/plain"
        response.body = text.data(using: .utf8)
        return response
    }
}

enum HTTPStatusCode: Int {
    case ok = 200
    case created = 201
    case accepted = 202
    case noContent = 204
    case movedPermanently = 301
    case found = 302
    case notModified = 304
    case badRequest = 400
    case unauthorized = 401
    case forbidden = 403
    case notFound = 404
    case methodNotAllowed = 405
    case conflict = 409
    case internalServerError = 500
    case notImplemented = 501
    case badGateway = 502
    case serviceUnavailable = 503
}

// MARK: - Route Handler

typealias RouteHandler = (HTTPRequest) -> HTTPResponse

// MARK: - Route

class Route {
    let method: HTTPMethod
    let pattern: String
    let handler: RouteHandler
    let regex: NSRegularExpression
    let parameterNames: [String]

    init(method: HTTPMethod, pattern: String, handler: @escaping RouteHandler) {
        self.method = method
        self.pattern = pattern
        self.handler = handler

        // Convert route pattern to regex
        let (regexString, params) = Route.compilePattern(pattern)
        self.regex = try! NSRegularExpression(pattern: regexString, options: [])
        self.parameterNames = params
    }

    // Check if route matches request
    func matches(request: HTTPRequest) -> Bool {
        if method != .ANY && method != request.method {
            return false
        }

        let range = NSRange(location: 0, length: request.path.utf16.count)
        return regex.firstMatch(in: request.path, options: [], range: range) != nil
    }

    // Extract path parameters from request
    func extractParameters(from request: HTTPRequest) -> [String: String] {
        var parameters: [String: String] = [:]

        let range = NSRange(location: 0, length: request.path.utf16.count)
        if let match = regex.firstMatch(in: request.path, options: [], range: range) {
            for (index, name) in parameterNames.enumerated() {
                let captureRange = match.range(at: index + 1)
                if captureRange.location != NSNotFound,
                   let range = Range(captureRange, in: request.path) {
                    parameters[name] = String(request.path[range])
                }
            }
        }

        return parameters
    }

    // Compile route pattern to regex
    private static func compilePattern(_ pattern: String) -> (String, [String]) {
        var regexPattern = "^"
        var params: [String] = []
        var current = pattern.startIndex

        while current < pattern.endIndex {
            if pattern[current] == ":" {
                // Parameter found
                let paramStart = pattern.index(after: current)
                if let paramEnd = pattern[paramStart...].firstIndex(where: { $0 == "/" || $0 == "." }) {
                    let paramName = String(pattern[paramStart..<paramEnd])
                    params.append(paramName)
                    regexPattern += "([^/\.]+)"
                    current = paramEnd
                } else {
                    let paramName = String(pattern[paramStart...])
                    params.append(paramName)
                    regexPattern += "([^/]+)"
                    current = pattern.endIndex
                }
            } else if pattern[current] == "*" {
                // Wildcard
                regexPattern += ".*"
                current = pattern.index(after: current)
            } else {
                // Regular character
                regexPattern += NSRegularExpression.escapedPattern(for: String(pattern[current]))
                current = pattern.index(after: current)
            }
        }

        regexPattern += "$"
        return (regexPattern, params)
    }
}

// MARK: - Router

class Router {
    private var routes: [Route] = []

    // Add route
    @discardableResult
    func add(method: HTTPMethod, path: String, handler: @escaping RouteHandler) -> Router {
        let route = Route(method: method, pattern: path, handler: handler)
        routes.append(route)
        print("Added route: \(method.rawValue) \(path)")
        return self
    }

    // Convenience methods
    func get(_ path: String, handler: @escaping RouteHandler) -> Router {
        add(method: .GET, path: path, handler: handler)
    }

    func post(_ path: String, handler: @escaping RouteHandler) -> Router {
        add(method: .POST, path: path, handler: handler)
    }

    func put(_ path: String, handler: @escaping RouteHandler) -> Router {
        add(method: .PUT, path: path, handler: handler)
    }

    func delete(_ path: String, handler: @escaping RouteHandler) -> Router {
        add(method: .DELETE, path: path, handler: handler)
    }

    func patch(_ path: String, handler: @escaping RouteHandler) -> Router {
        add(method: .PATCH, path: path, handler: handler)
    }

    func any(_ path: String, handler: @escaping RouteHandler) -> Router {
        add(method: .ANY, path: path, handler: handler)
    }

    // Route request
    func route(request: HTTPRequest) -> HTTPResponse {
        for route in routes {
            if route.matches(request: request) {
                var routedRequest = request
                routedRequest.pathParameters = route.extractParameters(from: request)

                print("Routing: \(request.method.rawValue) \(request.path) -> \(route.pattern)")

                do {
                    return route.handler(routedRequest)
                } catch {
                    return HTTPResponse(statusCode: .internalServerError, body: "Internal Server Error".data(using: .utf8))
                }
            }
        }

        // No matching route
        return HTTPResponse(statusCode: .notFound).setText("404 Not Found")
    }

    // Group routes with prefix
    func group(prefix: String, configure: (Router) -> Void) -> Router {
        let groupRouter = Router()
        configure(groupRouter)

        // Add all routes from group with prefix
        for route in groupRouter.routes {
            let fullPath = prefix + route.pattern
            let newRoute = Route(method: route.method, pattern: fullPath, handler: route.handler)
            routes.append(newRoute)
        }

        return self
    }
}

// MARK: - RESTful API Builder

class RESTfulAPI {
    let router = Router()
    private let resourceName: String

    init(resourceName: String) {
        self.resourceName = resourceName
        setupDefaultRoutes()
    }

    private func setupDefaultRoutes() {
        let path = "/\(resourceName)"

        // List all resources
        router.get(path) { request in
            let response = HTTPResponse()
            let json = """
            {
                "resource": "\(self.resourceName)",
                "items": [
                    {"id": 1, "name": "Item 1"},
                    {"id": 2, "name": "Item 2"},
                    {"id": 3, "name": "Item 3"}
                ],
                "count": 3
            }
            """
            return response.setJSON(json)
        }

        // Get specific resource
        router.get("\(path)/:id") { request in
            let id = request.pathParameters["id"] ?? "0"
            let response = HTTPResponse()
            let json = """
            {
                "id": \(id),
                "name": "Item \(id)",
                "description": "This is item \(id)"
            }
            """
            return response.setJSON(json)
        }

        // Create new resource
        router.post(path) { request in
            let response = HTTPResponse(statusCode: .created)
            let json = """
            {
                "id": 4,
                "status": "created",
                "message": "Resource created successfully"
            }
            """
            return response.setJSON(json)
        }

        // Update resource
        router.put("\(path)/:id") { request in
            let id = request.pathParameters["id"] ?? "0"
            let response = HTTPResponse()
            let json = """
            {
                "id": \(id),
                "status": "updated",
                "message": "Resource \(id) updated successfully"
            }
            """
            return response.setJSON(json)
        }

        // Delete resource
        router.delete("\(path)/:id") { request in
            let id = request.pathParameters["id"] ?? "0"
            let response = HTTPResponse()
            let json = """
            {
                "id": \(id),
                "status": "deleted",
                "message": "Resource \(id) deleted successfully"
            }
            """
            return response.setJSON(json)
        }
    }

    // Customize routes
    func customize(using builder: (Router) -> Void) -> RESTfulAPI {
        builder(router)
        return self
    }

    // Get router
    func build() -> Router {
        return router
    }
}

// MARK: - Route Middleware

class RouteMiddleware {
    let handler: (HTTPRequest, @escaping (HTTPRequest) -> HTTPResponse) -> HTTPResponse

    init(handler: @escaping (HTTPRequest, @escaping (HTTPRequest) -> HTTPResponse) -> HTTPResponse) {
        self.handler = handler
    }

    func process(request: HTTPRequest, next: @escaping (HTTPRequest) -> HTTPResponse) -> HTTPResponse {
        return handler(request, next)
    }
}

// Middleware implementations
extension RouteMiddleware {
    // Logging middleware
    static func logging() -> RouteMiddleware {
        return RouteMiddleware { request, next in
            print("[\(Date())] \(request.method.rawValue) \(request.path)")
            let response = next(request)
            print("[Response] \(response.statusCode.rawValue)")
            return response
        }
    }

    // Authentication middleware
    static func authenticate() -> RouteMiddleware {
        return RouteMiddleware { request, next in
            if let auth = request.headers["Authorization"], auth.hasPrefix("Bearer ") {
                return next(request)
            } else {
                return HTTPResponse(statusCode: .unauthorized).setJSON("{"error": "Unauthorized"}")
            }
        }
    }

    // CORS middleware
    static func cors() -> RouteMiddleware {
        return RouteMiddleware { request, next in
            var response = next(request)

            if request.method == .OPTIONS {
                response.headers["Access-Control-Allow-Origin"] = "*"
                response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS"
                response.headers["Access-Control-Allow-Headers"] = "Content-Type, Authorization"
                return response
            }

            response.headers["Access-Control-Allow-Origin"] = "*"
            return response
        }
    }
}

// MARK: - Demonstration

func demonstrateWebRouting() {
    print("=== macOS Swift Web Routing Examples ===\n")

    // 1. Basic router setup
    print("--- 1. Basic Router Setup ---")
    let router = Router()

    // Home page
    router.get("/") { request in
        let html = """
        <!DOCTYPE html>
        <html>
        <head><title>Swift Routing Demo</title></head>
        <body>
            <h1>Welcome to Swift Routing!</h1>
            <p>Try these routes:</p>
            <ul>
                <li><a href="/api/hello">GET /api/hello</a></li>
                <li><a href="/api/hello/John">GET /api/hello/John</a></li>
                <li><a href="/api/users">GET /api/users</a></li>
                <li><a href="/api/users/123">GET /api/users/123</a></li>
                <li><a href="/api/search?q=swift">GET /api/search?q=swift</a></li>
            </ul>
        </body>
        </html>
        """
        return HTTPResponse().setHTML(html)
    }

    // Simple API endpoint
    router.get("/api/hello") { request in
        return HTTPResponse().setJSON("{"message": "Hello, World!"}")
    }

    // Parameterized route
    router.get("/api/hello/:name") { request in
        let name = request.pathParameters["name"] ?? "Guest"
        return HTTPResponse().setJSON("{"message": "Hello, \(name)!"}")
    }

    // Multiple parameters
    router.get("/api/users/:userId/posts/:postId") { request in
        let userId = request.pathParameters["userId"] ?? "0"
        let postId = request.pathParameters["postId"] ?? "0"
        return HTTPResponse().setJSON("{"userId": \(userId), "postId": \(postId)}")
    }

    // Wildcard route
    router.get("/api/files/*") { request in
        return HTTPResponse().setJSON("{"path": "\(request.path)"}")
    }

    // 2. RESTful API
    print("\n--- 2. RESTful API ---")
    let userAPI = RESTfulAPI(resourceName: "users")

    // Customize with additional routes
    userAPI.customize { router in
        router.get("/users/:id/posts") { request in
            let id = request.pathParameters["id"] ?? "0"
            return HTTPResponse().setJSON("{"userId": \(id), "posts": []}")
        }
    }

    // Add RESTful routes to main router
    let apiRouter = userAPI.build()
    for route in apiRouter.routes {
        router.routes.append(route)
    }

    // 3. Route groups
    print("\n--- 3. Route Groups ---")
    router.group(prefix: "/api/v1") { group in
        group.get("/status") { request in
            return HTTPResponse().setJSON("{"version": "v1", "status": "ok"}")
        }

        group.get("/info") { request in
            return HTTPResponse().setJSON("{"version": "v1", "info": "API v1"}")
        }
    }

    // 4. Test routing
    print("\n--- 4. Testing Routes ---")

    let testRequests = [
        HTTPRequest(method: .GET, path: "/", headers: [:], body: nil),
        HTTPRequest(method: .GET, path: "/api/hello", headers: [:], body: nil),
        HTTPRequest(method: .GET, path: "/api/hello/John", headers: [:], body: nil),
        HTTPRequest(method: .GET, path: "/api/users/123/posts/456", headers: [:], body: nil),
        HTTPRequest(method: .GET, path: "/api/files/documents/report.pdf", headers: [:], body: nil),
        HTTPRequest(method: .GET, path: "/api/users", headers: [:], body: nil),
        HTTPRequest(method: .GET, path: "/api/users/42", headers: [:], body: nil),
        HTTPRequest(method: .GET, path: "/api/v1/status", headers: [:], body: nil),
        HTTPRequest(method: .GET, path: "/nonexistent", headers: [:], body: nil)
    ]

    for request in testRequests {
        print("\nRequest: \(request.method.rawValue) \(request.path)")
        let response = router.route(request: request)
        print("Response: \(response.statusCode.rawValue)")

        if let body = response.body,
           let bodyString = String(data: body, encoding: .utf8),
           bodyString.count < 200 {
            print("Body: \(bodyString)")
        }
    }

    print("\n=== Web Routing Demo Completed ===")
}

// Run demonstration
demonstrateWebRouting()

💻 Request Processing Middleware swift

🟡 intermediate ⭐⭐⭐⭐

Implement middleware pipeline for request logging, authentication, CORS, and error handling

⏱️ 35 min 🏷️ swift, macos, web, middleware, pipeline
Prerequisites: Swift basics, HTTP protocol, Functional programming
// macOS Swift Middleware Pipeline Examples
// Using Foundation and async/await patterns

import Foundation

// MARK: - HTTP Context

struct HTTPContext {
    var request: HTTPRequest
    var response: HTTPResponse
    var metadata: [String: Any] = [:]

    init(request: HTTPRequest) {
        self.request = request
        self.response = HTTPResponse()
    }
}

// MARK: - Middleware Protocol

protocol Middleware {
    func process(context: HTTPContext, next: @escaping (HTTPContext) -> HTTPContext) -> HTTPContext
}

// MARK: - Middleware Pipeline

class MiddlewarePipeline {
    private var middlewares: [Middleware] = []

    // Add middleware to pipeline
    @discardableResult
    func use(_ middleware: Middleware) -> MiddlewarePipeline {
        middlewares.append(middleware)
        print("Added middleware: \(type(of: middleware))")
        return self
    }

    // Process request through pipeline
    func process(request: HTTPRequest, finalHandler: @escaping (HTTPContext) -> HTTPContext) -> HTTPContext {
        var context = HTTPContext(request: request)

        // Build middleware chain
        let chain = buildChain(index: 0, finalHandler: finalHandler)

        return chain(context)
    }

    // Build middleware chain recursively
    private func buildChain(index: Int, finalHandler: @escaping (HTTPContext) -> HTTPContext) -> (HTTPContext) -> HTTPContext {
        if index < middlewares.count {
            let middleware = middlewares[index]
            return { context in
                let next = self.buildChain(index: index + 1, finalHandler: finalHandler)
                return middleware.process(context: context, next: next)
            }
        } else {
            return finalHandler
        }
    }
}

// MARK: - Middleware Implementations

// 1. Logging Middleware
class LoggingMiddleware: Middleware {
    let logLevel: LogLevel

    init(logLevel: LogLevel = .info) {
        self.logLevel = logLevel
    }

    func process(context: HTTPContext, next: @escaping (HTTPContext) -> HTTPContext) -> HTTPContext {
        let requestId = UUID().uuidString.prefix(8)
        let startTime = Date()

        log(.info, "[\(requestId]) \(context.request.method.rawValue) \(context.request.path) -> Started")

        // Store metadata
        context.metadata["requestId"] = String(requestId)
        context.metadata["startTime"] = startTime

        // Process next middleware
        let result = next(context)

        // Log completion
        let duration = Date().timeIntervalSince(startTime)
        log(.info, "[\(requestId)] \(context.request.method.rawValue) \(context.request.path) -> \(result.response.statusCode.rawValue) (\(String(format: "%.0f", duration * 1000))ms)")

        return result
    }

    private func log(_ level: LogLevel, _ message: String) {
        if level.rawValue >= logLevel.rawValue {
            print("[\(level)] \(message)")
        }
    }
}

enum LogLevel: Int, Comparable {
    case debug = 0
    case info = 1
    case warning = 2
    case error = 3

    static func < (lhs: LogLevel, rhs: LogLevel) -> Bool {
        return lhs.rawValue < rhs.rawValue
    }
}

// 2. Authentication Middleware
class AuthenticationMiddleware: Middleware {
    let authPaths: Set<String>
    let excludePaths: Set<String>

    init(authPaths: Set<String>, excludePaths: Set<String> = []) {
        self.authPaths = authPaths
        self.excludePaths = excludePaths
    }

    func process(context: HTTPContext, next: @escaping (HTTPContext) -> HTTPContext) -> HTTPContext {
        let path = context.request.path

        // Check if path requires authentication
        if authPaths.contains(where: { path.hasPrefix($0) }) &&
           !excludePaths.contains(where: { path.hasPrefix($0) }) {

            // Check for Authorization header
            guard let authHeader = context.request.headers["Authorization"],
                  authHeader.hasPrefix("Bearer ") else {

                log(.warning, "Authentication required for: \(path)")
                var unauthorizedContext = context
                unauthorizedContext.response = HTTPResponse(statusCode: .unauthorized)
                    .setJSON("{"error": "Authentication required", "code": 401}")
                return unauthorizedContext
            }

            // Validate token (simplified)
            let token = String(authHeader.dropFirst(7))
            if !isValidToken(token) {
                log(.warning, "Invalid token for: \(path)")
                var forbiddenContext = context
                forbiddenContext.response = HTTPResponse(statusCode: .forbidden)
                    .setJSON("{"error": "Invalid token", "code": 403}")
                return forbiddenContext
            }

            // Store user info in context
            context.metadata["authenticated"] = true
            context.metadata["userId"] = extractUserId(from: token)

            log(.info, "User authenticated: \(context.metadata["userId"] ?? "unknown")")
        }

        return next(context)
    }

    private func isValidToken(_ token: String) -> Bool {
        // Simplified token validation
        return token.count > 20
    }

    private func extractUserId(from token: String) -> String {
        // Extract user ID from token (simplified)
        return "user_\(token.prefix(8))"
    }

    private func log(_ level: LogLevel, _ message: String) {
        print("[\(level)] \(message)")
    }
}

// 3. CORS Middleware
class CORSMiddleware: Middleware {
    let allowedOrigins: [String]
    let allowedMethods: [String]
    let allowedHeaders: [String]

    init(allowedOrigins: [String] = ["*"],
         allowedMethods: [String] = ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
         allowedHeaders: [String] = ["Content-Type", "Authorization"]) {
        self.allowedOrigins = allowedOrigins
        self.allowedMethods = allowedMethods
        self.allowedHeaders = allowedHeaders
    }

    func process(context: HTTPContext, next: @escaping (HTTPContext) -> HTTPContext) -> HTTPContext {
        // Handle preflight request
        if context.request.method == .OPTIONS {
            var preflightContext = context
            preflightContext.response.statusCode = .ok
            preflightContext.response.headers["Access-Control-Allow-Origin"] = allowedOrigins.first ?? "*"
            preflightContext.response.headers["Access-Control-Allow-Methods"] = allowedMethods.joined(separator: ", ")
            preflightContext.response.headers["Access-Control-Allow-Headers"] = allowedHeaders.joined(separator: ", ")
            preflightContext.response.headers["Access-Control-Max-Age"] = "86400"
            return preflightContext
        }

        // Add CORS headers to response
        let result = next(context)
        result.response.headers["Access-Control-Allow-Origin"] = allowedOrigins.first ?? "*"
        result.response.headers["Access-Control-Allow-Methods"] = allowedMethods.joined(separator: ", ")
        result.response.headers["Access-Control-Allow-Headers"] = allowedHeaders.joined(separator: ", ")

        if let origin = context.request.headers["Origin"] {
            result.response.headers["Access-Control-Allow-Origin"] = origin
            result.response.headers["Vary"] = "Origin"
        }

        return result
    }
}

// 4. Rate Limiting Middleware
class RateLimitingMiddleware: Middleware {
    private var requestCounts: [String: [(Date, Int)]] = [:]
    private let maxRequests: Int
    private let windowInSeconds: Int
    private let cleanupInterval: Int

    init(maxRequests: Int = 100, windowInSeconds: Int = 60, cleanupInterval: Int = 300) {
        self.maxRequests = maxRequests
        self.windowInSeconds = windowInSeconds
        self.cleanupInterval = cleanupInterval
    }

    func process(context: HTTPContext, next: @escaping (HTTPContext) -> HTTPContext) -> HTTPContext {
        let clientId = getClientId(from: context.request)
        let now = Date()

        // Clean up old entries
        if Int.random(in: 1...100) == 1 { // Occasionally cleanup
            cleanup()
        }

        // Check rate limit
        if isRateLimited(clientId: clientId, at: now) {
            log(.warning, "Rate limit exceeded for: \(clientId)")
            var rateLimitedContext = context
            rateLimitedContext.response = HTTPResponse(statusCode: .serviceUnavailable)
                .setJSON("{"error": "Rate limit exceeded", "code": 429}")
            rateLimitedContext.response.headers["Retry-After"] = String(windowInSeconds)
            return rateLimitedContext
        }

        // Record request
        recordRequest(clientId: clientId, at: now)

        return next(context)
    }

    private func getClientId(from request: HTTPRequest) -> String {
        // Use IP or User-Agent as client identifier
        return request.headers["X-Forwarded-For"] ??
               request.headers["X-Real-IP"] ??
               request.headers["User-Agent"] ??
               "unknown"
    }

    private func isRateLimited(clientId: String, at now: Date) -> Bool {
        guard let requests = requestCounts[clientId] else {
            return false
        }

        let cutoff = now.addingTimeInterval(-Double(windowInSeconds))
        let recentRequests = requests.filter { $0.0 > cutoff }

        return recentRequests.count >= maxRequests
    }

    private func recordRequest(clientId: String, at now: Date) {
        if requestCounts[clientId] == nil {
            requestCounts[clientId] = []
        }
        requestCounts[clientId]?.append((now, 1))
    }

    private func cleanup() {
        let cutoff = Date().addingTimeInterval(-Double(cleanupInterval))
        for clientId in requestCounts.keys {
            requestCounts[clientId]?..removeAll { $0.0 < cutoff }
        }
    }

    private func log(_ level: LogLevel, _ message: String) {
        print("[\(level)] \(message)")
    }
}

// 5. Request Body Parsing Middleware
class BodyParsingMiddleware: Middleware {
    func process(context: HTTPContext, next: @escaping (HTTPContext) -> HTTPContext) -> HTTPContext {
        guard let body = context.request.body else {
            return next(context)
        }

        // Check content type
        let contentType = context.request.headers["Content-Type"] ?? ""

        if contentType.contains("application/json") {
            // Parse JSON body
            if let json = try? JSONSerialization.jsonObject(with: body, options: []) as? [String: Any] {
                context.metadata["parsedBody"] = json
                log(.info, "JSON body parsed: \(json.keys.count) fields")
            }
        } else if contentType.contains("application/x-www-form-urlencoded") {
            // Parse form data
            if let bodyString = String(data: body, encoding: .utf8) {
                let formData = parseFormData(bodyString)
                context.metadata["parsedBody"] = formData
                log(.info, "Form data parsed: \(formData.keys.count) fields")
            }
        } else {
            // Store raw body
            context.metadata["rawBody"] = body
        }

        return next(context)
    }

    private func parseFormData(_ string: String) -> [String: String] {
        var result: [String: String] = [:]
        let pairs = string.components(separatedBy: "&")

        for pair in pairs {
            let components = pair.components(separatedBy: "=")
            if components.count == 2,
               let key = components[0].removingPercentEncoding,
               let value = components[1].removingPercentEncoding {
                result[key] = value
            }
        }

        return result
    }

    private func log(_ level: LogLevel, _ message: String) {
        print("[\(level)] \(message)")
    }
}

// 6. Error Handling Middleware
class ErrorHandlingMiddleware: Middleware {
    func process(context: HTTPContext, next: @escaping (HTTPContext) -> HTTPContext) -> HTTPContext {
        do {
            return next(context)
        } catch {
            log(.error, "Unhandled error: \(error)")

            var errorContext = context
            let requestId = context.metadata["requestId"] as? String ?? "unknown"

            let errorJson = """
            {
                "error": "Internal Server Error",
                "message": "\(error.localizedDescription)",
                "requestId": "\(requestId)"
            }
            """

            errorContext.response = HTTPResponse(statusCode: .internalServerError)
                .setJSON(errorJson)

            return errorContext
        }
    }

    private func log(_ level: LogLevel, _ message: String) {
        print("[\(level)] \(message)")
    }
}

// 7. Response Compression Middleware
class CompressionMiddleware: Middleware {
    let minSize: Int

    init(minSize: Int = 1024) {
        self.minSize = minSize
    }

    func process(context: HTTPContext, next: @escaping (HTTPContext) -> HTTPContext) -> HTTPContext {
        let result = next(context)

        // Check if response should be compressed
        guard let body = result.response.body,
              body.count > minSize,
              shouldCompress(for: context.request) else {
            return result
        }

        // Compress body (simplified - just remove whitespace for JSON)
        if let contentType = result.response.headers["Content-Type"],
           contentType.contains("application/json"),
           let bodyString = String(data: body, encoding: .utf8) {

            let compressed = bodyString.split(separator: " ").joined()
            if let compressedData = compressed.data(using: .utf8) {
                result.response.body = compressedData
                result.response.headers["Content-Encoding"] = "gzip"
                result.response.headers["X-Original-Size"] = String(body.count)
                result.response.headers["X-Compressed-Size"] = String(compressedData.count)

                log(.info, "Compressed response: \(body.count) -> \(compressedData.count) bytes")
            }
        }

        return result
    }

    private func shouldCompress(for request: HTTPRequest) -> Bool {
        // Check Accept-Encoding header
        if let acceptEncoding = request.headers["Accept-Encoding"] {
            return acceptEncoding.contains("gzip") || acceptEncoding.contains("*")
        }
        return false
    }

    private func log(_ level: LogLevel, _ message: String) {
        print("[\(level)] \(message)")
    }
}

// 8. Timing Middleware
class TimingMiddleware: Middleware {
    func process(context: HTTPContext, next: @escaping (HTTPContext) -> HTTPContext) -> HTTPContext {
        let startTime = Date()

        let result = next(context)

        let duration = Date().timeIntervalSince(startTime)
        result.response.headers["X-Response-Time"] = String(format: "%.3f", duration)

        return result
    }
}

// MARK: - HTTP Types (from previous example)

struct HTTPRequest {
    let method: HTTPMethod
    let path: String
    let headers: [String: String]
    let body: Data?
}

enum HTTPMethod: String {
    case GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS, ANY
}

struct HTTPResponse {
    var statusCode: HTTPStatusCode = .ok
    var headers: [String: String] = [:]
    var body: Data?

    func setJSON(_ json: String) -> HTTPResponse {
        var response = self
        response.headers["Content-Type"] = "application/json"
        response.body = json.data(using: .utf8)
        return response
    }
}

enum HTTPStatusCode: Int {
    case ok = 200
    case unauthorized = 401
    case forbidden = 403
    case notFound = 404
    case serviceUnavailable = 503
    case internalServerError = 500
}

// MARK: - Demonstration

func demonstrateMiddleware() {
    print("=== macOS Swift Middleware Pipeline Examples ===\n")

    // 1. Create pipeline with multiple middlewares
    print("--- 1. Creating Middleware Pipeline ---")
    let pipeline = MiddlewarePipeline()

    pipeline
        .use(LoggingMiddleware(logLevel: .info))
        .use(ErrorHandlingMiddleware())
        .use(CORSMiddleware())
        .use(TimingMiddleware())

    // 2. Test public route (no authentication)
    print("\n--- 2. Testing Public Route ---")
    let publicRequest = HTTPRequest(
        method: .GET,
        path: "/api/status",
        headers: ["User-Agent": "TestClient"],
        body: nil
    )

    let publicContext = pipeline.process(request: publicRequest) { context in
        var ctx = context
        ctx.response = HTTPResponse().setJSON("{"status": "ok", "message": "Public access"}")
        return ctx
    }

    print("Public route response: \(publicContext.response.statusCode.rawValue)")

    // 3. Test authenticated route
    print("\n--- 3. Testing Authenticated Route ---")
    let authPipeline = MiddlewarePipeline()
    authPipeline
        .use(LoggingMiddleware())
        .use(AuthenticationMiddleware(authPaths: ["/api/protected"]))
        .use(ErrorHandlingMiddleware())

    let unauthRequest = HTTPRequest(
        method: .GET,
        path: "/api/protected/data",
        headers: ["User-Agent": "TestClient"],
        body: nil
    )

    let unauthContext = authPipeline.process(request: unauthRequest) { context in
        var ctx = context
        ctx.response = HTTPResponse().setJSON("{"data": "sensitive"}")
        return ctx
    }

    print("Unauthorized access: \(unauthContext.response.statusCode.rawValue)")

    // 4. Test with valid token
    let authRequest = HTTPRequest(
        method: .GET,
        path: "/api/protected/data",
        headers: ["Authorization": "Bearer valid_token_here_12345678"],
        body: nil
    )

    let authContext = authPipeline.process(request: authRequest) { context in
        var ctx = context
        let userId = context.metadata["userId"] as? String ?? "unknown"
        ctx.response = HTTPResponse().setJSON("{"data": "sensitive", "user": "\(userId)"}")
        return ctx
    }

    print("Authorized access: \(authContext.response.statusCode.rawValue)")

    // 5. Test rate limiting
    print("\n--- 4. Testing Rate Limiting ---")
    let rateLimitPipeline = MiddlewarePipeline()
    rateLimitPipeline
        .use(RateLimitingMiddleware(maxRequests: 3, windowInSeconds: 60))
        .use(LoggingMiddleware())

    // Make multiple requests
    for i in 1...5 {
        let request = HTTPRequest(
            method: .GET,
            path: "/api/test",
            headers: ["User-Agent": "TestClient"],
            body: nil
        )

        let context = rateLimitPipeline.process(request: request) { context in
            var ctx = context
            ctx.response = HTTPResponse().setJSON("{"request": \(i)}")
            return ctx
        }

        print("Request \(i): \(context.response.statusCode.rawValue)")
    }

    // 6. Test body parsing
    print("\n--- 5. Testing Body Parsing ---")
    let bodyPipeline = MiddlewarePipeline()
    bodyPipeline
        .use(BodyParsingMiddleware())
        .use(LoggingMiddleware())

    let jsonBody = """
    {
        "name": "John Doe",
        "email": "[email protected]"
    }
    """.data(using: .utf8)

    let postRequest = HTTPRequest(
        method: .POST,
        path: "/api/users",
        headers: ["Content-Type": "application/json"],
        body: jsonBody
    )

    let postContext = bodyPipeline.process(request: postRequest) { context in
        var ctx = context
        if let body = context.metadata["parsedBody"] as? [String: Any] {
            ctx.response = HTTPResponse().setJSON("{"received": \(body.keys.count) fields}")
        }
        return ctx
    }

    print("POST request: \(postContext.response.statusCode.rawValue)")

    print("\n=== Middleware Pipeline Demo Completed ===")
}

// Run demonstration
demonstrateMiddleware()

💻 Static File Serving swift

🟡 intermediate ⭐⭐⭐

Implement efficient static file serving with MIME type detection, caching headers, and security features

⏱️ 25 min 🏷️ swift, macos, web, static files, server
Prerequisites: Swift basics, File system operations, HTTP protocol
// macOS Swift Static File Serving Examples
// Using Foundation and URL handling

import Foundation

// MARK: - Static File Server Configuration

struct StaticFileConfig {
    var rootDirectory: String
    var enableDirectoryBrowsing: Bool = false
    var enableDefaultFiles: Bool = true
    var defaultFileNames: [String] = ["index.html", "default.html", "home.html"]
    var enableETag: Bool = true
    var enableLastModified: Bool = true
    var cacheMaxAge: Int = 3600 // 1 hour
    var enableCompression: Bool = true
    var allowedExtensions: [String] = [
        "html", "htm", "css", "js", "json", "xml", "txt", "md",
        "png", "jpg", "jpeg", "gif", "bmp", "svg", "ico",
        "pdf", "zip", "woff", "woff2", "ttf"
    ]

    var indexFileName: String {
        return defaultFileNames.first ?? "index.html"
    }
}

// MARK: - MIME Type Detector

class MIMETypeDetector {
    static let shared = MIMETypeDetector()

    private let mimeTypes: [String: String] = [
        // Text files
        "html": "text/html",
        "htm": "text/html",
        "css": "text/css",
        "js": "application/javascript",
        "json": "application/json",
        "xml": "application/xml",
        "txt": "text/plain",
        "md": "text/markdown",
        "csv": "text/csv",

        // Images
        "png": "image/png",
        "jpg": "image/jpeg",
        "jpeg": "image/jpeg",
        "gif": "image/gif",
        "bmp": "image/bmp",
        "svg": "image/svg+xml",
        "ico": "image/x-icon",
        "webp": "image/webp",

        // Fonts
        "woff": "font/woff",
        "woff2": "font/woff2",
        "ttf": "font/ttf",
        "otf": "font/otf",
        "eot": "application/vnd.ms-fontobject",

        // Documents
        "pdf": "application/pdf",
        "zip": "application/zip",
        "tar": "application/x-tar",
        "gz": "application/gzip",

        // Audio/Video
        "mp3": "audio/mpeg",
        "wav": "audio/wav",
        "mp4": "video/mp4",
        "webm": "video/webm"
    ]

    func detectMIMEType(for extension: String) -> String {
        let ext = extension.lowercased()
        return mimeTypes[ext] ?? "application/octet-stream"
    }

    func detectMIMEType(for url: URL) -> String {
        return detectMIMEType(for: url.pathExtension)
    }
}

// MARK: - Static File Server

class StaticFileServer {
    let config: StaticFileConfig
    private let fileManager = FileManager.default
    private let mimeDetector = MIMETypeDetector.shared

    init(config: StaticFileConfig) {
        self.config = config
    }

    convenience init(rootDirectory: String) {
        var config = StaticFileConfig(rootDirectory: rootDirectory)
        self.init(config: config)
    }

    // Serve file for request path
    func serveFile(for path: String) -> HTTPResponse {
        // Normalize and validate path
        let normalizedPath = normalizePath(path)

        // Security check: prevent path traversal
        if isPathTraversal(normalizedPath) {
            return HTTPResponse(statusCode: .forbidden)
                .setText("Forbidden: Path traversal detected")
        }

        // Resolve full path
        let fullPath = resolvePath(normalizedPath)

        // Check if path exists
        var isDirectory: ObjCBool = false
        guard fileManager.fileExists(atPath: fullPath, isDirectory: &isDirectory) else {
            return HTTPResponse(statusCode: .notFound)
                .setText("404 - File not found: \(path)")
        }

        // Handle directory
        if isDirectory.boolValue {
            return serveDirectory(at: fullPath, path: normalizedPath)
        }

        // Check file extension
        let fileExtension = (fullPath as NSString).pathExtension.lowercased()
        if !config.allowedExtensions.contains(fileExtension) {
            return HTTPResponse(statusCode: .forbidden)
                .setText("Forbidden: File type not allowed")
        }

        // Serve file
        return serveFile(at: fullPath)
    }

    // Serve individual file
    private func serveFile(at fullPath: String) -> HTTPResponse {
        do {
            // Get file attributes
            let attributes = try fileManager.attributesOfItem(atPath: fullPath)
            let fileSize = attributes[.size] as? UInt64 ?? 0
            let modificationDate = attributes[.modificationDate] as? Date ?? Date()

            // Read file content
            let fileData = try Data(contentsOf: URL(fileURLWithPath: fullPath))

            // Create response
            var response = HTTPResponse()
            response.body = fileData

            // Set content type
            let fileExtension = (fullPath as NSString).pathExtension.lowercased()
            let mimeType = mimeDetector.detectMIMEType(for: fileExtension)
            response.headers["Content-Type"] = mimeType

            // Set content length
            response.headers["Content-Length"] = String(fileSize)

            // Set cache headers
            if config.enableETag {
                let eTag = generateETag(for: fullPath, size: fileSize, modifiedDate: modificationDate)
                response.headers["ETag"] = eTag
                response.headers["Cache-Control"] = "public, max-age=\(config.cacheMaxAge)"
            }

            if config.enableLastModified {
                let dateFormatter = DateFormatter()
                dateFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss z"
                dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
                response.headers["Last-Modified"] = dateFormatter.string(from: modificationDate)
            }

            // Set security headers
            response.headers["X-Content-Type-Options"] = "nosniff"
            response.headers["X-Frame-Options"] = "SAMEORIGIN"

            print("Served: \(fullPath) (\(fileSize) bytes, \(mimeType))")

            return response

        } catch {
            print("Error serving file: \(error)")
            return HTTPResponse(statusCode: .internalServerError)
                .setText("Error reading file")
        }
    }

    // Serve directory
    private func serveDirectory(at fullPath: String, path: String) -> HTTPResponse {
        // Try to serve default file
        if config.enableDefaultFiles {
            for defaultFile in config.defaultFileNames {
                let defaultFilePath = (fullPath as NSString).appendingPathComponent(defaultFile)
                if fileManager.fileExists(atPath: defaultFilePath) {
                    return serveFile(at: defaultFilePath)
                }
            }
        }

        // Directory browsing
        if config.enableDirectoryBrowsing {
            return serveDirectoryListing(at: fullPath, path: path)
        }

        // No default file and browsing disabled
        return HTTPResponse(statusCode: .forbidden)
            .setText("Forbidden: Directory browsing disabled")
    }

    // Serve directory listing
    private func serveDirectoryListing(at fullPath: String, path: String) -> HTTPResponse {
        do {
            let contents = try fileManager.contentsOfDirectory(atPath: fullPath)

            var directories: [String] = []
            var files: [(name: String, size: UInt64, modified: Date)] = []

            for item in contents {
                let itemPath = (fullPath as NSString).appendingPathComponent(item)
                var isDirectory: ObjCBool = false
                fileManager.fileExists(atPath: itemPath, isDirectory: &isDirectory)

                if isDirectory.boolValue {
                    directories.append(item)
                } else {
                    if let attributes = try? fileManager.attributesOfItem(atPath: itemPath) {
                        let size = attributes[.size] as? UInt64 ?? 0
                        let modified = attributes[.modificationDate] as? Date ?? Date()
                        files.append((item, size, modified))
                    }
                }
            }

            // Generate HTML listing
            let html = generateDirectoryListingHTML(path: path, directories: directories, files: files)

            var response = HTTPResponse()
            response.headers["Content-Type"] = "text/html"
            response.body = html.data(using: .utf8)

            return response

        } catch {
            return HTTPResponse(statusCode: .internalServerError)
                .setText("Error reading directory")
        }
    }

    // Generate directory listing HTML
    private func generateDirectoryListingHTML(path: String, directories: [String], files: [(name: String, size: UInt64, modified: Date)]) -> String {
        var html = """
        <!DOCTYPE html>
        <html>
        <head>
            <title>Directory Listing: \(path)</title>
            <style>
                body { font-family: Arial, sans-serif; margin: 20px; }
                h1 { color: #333; }
                table { border-collapse: collapse; width: 100%; }
                th, td { padding: 10px; text-align: left; border-bottom: 1px solid #ddd; }
                th { background-color: #f4f4f4; }
                a { text-decoration: none; color: #0066cc; }
                a:hover { text-decoration: underline; }
                .icon { margin-right: 10px; }
            </style>
        </head>
        <body>
            <h1>Directory listing for \(path.isEmpty ? "/" : path)</h1>
            <table>
                <thead>
                    <tr>
                        <th>Name</th>
                        <th>Size</th>
                        <th>Modified</th>
                    </tr>
                </thead>
                <tbody>
        """

        // Parent directory link
        if path != "/" && !path.isEmpty {
            let parentPath = (path as NSString).deletingLastPathComponent
            html += "\n<tr><td><span class=\"icon\">📁</span><a href=\"\(parentPath)\">../</a></td><td>-</td><td>-</td></tr>"
        }

        // Directories
        for dir in directories.sorted() {
            let dirPath = path.isEmpty ? "/\(dir)" : "\(path)/\(dir)"
            html += "\n<tr><td><span class=\"icon\">📁</span><a href=\"\(dirPath)/\">\(dir)/</a></td><td>-</td><td>-</td></tr>"
        }

        // Files
        for file in files.sorted(by: { $0.name < $1.name }) {
            let filePath = path.isEmpty ? "/\(file.name)" : "\(path)/\(file.name)"
            let icon = getFileIcon(for: file.name)
            let size = formatBytes(file.size)
            let modified = formatDate(file.modified)
            html += "\n<tr><td><span class=\"icon\">\(icon)</span><a href=\"\(filePath)\">\(file.name)</a></td><td>\(size)</td><td>\(modified)</td></tr>"
        }

        html += """
                </tbody>
            </table>
            <p>Total: \(directories.count) directories, \(files.count) files</p>
        </body>
        </html>
        """

        return html
    }

    // Generate ETag
    private func generateETag(for path: String, size: UInt64, modifiedDate: Date) -> String {
        let hash = "\(modifiedDate.timeIntervalSince1970)-\(size)"
        return "W/\"\(hash)\""
    }

    // Normalize path
    private func normalizePath(_ path: String) -> String {
        var normalized = path

        // Remove leading slash
        if normalized.hasPrefix("/") {
            normalized = String(normalized.dropFirst())
        }

        // Replace backslashes with forward slashes
        normalized = normalized.replacingOccurrences(of: "\\", with: "/")

        // Remove query string
        if let queryRange = normalized.range(of: "?") {
            normalized = String(normalized[..<queryRange.lowerBound])
        }

        // Remove fragment
        if let fragmentRange = normalized.range(of: "#") {
            normalized = String(normalized[..<fragmentRange.lowerBound])
        }

        return normalized.isEmpty ? "/" : "/\(normalized)"
    }

    // Resolve full path
    private func resolvePath(_ normalizedPath: String) -> String {
        let relativePath = String(normalizedPath.dropFirst())
        return (config.rootDirectory as NSString).appendingPathComponent(relativePath)
    }

    // Check for path traversal
    private func isPathTraversal(_ path: String) -> Bool {
        return path.contains("..") || path.contains("./") || path.contains("\\")
    }

    // Get file icon
    private func getFileIcon(for fileName: String) -> String {
        let ext = ((fileName as NSString).pathExtension).lowercased()

        switch ext {
        case "html", "htm": return "🌐"
        case "css": return "🎨"
        case "js": return "⚡"
        case "json": return "📋"
        case "png", "jpg", "jpeg", "gif", "svg", "webp": return "🖼️"
        case "pdf": return "📕"
        case "zip", "tar", "gz": return "📦"
        case "woff", "woff2", "ttf": return "🔤"
        default: return "📄"
        }
    }

    // Format bytes
    private func formatBytes(_ bytes: UInt64) -> String {
        let kb = Double(bytes) / 1024
        let mb = kb / 1024
        let gb = mb / 1024

        if gb >= 1 {
            return String(format: "%.2f GB", gb)
        } else if mb >= 1 {
            return String(format: "%.2f MB", mb)
        } else if kb >= 1 {
            return String(format: "%.2f KB", kb)
        } else {
            return "\(bytes) B"
        }
    }

    // Format date
    private func formatDate(_ date: Date) -> String {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        return formatter.string(from: date)
    }
}

// MARK: - HTTP Response

struct HTTPResponse {
    var statusCode: HTTPStatusCode = .ok
    var headers: [String: String] = [:]
    var body: Data?

    func setText(_ text: String) -> HTTPResponse {
        var response = self
        response.headers["Content-Type"] = "text/plain"
        response.body = text.data(using: .utf8)
        return response
    }
}

enum HTTPStatusCode: Int {
    case ok = 200
    case forbidden = 403
    case notFound = 404
    case internalServerError = 500
}

// MARK: - File Cache

class FileCache {
    private var cache: [String: CachedFile] = [:]
    private let maxSize: Int
    private let maxAge: TimeInterval

    init(maxSize: Int = 100, maxAge: TimeInterval = 3600) {
        self.maxSize = maxSize
        self.maxAge = maxAge
    }

    func get(_ key: String) -> Data? {
        guard let cached = cache[key] else { return nil }

        // Check if expired
        if Date().timeIntervalSince(cached.timestamp) > maxAge {
            cache.removeValue(forKey: key)
            return nil
        }

        return cached.data
    }

    func set(_ key: String, data: Data) {
        // Evict oldest if necessary
        if cache.count >= maxSize {
            let oldest = cache.min(by: { $0.value.timestamp < $1.value.timestamp })
            if let oldestKey = oldest?.key {
                cache.removeValue(forKey: oldestKey)
            }
        }

        cache[key] = CachedFile(data: data, timestamp: Date())
    }

    func clear() {
        cache.removeAll()
    }

    private struct CachedFile {
        let data: Data
        let timestamp: Date
    }
}

// MARK: - Demonstration

func demonstrateStaticFileServing() {
    print("=== macOS Swift Static File Serving Examples ===\n")

    // Create test directory structure
    let testDirectory = "/tmp/static_file_test"
    let fileManager = FileManager.default

    try? fileManager.removeItem(atPath: testDirectory)
    try? fileManager.createDirectory(atPath: testDirectory, withIntermediateDirectories: true, attributes: nil)

    // Create sample files
    let indexPath = "\(testDirectory)/index.html"
    let cssPath = "\(testDirectory)/style.css"
    let jsPath = "\(testDirectory)/app.js"
    let subDir = "\(testDirectory)/assets"
    try? fileManager.createDirectory(atPath: subDir, withIntermediateDirectories: true, attributes: nil)

    try? "<html><body><h1>Test Page</h1></body></html>".write(toFile: indexPath, atomically: true, encoding: .utf8)
    try? "body { margin: 0; }".write(toFile: cssPath, atomically: true, encoding: .utf8)
    try? "console.log('Hello');".write(toFile: jsPath, atomically: true, encoding: .utf8)
    try? "Test".write(toFile: "\(subDir)/test.txt", atomically: true, encoding: .utf8)

    // 1. Basic file serving
    print("--- 1. Basic File Serving ---")
    var config = StaticFileConfig(rootDirectory: testDirectory)
    config.enableDirectoryBrowsing = true

    let server = StaticFileServer(config: config)

    // Test serving HTML file
    let response1 = server.serveFile(for: "/index.html")
    print("Served /index.html: \(response1.statusCode.rawValue)")
    if let contentType = response1.headers["Content-Type"] {
        print("  Content-Type: \(contentType)")
    }

    // Test serving CSS file
    let response2 = server.serveFile(for: "/style.css")
    print("Served /style.css: \(response2.statusCode.rawValue)")
    print("  Content-Type: \(response2.headers["Content-Type"] ?? "none")")

    // 2. Default file serving
    print("\n--- 2. Default File Serving ---")
    let response3 = server.serveFile(for: "/")
    print("Served / (default): \(response3.statusCode.rawValue)")

    // 3. Directory listing
    print("\n--- 3. Directory Listing ---")
    let response4 = server.serveFile(for: "/assets/")
    print("Served /assets/ (listing): \(response4.statusCode.rawValue)")

    // 4. 404 handling
    print("\n--- 4. 404 Handling ---")
    let response5 = server.serveFile(for: "/nonexistent.html")
    print("Served /nonexistent.html: \(response5.statusCode.rawValue)")

    // 5. Path traversal protection
    print("\n--- 5. Path Traversal Protection ---")
    let response6 = server.serveFile(for: "/../../../etc/passwd")
    print("Served ../../../etc/passwd: \(response6.statusCode.rawValue)")

    // 6. File type restriction
    print("\n--- 6. File Type Restriction ---")
    try? "test".write(toFile: "\(testDirectory)/test.exe", atomically: true, encoding: .utf8)
    let response7 = server.serveFile(for: "/test.exe")
    print("Served /test.exe: \(response7.statusCode.rawValue)")

    // 7. ETag generation
    print("\n--- 7. ETag Generation ---")
    config.enableETag = true
    let serverWithETag = StaticFileServer(config: config)
    let response8 = serverWithETag.serveFile(for: "/index.html")
    print("ETag: \(response8.headers["ETag"] ?? "none")")
    print("Cache-Control: \(response8.headers["Cache-Control"] ?? "none")")

    // Cleanup
    try? fileManager.removeItem(atPath: testDirectory)
    print("\nCleanup completed")

    print("\n=== Static File Serving Demo Completed ===")
}

// Run demonstration
demonstrateStaticFileServing()