# Request Sieve 0.1.0 Select Nginx JSONL records by exact host, raw request URI and time. Matching lines leave the program as their original bytes, not reserialized JSON. Python 3.9 or newer. Standard library only. No installation, network access, accounts or telemetry. MIT licensed. ## Run it Extract the release archive, enter its directory, then run: ```sh python3 request_sieve.py --host app.example \ --uri '/report?a=1&b=2' --since 1700000000 examples/access.jsonl ``` The included synthetic example produces exactly: ```json {"epoch":1700000000.125,"host":"app.example","uri":"/report?a=1&b=2","status":200} ``` Use a file, or omit the filename to read stdin: ```sh python3 request_sieve.py --host app.example access.jsonl > selected.jsonl cat access.jsonl | python3 request_sieve.py --uri '/health?full=1' python3 request_sieve.py --since 1700000000 --before 1700000060 access.jsonl python3 request_sieve.py --help ``` Do not redirect output to your input file: the shell would truncate it before the program starts. On an error, stdout can contain earlier matching records. Check the exit status before treating an output file as complete. ## Input contract Each line must be a UTF-8 JSON object with these fields: | Field | Value | | --- | --- | | `host` | A nonempty string, normally Nginx `$host`. | | `uri` | A nonempty string, normally Nginx `$request_uri`, including the original query. | | `epoch` | Finite decimal Unix seconds, as a JSON number or numeric string, normally `$msec`. | Other fields are allowed and retained. Required fields are validated on every record, including records that do not match. Duplicate object keys, blank lines, invalid UTF-8, malformed JSON, nonstandard `NaN`/`Infinity` constants, missing fields and invalid field types stop processing with a line-numbered diagnostic. Diagnostics do not include log contents. UTF-8 BOMs are not accepted. The program does not parse Nginx's combined/text log format. A matching Nginx configuration example is in `examples/nginx-log-format.conf`. Review it for your server rather than replacing your existing configuration blindly. Do not publish real access logs; URLs and other fields can contain private data. ## Matching rules - `--host HOST`: exact, case-sensitive string equality. Repeat to accept several hosts. - `--uri URI`: exact, case-sensitive string equality. Repeat to accept several URIs. - Different filter categories are combined with AND. - No decoding, query sorting, substring matching, wildcards or regular expressions. `/a?x=1&y=2`, `/a?y=2&x=1` and `/a?x=%31&y=2` are distinct. - `--since SECONDS` includes the boundary; `--before SECONDS` excludes it. If both are supplied, `--before` must be greater than `--since`. - Time comparisons use decimal arithmetic, not binary floating point. Numeric strings and CLI limits may use a sign, decimal point or exponent, but not whitespace, separators, `NaN` or infinity. - With no filters, all valid records are emitted. Empty input and no matches succeed. - `-` selects stdin explicitly. Only one input file is accepted per invocation. The original spaces, key order, Unicode bytes, line endings and missing final newline are preserved for matching records. Processing streams one line at a time; memory depends on the longest input line and its decoded JSON object. The program reads a finite stream; it does not follow a growing file. ## Exit status | Code | Meaning | | --- | --- | | `0` | Successful processing, including zero matches, or a consumer closing the output pipe. | | `1` | Invalid input record or an input/output error. Earlier output may be partial. | | `2` | Invalid command-line arguments. | A closed output pipe stops processing quietly, so later input is not validated. The script does not determine crawler identity, perform DNS lookups or infer anything about a request beyond the filters supplied by its operator. ## Verify the release From the extracted directory: ```sh python3 tests/test_cli.py ``` These black-box checks run the CLI as a real subprocess with synthetic data. They cover exact matching, repeated filters, decimal boundaries, byte preservation, malformed input, partial output, file errors and a closed output pipe. ## Attribution and license Developed by an AI assistant under Ryan's direction. Ryan operates this release site. Request Sieve is an independent utility, not affiliated with the Nginx project. All packaged example records are synthetic. This is the first release; no earlier release history or user adoption is claimed. The software and included documentation are available under the MIT License in `LICENSE`.