Compare commits

..

1 commit

Author SHA1 Message Date
Claude
a9fdd6599d
Change wantedScripts to ordered list format
This ensures scripts execute in the order they appear in the config file,
resolving the TODO in the README. The config format has been changed from
a table with script names as keys to an ordered list of script entries.

Changes:
- ctx.lua: Use ipairs() instead of pairs() to iterate in order
- config.lua: Update validation to handle new list structure
- conf.lua: Update example config to use new format
- README.md: Remove TODO and clarify execution order

New config format:
wantedScripts = {
    {name = 'script1', config = {...}},
    {name = 'script2', config = {...}}
}
2025-11-22 04:37:40 +00:00

135
CLAUDE.md
View file

@ -1,135 +0,0 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
aproxy is an Activity Pub Reverse Proxy Framework built on OpenResty (NGINX + LuaJIT). It provides a modular script system to add filtering and protection capabilities in front of ActivityPub implementations.
## Development Commands
### Testing
```sh
# Install test dependencies (only needed once)
make testdeps
eval (luarocks-5.1 path --bin)
# Run test suite
make test
```
The test suite uses luajit and luaunit for testing. Tests are located in the `tests/` directory.
## Architecture
### Core Components
- **main.lua**: Entry point with two hooks:
- `init()`: Validates configuration at startup
- `access()`: Called on every request to execute the filter chain
- **config.lua**: Configuration system
- Searches for `conf.lua` in paths: `.;/etc/aproxy` (or `$APROXY_CONFIG_PATH`)
- Provides schema validation framework
- Schema supports types: `string`, `number`, `table`, `list` (array of values)
- **ctx.lua**: Request context and filter chain executor
- Loads scripts from config and builds `compiled_chain`
- Matches request URIs against script PCRE regexes
- Executes matching callbacks sequentially
- If any callback returns a status code, request is terminated with that response
- **util.lua**: Lua standard library extensions
- `table.readonly()`: Create read-only table wrapper
- `table.pprint()`: Pretty-print nested tables
- `string.split()`: Split strings by separator
### Script Module Structure
Scripts live in `scripts/` and must export:
```lua
return {
name = 'ModuleName',
author = 'email',
title = 'Short Title',
description = [[Long description]],
version = 1,
-- Called once at startup with config
-- Return value becomes module state
init = function(cfg)
return state
end,
-- Map of PCRE regex patterns to callback functions
callbacks = {
['/api/path'] = function(cfg, state)
-- Return nil to allow request
-- Return status_code, body to block request
return nil
end
},
-- Schema for validating this module's config
config = {
['field_name'] = {
type = 'string|number|table|list',
schema = {...}, -- for table/list types
description = 'field description'
}
}
}
```
**Important**: Module configs are made read-only via `table.readonly()` before being passed to callbacks. Attempting to modify them will error.
### Request Flow
1. OpenResty calls `aproxy.main.access()` on each request
2. `ctx:onRequest()` iterates through `compiled_chain`
3. For each script, check if request URI matches any callback regex
4. Execute matching callbacks with their config and state
5. If callback returns `(status_code, body)`, terminate request with that response
6. If callback returns `nil`, continue to next callback
7. If no callbacks block the request, pass through to backend
### Testing Framework
Tests use a mock `ngx` object (created by `createNgx()` in test.lua) that simulates OpenResty's API:
- `ngx.var.uri`: Request URI
- `ngx.req.get_uri_args()`: Query parameters
- `ngx.req.get_headers()`: Request headers
- `ngx.status`, `ngx.say()`, `ngx.exit()`: Response control
- `ngx.re.match()`: PCRE regex matching via rex_pcre2
Use `setupTest(module_path, config)` to initialize a module for testing and `setupFakeRequest(path, options)` to simulate requests.
To run the test suite:
```sh
# needed only once ever to setup the environment
make testdeps
# run once on any new shell
eval (luarocks-5.1 path --bin)
# actually run suite
make test
```
## Configuration
The default config file (`conf.lua`) structure:
```lua
return {
version = 1,
wantedScripts = {
['script_name'] = {
-- script-specific config matching its schema
}
}
}
```
Scripts are loaded from `scripts/{script_name}.lua` based on keys in `wantedScripts`.