This file provides guidance to coding agents working with this repository.
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)
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/.
Use this sequence for most tasks:
# 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 formatFor environments using the default preset naming:
cmake --preset default
cmake --build build-default
ctest --test-dir build-default
cmake --build build-default -t formatIf this file drifts from current project conventions, run /init to
re-bootstrap agent guidance, then keep repository-specific commands and rules
below.
If .codex/AGENTS.local.md exists, load it for user-specific style preferences
and working conventions. This file is optional and should stay untracked.
BUILD_EXPERIMENTAL_PLUGINS=ON- Enable experimental pluginsENABLE_QUICHE=ON- QUIC/HTTP3 supportENABLE_CRIPTS=ON- Cripts scripting APIBUILD_REGRESSION_TESTING=ON- Enable legacy test suiteENABLE_ASAN=ON- Configure ASan instrumentationBUILD_TESTING=ON- Enable building of the Catch2 tests
Built automatically with the project. Run via ctest:
ctest --test-dir build -j4Unit tests are built into executables. Find the test binary and run it directly:
# Unit tests are typically in build/src/<component>/
./build/src/tscore/test_tscoreEnable autests during configuration:
cmake -B build -DENABLE_AUTEST=ON
cmake --build build
cmake --install buildRun all autests:
cmake --build build -t autestRun specific test(s):
cd build/tests
./autest.sh --sandbox /tmp/sbcodex --clean=none -f <test_name_without_test_py>For example, to run cache-auth.test.py:
./autest.sh --sandbox /tmp/sbcursor --clean=none -f cache-authTo run multiple tests efficiently, pass the -j option.
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).
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.
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/
Always format code before committing:
cmake --build build -t format- Keep scope tight and avoid unrelated file churn.
- Run formatter:
cmake --build build -t format(orbuild-devwhen 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.
- 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.
- Branch off
masterfor 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.
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.
I/O Core (src/iocore/):
eventsystem/- Event-driven engine (Continuations, Events, Processors)cache/- Disk and RAM cache implementationnet/- Network layer with TLS and QUIC supportdns/- Asynchronous DNS resolutionhostdb/- Internal DNS cacheaio/- Asynchronous I/O
Proxy Logic (src/proxy/):
http/- HTTP/1.1 protocol implementationhttp2/- HTTP/2 supporthttp3/- HTTP/3 implementationhdrs/- Header parsing and managementlogging/- Flexible logging systemhttp/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 structurestsutil/- Core utilities (metrics, debugging, regex, etc.)api/- Plugin API implementationtscpp/api/- C++ API wrapper for pluginscripts/- Cripts scripting framework for plugins
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
Primary configs (installed to /etc/trafficserver/ by default):
records.yaml- Main configuration (formerly records.config)remap.config- URL remapping rulesplugin.config- Plugin loading configurationip_allow.yaml- IP access controlssl_multicert.config- TLS certificate configurationsni.yaml- SNI-based routingstorage.config- Cache storage configuration
Configuration can be modified at runtime via:
traffic_ctl config reload(for some settings)- JSONRPC API
- Global plugins - Loaded in
plugin.config, affect all requests - Remap plugins - Loaded per remap rule, affect specific mapped requests
Headers in include/ts/:
ts.h- Main plugin APIremap.h- Remap plugin APIInkAPIPrivateIOCore.h- Advanced internal APIs
Plugins register callbacks at various points in request processing:
TS_HTTP_READ_REQUEST_HDR_HOOKTS_HTTP_SEND_REQUEST_HDR_HOOKTS_HTTP_READ_RESPONSE_HDR_HOOKTS_HTTP_SEND_RESPONSE_HDR_HOOK- Many more (see
ts.h)
example/plugins/- Simple example pluginsplugins/- Stable core pluginsplugins/experimental/- Experimental plugins
- Understand the state machine:
src/proxy/http/HttpSM.cc- HTTP State Machine - Hook into the appropriate stage via plugin hooks or core modification
- Use
HttpTxnobjects to access transaction state - Headers are accessed via
HDRHandleand field APIs
- Define record in
src/records/RecordsConfig.cc - Add validation if needed
- Update documentation in
doc/admin-guide/ - Configuration can be read via
REC_APIs
- 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/
- Enable debug tags in
records.yaml:proxy.config.diags.debug.enabled: 1 proxy.config.diags.debug.tags: http|cache
- Check logs in
/var/log/trafficserver/:diags.log- Debug outputerror.log- Errors and warnings
- Use
traffic_topfor live statistics - Use
traffic_ctlfor runtime inspection
Debug Controls in Code:
static DbgCtl dbg_ctl{"my_component"};
SMDebug(dbg_ctl, "Processing request for URL: %s", url);- 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
.editorconfigand.clang-formatis 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 formatbefore 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, notType* 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 have the
m_prefix.
Modern C++ Patterns (Preferred):
// 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 3.11+ with proper type annotations
- 4-space indentation, never TABs
- Custom allocators supported (jemalloc, mimalloc)
- Use
ats_mallocfamily for large allocations - IOBuffers for network data (zero-copy where possible)
- 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
- Return error codes for recoverable errors
- Use
ink_release_assertfor unrecoverable errors - Log errors appropriately (ERROR vs WARNING vs NOTE)
include/iocore/eventsystem/Continuation.h- Core async patternsrc/proxy/http/HttpSM.cc- HTTP request state machinesrc/iocore/net/UnixNetVConnection.cc- Network connection handlingsrc/iocore/cache/Cache.cc- Cache implementationsrc/proxy/http/remap/RemapConfig.cc- URL remapping logicinclude/ts/ts.h- Plugin API
- Official docs: https://trafficserver.apache.org/
- Developer wiki: https://cwiki.apache.org/confluence/display/TS/
- CI dashboard: https://ci.trafficserver.apache.org/
- AuTest framework: https://autestsuite.bitbucket.io/
- Proxy Verifier: https://github.com/yahoo/proxy-verifier