Files
FlociClone/docs/services/textract.md
2026-09-22 08:57:00 -04:00

124 lines
5.1 KiB
Markdown

# Textract
**Protocol:** JSON 1.1
**Header:** `X-Amz-Target: Textract.<Action>`
Floci emulates the AWS Textract API with a dummy response stub. The response shape matches the real AWS Textract contracts so AWS SDK and CLI clients accept the reply without error. No real OCR or document analysis is performed: every call returns a fixed set of `Block` objects with synthetic metadata.
## Supported Operations
| Operation | Notes |
|-----------|-------|
| `DetectDocumentText` | Returns stub PAGE + LINE + WORD blocks |
| `AnalyzeDocument` | Returns stub blocks; `FeatureTypes` accepted but ignored |
| `StartDocumentTextDetection` | Returns a `JobId`; job is immediately SUCCEEDED |
| `GetDocumentTextDetection` | Returns `SUCCEEDED` + stub blocks for a known `JobId` |
| `StartDocumentAnalysis` | Returns a `JobId`; job is immediately SUCCEEDED |
| `GetDocumentAnalysis` | Returns `SUCCEEDED` + stub blocks for a known `JobId` |
`Document` and `DocumentLocation` inputs (bytes or S3 references) are accepted but not parsed.
### Block shape
Each response includes a 3-block hierarchy matching the [AWS Block API shape](https://docs.aws.amazon.com/textract/latest/dg/API_Block.html):
| BlockType | Text | Relationships |
|-----------|------|---------------|
| `PAGE` | *(none)* | CHILD → LINE |
| `LINE` | `"Floci"` | CHILD → WORD |
| `WORD` | `"Floci"` | *(none)* |
Every block includes: `Id` (UUID), `Confidence` (99.9), `Page` (1), and a `Geometry` with `BoundingBox` + 4-point `Polygon`.
### Async job lifecycle
`Start*` operations store a job ID and its result in memory and return the ID immediately. `Get*` calls with a valid job ID return `JobStatus: SUCCEEDED` and the same result every time, so a result can be fetched repeatedly. A job is retained for 7 days, after which it expires and `Get*` returns `InvalidJobIdException`; expired jobs are also swept when a new job is stored. The store is capped at 10,000 jobs: once the cap is reached the oldest job is evicted first, which AWS does not do, so a job that is still inside its 7-day window can read as `InvalidJobIdException` once enough newer jobs exist. Job IDs are not persisted across restarts. Using a `GetDocumentTextDetection` job ID in `GetDocumentAnalysis` (or vice-versa) returns `InvalidJobIdException`.
## Configuration
| Variable | Default | Description |
|---|---|---|
| `FLOCI_SERVICES_TEXTRACT_ENABLED` | `true` | Enable or disable the service |
| `AI_MOCK_CONFIG` | unset | Path to a shared mock-response config file — see "Mock Responses" below |
## Mock Responses
`DetectDocumentText` and `AnalyzeDocument` return the same stub `Block` list for every
call by default. To exercise application logic that reads the detected text, point
`AI_MOCK_CONFIG` at a JSON file shared across Textract, Comprehend, and Rekognition:
```json
{
"textract": {
"my-bucket/invoice.pdf": {
"DetectDocumentText": {
"DocumentMetadata": { "Pages": 1 },
"Blocks": [{ "BlockType": "LINE", "Id": "line-1", "Confidence": 99.5, "Text": "Invoice Total: $42.00" }],
"DetectDocumentTextModelVersion": "1.0"
}
}
}
}
```
The lookup key is **`"<Bucket>/<Name>"`** from `Document.S3Object`. A `Bytes`-backed
`Document` has no such key, so mocking only applies to S3Object-based calls — a
`Bytes`-backed request always gets the default stub. The file is re-read when its
modification time changes, so it can be edited without restarting the emulator. A missing
file, an unset `AI_MOCK_CONFIG`, or no matching entry all fall back to the default stub.
The async `Start*`/`Get*` job flow does not support mocking.
## Examples
```bash
export AWS_ENDPOINT_URL=http://localhost:4566
export AWS_DEFAULT_REGION=us-east-1
export AWS_ACCESS_KEY_ID=test
export AWS_SECRET_ACCESS_KEY=test
# DetectDocumentText
aws textract detect-document-text \
--document '{"S3Object":{"Bucket":"my-bucket","Name":"test.pdf"}}'
# AnalyzeDocument
aws textract analyze-document \
--document '{"S3Object":{"Bucket":"my-bucket","Name":"test.pdf"}}' \
--feature-types TABLES FORMS
# Async: start + poll
JOB_ID=$(aws textract start-document-text-detection \
--document-location '{"S3Object":{"Bucket":"my-bucket","Name":"test.pdf"}}' \
--query JobId --output text)
aws textract get-document-text-detection --job-id "$JOB_ID"
```
```python
import boto3
client = boto3.client("textract", endpoint_url="http://localhost:4566")
# Sync
resp = client.detect_document_text(
Document={"S3Object": {"Bucket": "my-bucket", "Name": "test.pdf"}}
)
for block in resp["Blocks"]:
print(block["BlockType"], block.get("Text", ""))
# Async
job = client.start_document_text_detection(
DocumentLocation={"S3Object": {"Bucket": "my-bucket", "Name": "test.pdf"}}
)
result = client.get_document_text_detection(JobId=job["JobId"])
print(result["JobStatus"]) # SUCCEEDED
```
## Out of Scope
- Real OCR or document analysis (always returns a fixed stub block list).
- `AnalyzeExpense`, `AnalyzeID`, `AnalyzeLendingDocument` and other specialized analysis operations.
- `GetAdapterVersion`, `CreateAdapter`, `ListAdapters` (Adapter management API).
- `GetDocumentTextDetection` / `GetDocumentAnalysis` pagination via `NextToken`.
- Persistent job storage across restarts.