| # AGENTS.md |
| |
| This file provides guidance to coding agents working with this repository. |
| |
| ## Project Overview |
| |
| Apache Traffic Server (ATS) is a high-performance HTTP/HTTPS caching proxy |
| server written in C++20. It uses an event-driven, multi-threaded architecture |
| with a sophisticated plugin system. |
| |
| **Key Technologies:** |
| - Language: C++20 |
| - Build System: CMake (migrated from autotools in v10) |
| - Testing: Catch2 (unit tests) + AuTest Python framework (end-to-end tests) |
| - Protocols: TLS, HTTP/1.1, HTTP/2, HTTP/3 (via Quiche) |
| |
| ## Project Structure |
| |
| Core sources live in `src/` (for example `src/proxy`, `src/iocore`, |
| `src/traffic_server`). Public headers are in `include/`. Built-in plugins are |
| in `plugins/` and `plugins/experimental/`. End-to-end tests are in `tests/`, |
| especially `tests/gold_tests/`. Build system files are in `cmake/` plus the |
| top-level `CMakeLists.txt`, and docs are in `doc/`. Third party libraries that |
| we include locally are in `lib/`. |
| |
| ## Codex Agent Quick Start |
| |
| Use this sequence for most tasks: |
| |
| ```bash |
| # Configure and build a dev tree. |
| cmake --preset dev |
| cmake --build build-dev |
| |
| # Run a focused unit test or test suite. |
| ctest --test-dir build-dev -j4 |
| |
| # Format before commit. |
| cmake --build build-dev -t format |
| ``` |
| |
| For environments using the default preset naming: |
| |
| ```bash |
| cmake --preset default |
| cmake --build build-default |
| ctest --test-dir build-default |
| cmake --build build-default -t format |
| ``` |
| |
| If this file drifts from current project conventions, run `/init` to |
| re-bootstrap agent guidance, then keep repository-specific commands and rules |
| below. |
| |
| ## Personal Preferences |
| |
| If `.codex/AGENTS.local.md` exists, load it for user-specific style preferences |
| and working conventions. This file is optional and should stay untracked. |
| |
| ### Key CMake Options |
| - `BUILD_EXPERIMENTAL_PLUGINS=ON` - Enable experimental plugins |
| - `ENABLE_QUICHE=ON` - QUIC/HTTP3 support |
| - `ENABLE_CRIPTS=ON` - Cripts scripting API |
| - `BUILD_REGRESSION_TESTING=ON` - Enable legacy test suite |
| - `ENABLE_ASAN=ON` - Configure ASan instrumentation |
| - `BUILD_TESTING=ON` - Enable building of the Catch2 tests |
| |
| ## Testing |
| |
| ### Unit Tests (Catch2) |
| Built automatically with the project. Run via ctest: |
| ```bash |
| ctest --test-dir build -j4 |
| ``` |
| |
| ### Running a Single Unit Test |
| Unit tests are built into executables. Find the test binary and run it directly: |
| ```bash |
| # Unit tests are typically in build/src/<component>/ |
| ./build/src/tscore/test_tscore |
| ``` |
| |
| ### End-to-End Tests (AuTest) |
| |
| **Enable autests during configuration:** |
| ```bash |
| cmake -B build -DENABLE_AUTEST=ON |
| cmake --build build |
| cmake --install build |
| ``` |
| |
| **Run all autests:** |
| ```bash |
| cmake --build build -t autest |
| ``` |
| |
| **Run specific test(s):** |
| ```bash |
| cd build/tests |
| ./autest.sh --sandbox /tmp/sbcodex --clean=none -f <test_name_without_test_py> |
| ``` |
| |
| For example, to run `cache-auth.test.py`: |
| ```bash |
| ./autest.sh --sandbox /tmp/sbcursor --clean=none -f cache-auth |
| ``` |
| |
| To run multiple tests efficiently, pass the -j option. |
| |
| ```bash |
| cd build/tests |
| ./autest.sh -j4 --sandbox /tmp/sbcodex --clean=none -f 'header_rewrite*' |
| ``` |
| |
| Most end-to-end test coverage is in `tests/gold_tests/`. The CI system uses the |
| Docker image `ci.trafficserver.apache.org/ats/fedora:43` (Fedora version updated |
| regularly). |
| |
| ### Writing Autests |
| |
| **New tests should use the `Test.ATSReplayTest()` approach**, which references a |
| `replay.yaml` file that describes the test configuration and traffic patterns |
| using the Proxy Verifier format. This is simpler, more maintainable, and |
| parseable by tools. |
| |
| If `ATSReplayTest` is not a good fit (say, the test needs a custom client), then |
| organize the test around a test class with member functions that configure any |
| servers, the ATS process, and the client. See |
| `tests/gold_tests/ats_probe/ats_probe.test.py` for an example of a test organized |
| around a test class. |
| |
| In autests, launch Python helpers with `{sys.executable}` rather than a |
| hardcoded `python3`, so the test runs under the same interpreter the harness |
| uses. |
| |
| **For complete details on writing autests, see:** |
| - `doc/developer-guide/testing/autests.en.rst` - Comprehensive guide to autest |
| - Proxy Verifier format: https://github.com/yahoo/proxy-verifier |
| - AuTest framework: https://autestsuite.bitbucket.io/ |
| |
| ## Development Workflow |
| |
| ### Code Formatting |
| Always format code before committing: |
| ```bash |
| cmake --build build -t format |
| ``` |
| |
| ### Before Commit Checklist |
| - Keep scope tight and avoid unrelated file churn. |
| - Run formatter: `cmake --build build -t format` (or `build-dev` when used). |
| - Run targeted tests for changed areas (or explain why tests were skipped). |
| - Keep commit message body wrapped to 72 characters per line. |
| - Describe why the change was needed, not only what changed. |
| |
| ### Editing Safety |
| - Do not revert unrelated working tree changes. |
| - Prefer minimal diffs over broad refactors unless requested. |
| - Do not edit generated artifacts unless the task explicitly requires it. |
| - When touching behavior, add or update tests when practical. |
| |
| ### Git Workflow |
| - Branch off `master` for almost all PRs |
| - PRs must pass all Jenkins CI jobs before merging |
| - Use the GitHub PR workflow (not Jira) |
| - Set appropriate labels: **Backport**, **WIP**, etc. |
| |
| ### Commit Message Format |
| When an agent creates commits, use a short imperative summary line (under 50 |
| characters when practical) plus concise body text (1-3 sentences) focused on |
| "why" rather than only "what". If the PR fixes an issue, add 'Fixes: |
| #<issue_number>'. Keep commit message body lines to 72 characters. |
| |
| ## Architecture Overview |
| |
| ### Core Components |
| |
| **I/O Core (`src/iocore/`):** |
| - `eventsystem/` - Event-driven engine (Continuations, Events, Processors) |
| - `cache/` - Disk and RAM cache implementation |
| - `net/` - Network layer with TLS and QUIC support |
| - `dns/` - Asynchronous DNS resolution |
| - `hostdb/` - Internal DNS cache |
| - `aio/` - Asynchronous I/O |
| |
| **Proxy Logic (`src/proxy/`):** |
| - `http/` - HTTP/1.1 protocol implementation |
| - `http2/` - HTTP/2 support |
| - `http3/` - HTTP/3 implementation |
| - `hdrs/` - Header parsing and management |
| - `logging/` - Flexible logging system |
| - `http/remap/` - URL remapping and routing |
| |
| **Management (`src/mgmt/`):** |
| - JSONRPC server for runtime configuration and management |
| - Configuration file parsing and validation |
| |
| **Base Libraries (`src/`):** |
| - `tscore/` - Core utilities and data structures |
| - `tsutil/` - Core utilities (metrics, debugging, regex, etc.) |
| - `api/` - Plugin API implementation |
| - `tscpp/api/` - C++ API wrapper for plugins |
| - `cripts/` - Cripts scripting framework for plugins |
| |
| ### Event-Driven Architecture |
| |
| ATS uses a **Continuation-based** programming model: |
| - All async operations use Continuations (callback objects) |
| - Events are dispatched through an event system |
| - Multiple thread pools handle different event types |
| - Non-blocking I/O throughout |
| |
| ### Configuration Files |
| |
| Primary configs (installed to `/etc/trafficserver/` by default): |
| - `records.yaml` - Main configuration (formerly records.config) |
| - `remap.config` - URL remapping rules |
| - `plugin.config` - Plugin loading configuration |
| - `ip_allow.yaml` - IP access control |
| - `ssl_multicert.config` - TLS certificate configuration |
| - `sni.yaml` - SNI-based routing |
| - `storage.config` - Cache storage configuration |
| |
| Configuration can be modified at runtime via: |
| - `traffic_ctl config reload` (for some settings) |
| - JSONRPC API |
| |
| ## Plugin Development |
| |
| ### Plugin Types |
| - **Global plugins** - Loaded in `plugin.config`, affect all requests |
| - **Remap plugins** - Loaded per remap rule, affect specific mapped requests |
| |
| ### Key Plugin APIs |
| Headers in `include/ts/`: |
| - `ts.h` - Main plugin API |
| - `remap.h` - Remap plugin API |
| - `InkAPIPrivateIOCore.h` - Advanced internal APIs |
| |
| ### Plugin Hooks |
| Plugins register callbacks at various points in request processing: |
| - `TS_HTTP_READ_REQUEST_HDR_HOOK` |
| - `TS_HTTP_SEND_REQUEST_HDR_HOOK` |
| - `TS_HTTP_READ_RESPONSE_HDR_HOOK` |
| - `TS_HTTP_SEND_RESPONSE_HDR_HOOK` |
| - Many more (see `ts.h`) |
| |
| ### Example Plugins |
| - `example/plugins/` - Simple example plugins |
| - `plugins/` - Stable core plugins |
| - `plugins/experimental/` - Experimental plugins |
| |
| ## Common Development Patterns |
| |
| ### When Modifying HTTP Processing |
| 1. Understand the state machine: `src/proxy/http/HttpSM.cc` - HTTP State Machine |
| 2. Hook into the appropriate stage via plugin hooks or core modification |
| 3. Use `HttpTxn` objects to access transaction state |
| 4. Headers are accessed via `HDRHandle` and field APIs |
| |
| ### When Adding Configuration |
| 1. Define record in `src/records/RecordsConfig.cc` |
| 2. Add validation if needed |
| 3. Update documentation in `doc/admin-guide/` |
| 4. Configuration can be read via `REC_` APIs |
| |
| ### When Working with Cache |
| - Cache is content-addressable, keyed by URL (modifiable via plugins) |
| - Cache operations are async, continuation-based |
| - Cache has RAM and disk tiers |
| - Cache code is in `src/iocore/cache/` |
| |
| ### When Debugging |
| 1. Enable debug tags in `records.yaml`: |
| ```yaml |
| proxy.config.diags.debug.enabled: 1 |
| proxy.config.diags.debug.tags: http|cache |
| ``` |
| 2. Check logs in `/var/log/trafficserver/`: |
| - `diags.log` - Debug output |
| - `error.log` - Errors and warnings |
| 3. Use `traffic_top` for live statistics |
| 4. Use `traffic_ctl` for runtime inspection |
| |
| **Debug Controls in Code:** |
| ```cpp |
| static DbgCtl dbg_ctl{"my_component"}; |
| SMDebug(dbg_ctl, "Processing request for URL: %s", url); |
| ``` |
| |
| ## Important Conventions |
| |
| ### License Headers |
| - Always add Apache License 2.0 headers to the top of new source and test files |
| - This includes `.cc`, `.h`, `.py`, and other code files |
| - Follow the existing license header format used in the codebase |
| |
| ### Code Style |
| - `.editorconfig` and `.clang-format` is the source of truth for baseline formatting rules. |
| - C++20 standard (nothing from C++23 or later) |
| - Use RAII principles |
| - Prefer smart pointers for ownership |
| - Don't use templates unless needed and appropriate |
| - Run `cmake --build build -t format` before committing |
| - Source code line length: 132 characters maximum |
| - Don't add comments where the code documents itself, don't comment AI interactions |
| |
| **C++ Formatting (Mozilla-based style):** |
| - Indentation: 2 spaces for C/C++ |
| - Braces: Linux style (opening brace on same line) |
| - Pointer alignment: Right (`Type *ptr`, not `Type* ptr`) |
| - Variable declarations: Add empty line after declarations before subsequent code |
| - Avoid naked conditions (always use braces with if statements) |
| |
| **Naming Conventions:** |
| - CamelCase for classes: `HttpSM`, `NetVConnection` |
| - snake_case for variables and functions: `server_entry`, `handle_api_return()` |
| - UPPER_CASE for macros and constants: `HTTP_SM_SET_DEFAULT_HANDLER` |
| - Private member variables use both `_` and `m_` prefixes in the source code; |
| be consistent with the surrounding code. For new files, prefer the `_` prefix |
| because that reflects the community consensus. |
| - Boolean variables and functions returning boolean values are named as |
| predicates: use `was_modified` rather than `modified`. |
| |
| **Doxygen Comments:** |
| |
| When adding doxygen comments: |
| |
| - `@brief` is assumed for the first sentence, so give a brief summary right |
| after `/** ` without using `@brief`. |
| - In the description of classes, functions, and member variables, convey the |
| responsibility of the item being described (its role and intent), not just |
| what the code obviously does. |
| - Use `@a <name>` to reference a function argument by name in prose |
| (e.g. "If @a size is zero..."). Use `@c <text>` for inline code or |
| constants (e.g. `@c true`, `@c NULL`, `@c MyEnum::VALUE`). |
| - Use `@ref`, `@see`, or `@sa` to cross-reference related types or functions |
| when that helps convey how items interact. |
| - Use `@param` with `[in]`, `[out]`, or `[in,out]` to indicate the |
| parameter's direction, followed by a description of its meaning. |
| - Use `@return` to describe the semantics of the returned value. Don't |
| restate the type; that is obvious from the signature and rendered docs. |
| - Use `@note` for non-obvious caveats and `@warning` for hazards (e.g. lock |
| ordering, lifetime, or threading constraints). |
| - Use `@code` ... `@endcode` for embedded usage examples. |
| - For templates, document type parameters with `@tparam`. |
| |
| Conventions specific to this codebase: |
| |
| - Every new header file should start with a `/** @file` block (see existing |
| headers in `include/` for the standard license/section layout). |
| - Prefer trailing briefs for data members and enumerators, e.g. |
| `int max_conns{0}; ///< Maximum concurrent connections.` |
| - Use single-line `///` briefs for short function or type docs where a full |
| `/** ... */` block would be overkill. |
| |
| **Modern C++ Patterns (Preferred):** |
| ```cpp |
| // GOOD - Modern C++20 |
| auto buffer = std::make_unique<MIOBuffer>(alloc_index); |
| for (const auto &entry : container) { |
| if (auto *vc = entry.get_vc(); vc != nullptr) { |
| // Process vc |
| } |
| } |
| |
| // AVOID - Legacy C-style |
| MIOBuffer *buffer = (MIOBuffer*)malloc(sizeof(MIOBuffer)); |
| ``` |
| |
| ### Python Code Style (for tests and tools) |
| - Python 3.11+ with proper type annotations |
| - 4-space indentation, never TABs |
| - Type annotations on all function signatures |
| - Prefer f-strings over `str.format()` when building command lines, config lines, |
| and `Testers` expressions. |
| |
| ### Memory Management |
| - Custom allocators supported (jemalloc, mimalloc) |
| - Use `ats_malloc` family for large allocations |
| - IOBuffers for network data (zero-copy where possible) |
| |
| ### Threading |
| - Event threads handle most work |
| - DNS has dedicated threads |
| - Disk I/O uses thread pool |
| - Most code should be async/event-driven, not thread-based |
| |
| ### Error Handling |
| - Return error codes for recoverable errors |
| - Use `ink_release_assert` for unrecoverable errors |
| - Log errors appropriately (ERROR vs WARNING vs NOTE) |
| |
| ## Key Files for Understanding Architecture |
| |
| - `include/iocore/eventsystem/Continuation.h` - Core async pattern |
| - `src/proxy/http/HttpSM.cc` - HTTP request state machine |
| - `src/iocore/net/UnixNetVConnection.cc` - Network connection handling |
| - `src/iocore/cache/Cache.cc` - Cache implementation |
| - `src/proxy/http/remap/RemapConfig.cc` - URL remapping logic |
| - `include/ts/ts.h` - Plugin API |
| |
| ## Security |
| |
| See [SECURITY.md](SECURITY.md) for the project's security policy, threat model, |
| scope, and vulnerability reporting process. |
| |
| ## Resources |
| |
| - Official docs: https://trafficserver.apache.org/ |
| - Developer wiki: https://github.com/apache/trafficserver/wiki |
| - CI dashboard: https://ci.trafficserver.apache.org/ |
| - AuTest framework: https://autestsuite.bitbucket.io/ |
| - Proxy Verifier: https://github.com/yahoo/proxy-verifier |