diff --git a/AGENTS.md b/AGENTS.md new file mode 120000 index 0000000..681311e --- /dev/null +++ b/AGENTS.md @@ -0,0 +1 @@ +CLAUDE.md \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..2d10647 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,84 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Overview + +GCDWebServer is a lightweight, GCD-based HTTP 1.1 server written in Objective-C (ARC) for embedding in iOS, macOS, and tvOS apps. It has no third-party dependencies. This fork has bumped the deployment targets to iOS 16 / tvOS 16 / macOS 12 (the upstream README still documents the original iOS 8 / tvOS 9 / macOS 10.7 minimums and the CocoaPods podspec still declares 8.0/9.0/10.7). + +Not supported by design: keep-alive connections and HTTPS. + +## Build & Test + +There is no Swift Package Manager `Package.swift`; the build is driven entirely by `GCDWebServer.xcodeproj` (and CocoaPods for consumers). + +Schemes (`xcodebuild -list -project GCDWebServer.xcodeproj`): +- `GCDWebServer (Mac|iOS|tvOS)` — the static library / framework per platform. +- `GCDWebServers (Mac|iOS|tvOS)` — the framework target plus the XCTest unit tests (`Frameworks/Tests.m`). +- `Build All`. + +Run the unit tests (XCTest): +```sh +xcodebuild test -scheme "GCDWebServers (Mac)" +``` + +Run a single XCTest method: +```sh +xcodebuild test -scheme "GCDWebServers (Mac)" -only-testing:Tests/Tests/testPaths +``` + +Full CI test suite (builds for all platforms at oldest + current deployment targets, then runs the request/response replay tests): +```sh +./Run-Tests.sh +``` + +`Run-Tests.sh` does the bulk of the real testing. It builds the `GCDWebServer (Mac)` target, then runs the resulting command-line `GCDWebServer` executable in test modes (`webServer`, `webDAV`, `htmlForm`, `htmlFileUpload`, `webUploader`) against recorded fixtures. + +### How the fixture-replay tests work + +The `Tests/` directory holds recorded HTTP exchanges, not code. Each test case is a pair of files: `NNN-.request` (raw bytes sent to the server) and `NNN-.response` (expected raw response bytes). The test runner (`-mode -root -tests `) replays each `.request` against a server rooted at an extracted copy of `Tests/Payload.zip` and byte-compares the reply to the `.response`. To add coverage for a new behavior, add a matching `.request`/`.response` pair to the relevant `Tests/` directory rather than writing new XCTest code. + +## Formatting + +Source style is enforced by clang-format (Google base style, see `.clang-format`) for Objective-C and SwiftFormat for the Swift example apps. Run before committing: +```sh +./format-source.sh +``` +Note: `format-source.sh` pins exact tool versions (clang-format 9.0.0, SwiftFormat 0.44.5) and will refuse to run otherwise. + +## Architecture + +The entire library is built around 4 core classes in `GCDWebServer/Core/`: +- **GCDWebServer** — owns the listening socket and the ordered list of handlers. Manages start/stop, options, Bonjour, NAT port mapping, and (on iOS) automatic suspend/resume across foreground/background transitions. +- **GCDWebServerConnection** — one instance per open HTTP connection, lives until the connection closes. Drives reading the request and writing the response. Subclassable via hooks (it's exposed but not used directly). +- **GCDWebServerRequest** — created once HTTP headers arrive; wraps the request and consumes the body. Subclasses in `GCDWebServer/Requests/` choose how the body is handled (in memory, streamed to disk, parsed as a form, etc.). +- **GCDWebServerResponse** — produced by a handler; wraps response headers and an optional body. Subclasses in `GCDWebServer/Responses/` cover data-in-memory, file-on-disk, streamed, and error responses. + +`GCDWebServer/Core/GCDWebServerFunctions.{h,m}` holds shared C helpers (e.g. `GCDWebServerNormalizePath`, MIME-type and date helpers). `GCDWebServerPrivate.h` is the internal/private header (including the logging-facility abstraction). `GCDWebServerHTTPStatusCodes.h` enumerates status codes. + +### Handler model + +A request is matched and processed by **handlers** added to the server, evaluated in **LIFO order** (last added wins). Each handler is two GCD blocks: +- `GCDWebServerMatchBlock` — runs as soon as headers are received; inspects method/URL/headers and returns a `GCDWebServerRequest` subclass instance to claim the request, or `nil` to pass. +- `GCDWebServerProcessBlock` (sync) or `GCDWebServerAsyncProcessBlock` (async) — runs after the full request body is received and returns a `GCDWebServerResponse` (or `nil`/error response → 500). + +Handlers run on **arbitrary GCD threads**, so handler code must be thread-safe and re-entrant. + +### Extensions (subclasses of GCDWebServer) + +- `GCDWebUploader/` — `GCDWebUploader`, an HTML5 web UI for uploading/downloading/managing files in a directory. Ships front-end assets in `GCDWebUploader.bundle`. +- `GCDWebDAVServer/` — `GCDWebDAVServer`, a class-1 WebDAV server (partial class-2 for macOS Finder). Depends on `libxml2`. + +### Example apps & framework packaging + +- `Mac/main.m` — macOS command-line example (also serves as the test-runner executable). +- `iOS/`, `tvOS/` — Swift example apps (`AppDelegate.swift`, `ViewController.swift`). +- `Frameworks/` — umbrella header (`GCDWebServers.h`), module map, and the XCTest target source (`Tests.m`). + +## Consumer linking requirements + +When integrated manually (not via CocoaPods), consuming apps must link `libz`, and WebDAV additionally needs `libxml2` with `$(SDKROOT)/usr/include/libxml2` on the header search path. The `GCDWebServer.podspec` defines three subspecs: `Core` (default), `WebDAV`, and `WebUploader`. + +## Logging & debug builds + +Define `DEBUG=1` in `GCC_PREPROCESSOR_DEFINITIONS` to enable verbose logging plus internal consistency checks. Runtime verbosity is controlled via `+[GCDWebServer setLogLevel:]`. If XLFacility is present in the same Xcode project, GCDWebServer routes logging through it automatically (see `GCDWebServerPrivate.h`).