feat(docs): clean up docs and make dev ex easier with variables
This commit is contained in:
parent
68f5da509b
commit
f7874f4541
21
README.md
21
README.md
|
|
@ -142,6 +142,25 @@ volumes:
|
||||||
|
|
||||||
### Environment Variables
|
### Environment Variables
|
||||||
|
|
||||||
|
#### Port Configuration
|
||||||
|
|
||||||
|
Readur supports flexible port configuration:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Method 1: Specify full server address
|
||||||
|
SERVER_ADDRESS=0.0.0.0:3000
|
||||||
|
|
||||||
|
# Method 2: Use separate host and port (recommended)
|
||||||
|
SERVER_HOST=0.0.0.0
|
||||||
|
SERVER_PORT=3000
|
||||||
|
|
||||||
|
# For development: Configure frontend port
|
||||||
|
CLIENT_PORT=5173
|
||||||
|
BACKEND_PORT=8000
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Security Configuration
|
||||||
|
|
||||||
Create a `.env` file for your secrets:
|
Create a `.env` file for your secrets:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -243,6 +262,8 @@ services:
|
||||||
- "traefik.http.routers.readur.tls.certresolver=letsencrypt"
|
- "traefik.http.routers.readur.tls.certresolver=letsencrypt"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> 📘 **For detailed reverse proxy configurations** including Apache, Caddy, custom ports, load balancing, and advanced scenarios, see [REVERSE_PROXY.md](./REVERSE_PROXY.md).
|
||||||
|
|
||||||
### Health Checks
|
### Health Checks
|
||||||
|
|
||||||
Add health checks to your Docker configuration:
|
Add health checks to your Docker configuration:
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,100 @@
|
||||||
services:
|
version: '3.8'
|
||||||
readur:
|
|
||||||
build: .
|
|
||||||
ports:
|
|
||||||
- "8000:8000"
|
|
||||||
environment:
|
|
||||||
- DATABASE_URL=postgresql://readur:readur_password@postgres:5432/readur
|
|
||||||
- JWT_SECRET=your-super-secret-jwt-key-change-this-in-production
|
|
||||||
- UPLOAD_PATH=/app/uploads
|
|
||||||
- WATCH_FOLDER=/app/watch
|
|
||||||
- RUST_BACKTRACE=1
|
|
||||||
volumes:
|
|
||||||
- uploads:/app/uploads
|
|
||||||
- watch:/app/watch
|
|
||||||
depends_on:
|
|
||||||
- postgres
|
|
||||||
restart: unless-stopped
|
|
||||||
|
|
||||||
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:15
|
image: postgres:16-alpine
|
||||||
environment:
|
environment:
|
||||||
- POSTGRES_USER=readur
|
POSTGRES_USER: readur
|
||||||
- POSTGRES_PASSWORD=readur_password
|
POSTGRES_PASSWORD: readur
|
||||||
- POSTGRES_DB=readur
|
POSTGRES_DB: readur
|
||||||
volumes:
|
volumes:
|
||||||
- postgres_data:/var/lib/postgresql/data
|
- postgres_data:/var/lib/postgresql/data
|
||||||
ports:
|
ports:
|
||||||
- "5433:5432"
|
- "5432:5432"
|
||||||
restart: unless-stopped
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U readur"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
|
readur:
|
||||||
|
build: .
|
||||||
|
environment:
|
||||||
|
# Database configuration
|
||||||
|
DATABASE_URL: postgresql://readur:readur@postgres/readur
|
||||||
|
|
||||||
|
# Server configuration - choose one of these methods:
|
||||||
|
# Method 1: Use SERVER_ADDRESS for full control
|
||||||
|
# SERVER_ADDRESS: 0.0.0.0:8080
|
||||||
|
|
||||||
|
# Method 2: Use SERVER_HOST and SERVER_PORT separately
|
||||||
|
SERVER_HOST: 0.0.0.0
|
||||||
|
SERVER_PORT: 8080
|
||||||
|
|
||||||
|
# Security
|
||||||
|
JWT_SECRET: your-secret-key-change-this-in-production
|
||||||
|
|
||||||
|
# File paths
|
||||||
|
UPLOAD_PATH: /app/uploads
|
||||||
|
WATCH_FOLDER: /app/watch
|
||||||
|
|
||||||
|
# OCR configuration
|
||||||
|
OCR_LANGUAGE: eng
|
||||||
|
CONCURRENT_OCR_JOBS: 4
|
||||||
|
OCR_TIMEOUT_SECONDS: 300
|
||||||
|
MAX_FILE_SIZE_MB: 50
|
||||||
|
|
||||||
|
# Performance
|
||||||
|
MEMORY_LIMIT_MB: 512
|
||||||
|
CPU_PRIORITY: normal
|
||||||
|
|
||||||
|
# File watching
|
||||||
|
ALLOWED_FILE_TYPES: pdf,txt,doc,docx,png,jpg,jpeg
|
||||||
|
WATCH_INTERVAL_SECONDS: 30
|
||||||
|
FILE_STABILITY_CHECK_MS: 1000
|
||||||
|
MAX_FILE_AGE_HOURS: 24
|
||||||
|
|
||||||
|
ports:
|
||||||
|
# Map container port to host port
|
||||||
|
# Format: "host_port:container_port"
|
||||||
|
- "8080:8080"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
# Persistent storage for uploads
|
||||||
|
- readur_uploads:/app/uploads
|
||||||
|
|
||||||
|
# Watch folder - can be mapped to a host directory
|
||||||
|
- ./watch:/app/watch
|
||||||
|
|
||||||
|
# Or use a named volume for watch folder
|
||||||
|
# - readur_watch:/app/watch
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8080/api/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 40s
|
||||||
|
|
||||||
|
# Optional: Nginx reverse proxy example
|
||||||
|
nginx:
|
||||||
|
image: nginx:alpine
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
volumes:
|
||||||
|
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
||||||
|
- ./ssl:/etc/nginx/ssl:ro
|
||||||
|
depends_on:
|
||||||
|
- readur
|
||||||
|
profiles:
|
||||||
|
- with-proxy
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
uploads:
|
|
||||||
watch:
|
|
||||||
postgres_data:
|
postgres_data:
|
||||||
|
readur_uploads:
|
||||||
|
readur_watch:
|
||||||
|
|
@ -0,0 +1,430 @@
|
||||||
|
# Reverse Proxy Configuration Guide for Readur
|
||||||
|
|
||||||
|
This guide covers various deployment scenarios for running Readur behind reverse proxies with configurable ports.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
- [Port Configuration](#port-configuration)
|
||||||
|
- [Docker Deployment](#docker-deployment)
|
||||||
|
- [Nginx Configuration](#nginx-configuration)
|
||||||
|
- [Traefik Configuration](#traefik-configuration)
|
||||||
|
- [Apache Configuration](#apache-configuration)
|
||||||
|
- [Caddy Configuration](#caddy-configuration)
|
||||||
|
- [Common Scenarios](#common-scenarios)
|
||||||
|
- [Troubleshooting](#troubleshooting)
|
||||||
|
|
||||||
|
## Port Configuration
|
||||||
|
|
||||||
|
Readur supports flexible port configuration through environment variables:
|
||||||
|
|
||||||
|
### Server Port Configuration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Method 1: Full address specification
|
||||||
|
SERVER_ADDRESS=0.0.0.0:3000
|
||||||
|
|
||||||
|
# Method 2: Separate host and port (recommended)
|
||||||
|
SERVER_HOST=0.0.0.0
|
||||||
|
SERVER_PORT=3000
|
||||||
|
```
|
||||||
|
|
||||||
|
### Development Port Configuration
|
||||||
|
|
||||||
|
For frontend development with Vite:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backend API port
|
||||||
|
BACKEND_PORT=8000
|
||||||
|
|
||||||
|
# Frontend dev server port
|
||||||
|
CLIENT_PORT=5173
|
||||||
|
```
|
||||||
|
|
||||||
|
## Docker Deployment
|
||||||
|
|
||||||
|
### Basic Docker Run
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run on custom port 3000
|
||||||
|
docker run -d \
|
||||||
|
-e SERVER_PORT=3000 \
|
||||||
|
-e DATABASE_URL=postgresql://user:pass@host/db \
|
||||||
|
-e JWT_SECRET=your-secret-key \
|
||||||
|
-p 3000:3000 \
|
||||||
|
readur:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker Compose with Custom Ports
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
readur:
|
||||||
|
image: readur:latest
|
||||||
|
environment:
|
||||||
|
SERVER_PORT: 3000
|
||||||
|
DATABASE_URL: postgresql://readur:readur@postgres/readur
|
||||||
|
JWT_SECRET: ${JWT_SECRET}
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Nginx Configuration
|
||||||
|
|
||||||
|
### Basic Reverse Proxy
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name readur.example.com;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://localhost:3000;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
|
# Large file uploads for documents
|
||||||
|
client_max_body_size 100M;
|
||||||
|
|
||||||
|
# Extended timeouts for OCR processing
|
||||||
|
proxy_connect_timeout 300s;
|
||||||
|
proxy_send_timeout 300s;
|
||||||
|
proxy_read_timeout 300s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### SSL Configuration
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name readur.example.com;
|
||||||
|
|
||||||
|
ssl_certificate /path/to/cert.pem;
|
||||||
|
ssl_certificate_key /path/to/key.pem;
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://localhost:3000;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto https;
|
||||||
|
|
||||||
|
# WebSocket support (future feature)
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Subpath Configuration
|
||||||
|
|
||||||
|
To serve Readur under a subpath like `/readur/`:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
location /readur/ {
|
||||||
|
# Remove prefix when passing to backend
|
||||||
|
rewrite ^/readur/(.*) /$1 break;
|
||||||
|
|
||||||
|
proxy_pass http://localhost:3000;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header X-Forwarded-Prefix /readur;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Traefik Configuration
|
||||||
|
|
||||||
|
### Docker Labels
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
readur:
|
||||||
|
image: readur:latest
|
||||||
|
environment:
|
||||||
|
SERVER_PORT: 3000
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.readur.rule=Host(`readur.example.com`)"
|
||||||
|
- "traefik.http.routers.readur.tls=true"
|
||||||
|
- "traefik.http.routers.readur.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.services.readur.loadbalancer.server.port=3000"
|
||||||
|
# Middleware for large uploads
|
||||||
|
- "traefik.http.middlewares.readur-upload.buffering.maxRequestBodyBytes=104857600"
|
||||||
|
- "traefik.http.routers.readur.middlewares=readur-upload"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Static Configuration
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# traefik.yml
|
||||||
|
http:
|
||||||
|
routers:
|
||||||
|
readur:
|
||||||
|
rule: "Host(`readur.example.com`)"
|
||||||
|
service: readur
|
||||||
|
tls:
|
||||||
|
certResolver: letsencrypt
|
||||||
|
middlewares:
|
||||||
|
- readur-headers
|
||||||
|
|
||||||
|
services:
|
||||||
|
readur:
|
||||||
|
loadBalancer:
|
||||||
|
servers:
|
||||||
|
- url: "http://localhost:3000"
|
||||||
|
healthCheck:
|
||||||
|
path: /api/health
|
||||||
|
interval: 30s
|
||||||
|
|
||||||
|
middlewares:
|
||||||
|
readur-headers:
|
||||||
|
headers:
|
||||||
|
customRequestHeaders:
|
||||||
|
X-Forwarded-Proto: https
|
||||||
|
```
|
||||||
|
|
||||||
|
## Apache Configuration
|
||||||
|
|
||||||
|
### Basic Reverse Proxy
|
||||||
|
|
||||||
|
```apache
|
||||||
|
<VirtualHost *:80>
|
||||||
|
ServerName readur.example.com
|
||||||
|
|
||||||
|
ProxyRequests Off
|
||||||
|
ProxyPreserveHost On
|
||||||
|
|
||||||
|
ProxyPass / http://localhost:3000/
|
||||||
|
ProxyPassReverse / http://localhost:3000/
|
||||||
|
|
||||||
|
# Large file uploads
|
||||||
|
LimitRequestBody 104857600
|
||||||
|
|
||||||
|
# Extended timeouts
|
||||||
|
ProxyTimeout 300
|
||||||
|
</VirtualHost>
|
||||||
|
```
|
||||||
|
|
||||||
|
### SSL Configuration
|
||||||
|
|
||||||
|
```apache
|
||||||
|
<VirtualHost *:443>
|
||||||
|
ServerName readur.example.com
|
||||||
|
|
||||||
|
SSLEngine on
|
||||||
|
SSLCertificateFile /path/to/cert.pem
|
||||||
|
SSLCertificateKeyFile /path/to/key.pem
|
||||||
|
|
||||||
|
ProxyRequests Off
|
||||||
|
ProxyPreserveHost On
|
||||||
|
|
||||||
|
ProxyPass / http://localhost:3000/
|
||||||
|
ProxyPassReverse / http://localhost:3000/
|
||||||
|
|
||||||
|
RequestHeader set X-Forwarded-Proto "https"
|
||||||
|
</VirtualHost>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Caddy Configuration
|
||||||
|
|
||||||
|
### Caddyfile
|
||||||
|
|
||||||
|
```caddy
|
||||||
|
readur.example.com {
|
||||||
|
reverse_proxy localhost:3000 {
|
||||||
|
header_up X-Real-IP {remote_host}
|
||||||
|
header_up X-Forwarded-Proto {scheme}
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
health_uri /api/health
|
||||||
|
health_interval 30s
|
||||||
|
|
||||||
|
# Extended timeouts
|
||||||
|
transport http {
|
||||||
|
dial_timeout 10s
|
||||||
|
response_header_timeout 300s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Large file uploads
|
||||||
|
request_body {
|
||||||
|
max_size 100MB
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Scenarios
|
||||||
|
|
||||||
|
### Multiple Instances with Load Balancing
|
||||||
|
|
||||||
|
#### Nginx
|
||||||
|
```nginx
|
||||||
|
upstream readur_pool {
|
||||||
|
least_conn;
|
||||||
|
server readur1:3000 max_fails=3 fail_timeout=30s;
|
||||||
|
server readur2:3000 max_fails=3 fail_timeout=30s;
|
||||||
|
server readur3:3000 max_fails=3 fail_timeout=30s;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
location / {
|
||||||
|
proxy_pass http://readur_pool;
|
||||||
|
# ... other proxy settings
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Docker Compose Scale
|
||||||
|
```bash
|
||||||
|
# Scale to 3 instances
|
||||||
|
docker compose up -d --scale readur=3
|
||||||
|
```
|
||||||
|
|
||||||
|
### Blue-Green Deployment
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
# nginx.conf
|
||||||
|
upstream readur_blue {
|
||||||
|
server blue:3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream readur_green {
|
||||||
|
server green:3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Switch between blue and green
|
||||||
|
upstream readur_current {
|
||||||
|
server blue:3000; # Change to green:3000 for switch
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
location / {
|
||||||
|
proxy_pass http://readur_current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rate Limiting
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
# Define rate limit zones
|
||||||
|
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
|
||||||
|
limit_req_zone $binary_remote_addr zone=auth:10m rate=5r/m;
|
||||||
|
|
||||||
|
server {
|
||||||
|
# Apply to API endpoints
|
||||||
|
location /api/ {
|
||||||
|
limit_req zone=api burst=20 nodelay;
|
||||||
|
proxy_pass http://localhost:3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Stricter for auth
|
||||||
|
location /api/auth/ {
|
||||||
|
limit_req zone=auth burst=5 nodelay;
|
||||||
|
proxy_pass http://localhost:3000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
1. **502 Bad Gateway**
|
||||||
|
- Check if Readur is running on the configured port
|
||||||
|
- Verify `SERVER_PORT` environment variable
|
||||||
|
- Check container logs: `docker logs readur`
|
||||||
|
|
||||||
|
2. **Large File Upload Failures**
|
||||||
|
- Increase `client_max_body_size` in nginx
|
||||||
|
- Adjust `MAX_FILE_SIZE_MB` in Readur config
|
||||||
|
- Check proxy timeout settings
|
||||||
|
|
||||||
|
3. **WebSocket Connection Issues** (future feature)
|
||||||
|
- Ensure `proxy_http_version 1.1` is set
|
||||||
|
- Include Upgrade and Connection headers
|
||||||
|
|
||||||
|
4. **CORS Errors**
|
||||||
|
- Readur includes CORS middleware
|
||||||
|
- Ensure `X-Forwarded-Proto` header is set correctly
|
||||||
|
- Check if frontend URL matches expected origin
|
||||||
|
|
||||||
|
### Health Check Monitoring
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Direct health check
|
||||||
|
curl http://localhost:3000/api/health
|
||||||
|
|
||||||
|
# Through reverse proxy
|
||||||
|
curl https://readur.example.com/api/health
|
||||||
|
|
||||||
|
# Expected response
|
||||||
|
{"status":"ok"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Debug Headers
|
||||||
|
|
||||||
|
Add these to your reverse proxy for debugging:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
add_header X-Proxy-Debug "nginx" always;
|
||||||
|
add_header X-Upstream-Addr $upstream_addr always;
|
||||||
|
add_header X-Upstream-Status $upstream_status always;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Recommendations
|
||||||
|
|
||||||
|
1. **Always use HTTPS** in production
|
||||||
|
2. **Implement rate limiting** to prevent abuse
|
||||||
|
3. **Set security headers**:
|
||||||
|
```nginx
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Restrict access** to health check endpoint if needed:
|
||||||
|
```nginx
|
||||||
|
location /api/health {
|
||||||
|
allow 10.0.0.0/8;
|
||||||
|
deny all;
|
||||||
|
proxy_pass http://localhost:3000;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Use strong JWT secrets** and rotate them regularly
|
||||||
|
6. **Monitor access logs** for suspicious activity
|
||||||
|
|
||||||
|
## Performance Optimization
|
||||||
|
|
||||||
|
1. **Enable caching** for static assets:
|
||||||
|
```nginx
|
||||||
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
|
||||||
|
proxy_pass http://localhost:3000;
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Use HTTP/2** for better performance
|
||||||
|
3. **Enable gzip compression**:
|
||||||
|
```nginx
|
||||||
|
gzip on;
|
||||||
|
gzip_types text/plain text/css application/json application/javascript;
|
||||||
|
gzip_min_length 1000;
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Configure connection pooling** for database
|
||||||
|
5. **Use CDN** for static assets in production
|
||||||
|
|
@ -1,12 +1,17 @@
|
||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import react from '@vitejs/plugin-react'
|
import react from '@vitejs/plugin-react'
|
||||||
|
|
||||||
|
// Support environment variables for development
|
||||||
|
const BACKEND_PORT = process.env.BACKEND_PORT || '8000'
|
||||||
|
const CLIENT_PORT = process.env.CLIENT_PORT || '5173'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [react()],
|
||||||
server: {
|
server: {
|
||||||
|
port: parseInt(CLIENT_PORT),
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api': {
|
'/api': {
|
||||||
target: 'http://localhost:8000',
|
target: `http://localhost:${BACKEND_PORT}`,
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,145 @@
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
# Upstream configuration
|
||||||
|
upstream readur {
|
||||||
|
server readur:8080;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Rate limiting
|
||||||
|
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
|
||||||
|
limit_req_zone $binary_remote_addr zone=auth:10m rate=5r/m;
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name localhost;
|
||||||
|
|
||||||
|
# Redirect HTTP to HTTPS (uncomment in production)
|
||||||
|
# return 301 https://$server_name$request_uri;
|
||||||
|
|
||||||
|
# For development without SSL
|
||||||
|
location / {
|
||||||
|
proxy_pass http://readur;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# HTTPS server configuration
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name localhost;
|
||||||
|
|
||||||
|
# SSL configuration (update paths as needed)
|
||||||
|
ssl_certificate /etc/nginx/ssl/cert.pem;
|
||||||
|
ssl_certificate_key /etc/nginx/ssl/key.pem;
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||||
|
|
||||||
|
# Max upload size
|
||||||
|
client_max_body_size 100M;
|
||||||
|
client_body_timeout 300s;
|
||||||
|
|
||||||
|
# Main application
|
||||||
|
location / {
|
||||||
|
proxy_pass http://readur;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
|
# WebSocket support (if needed in future)
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
|
||||||
|
# Timeouts for long-running OCR operations
|
||||||
|
proxy_connect_timeout 300s;
|
||||||
|
proxy_send_timeout 300s;
|
||||||
|
proxy_read_timeout 300s;
|
||||||
|
}
|
||||||
|
|
||||||
|
# API rate limiting
|
||||||
|
location /api/ {
|
||||||
|
limit_req zone=api burst=20 nodelay;
|
||||||
|
|
||||||
|
proxy_pass http://readur;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Stricter rate limiting for auth endpoints
|
||||||
|
location /api/auth/ {
|
||||||
|
limit_req zone=auth burst=5 nodelay;
|
||||||
|
|
||||||
|
proxy_pass http://readur;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Health check endpoint (no rate limiting)
|
||||||
|
location /api/health {
|
||||||
|
proxy_pass http://readur;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
access_log off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Static assets caching
|
||||||
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||||
|
proxy_pass http://readur;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Subpath example - serving readur under /readur/
|
||||||
|
# server {
|
||||||
|
# listen 80;
|
||||||
|
# server_name example.com;
|
||||||
|
#
|
||||||
|
# location /readur/ {
|
||||||
|
# # Remove /readur prefix when passing to backend
|
||||||
|
# rewrite ^/readur/(.*) /$1 break;
|
||||||
|
#
|
||||||
|
# proxy_pass http://readur;
|
||||||
|
# proxy_set_header Host $host;
|
||||||
|
# proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
# proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
# proxy_set_header X-Forwarded-Prefix /readur;
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
|
||||||
|
# Multiple instances example
|
||||||
|
# upstream readur_pool {
|
||||||
|
# least_conn;
|
||||||
|
# server readur1:8080;
|
||||||
|
# server readur2:8080;
|
||||||
|
# server readur3:8080;
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# server {
|
||||||
|
# listen 80;
|
||||||
|
#
|
||||||
|
# location / {
|
||||||
|
# proxy_pass http://readur_pool;
|
||||||
|
# # ... rest of proxy configuration
|
||||||
|
# }
|
||||||
|
# }
|
||||||
229
run_all_tests.sh
229
run_all_tests.sh
|
|
@ -1,229 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Readur - Complete Test Suite Runner
|
|
||||||
# This script runs all unit tests and integration tests for the Readur project
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "🧪 Readur Complete Test Suite"
|
|
||||||
echo "=============================="
|
|
||||||
|
|
||||||
# Colors for output
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# Function to print colored output
|
|
||||||
print_step() {
|
|
||||||
echo -e "${BLUE}📋 $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
print_success() {
|
|
||||||
echo -e "${GREEN}✅ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
print_warning() {
|
|
||||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
print_error() {
|
|
||||||
echo -e "${RED}❌ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check if PostgreSQL is running (for integration tests)
|
|
||||||
check_postgres() {
|
|
||||||
if ! command -v psql >/dev/null 2>&1; then
|
|
||||||
print_warning "PostgreSQL not found. Integration tests may fail."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! pg_isready >/dev/null 2>&1; then
|
|
||||||
print_warning "PostgreSQL is not running. Integration tests may fail."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# Backend Unit Tests
|
|
||||||
run_backend_unit_tests() {
|
|
||||||
print_step "Running Backend Unit Tests"
|
|
||||||
|
|
||||||
if cargo test --lib; then
|
|
||||||
print_success "Backend unit tests passed"
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
print_error "Backend unit tests failed"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Backend Integration Tests
|
|
||||||
run_backend_integration_tests() {
|
|
||||||
print_step "Running Backend Integration Tests"
|
|
||||||
|
|
||||||
if ! check_postgres; then
|
|
||||||
print_warning "Skipping integration tests - PostgreSQL not available"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if server is running
|
|
||||||
if ! curl -s http://localhost:8000/api/health >/dev/null 2>&1; then
|
|
||||||
print_warning "Server not running at localhost:8000"
|
|
||||||
print_warning "Start server with: cargo run"
|
|
||||||
print_warning "Skipping integration tests"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if RUST_BACKTRACE=1 cargo test --test integration_tests; then
|
|
||||||
print_success "Backend integration tests passed"
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
print_error "Backend integration tests failed"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Frontend Tests
|
|
||||||
run_frontend_tests() {
|
|
||||||
print_step "Running Frontend Tests"
|
|
||||||
|
|
||||||
if [ ! -d "frontend" ]; then
|
|
||||||
print_error "Frontend directory not found"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd frontend
|
|
||||||
|
|
||||||
if [ ! -f "package.json" ]; then
|
|
||||||
print_error "package.json not found in frontend directory"
|
|
||||||
cd ..
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Install dependencies if node_modules doesn't exist
|
|
||||||
if [ ! -d "node_modules" ]; then
|
|
||||||
print_step "Installing frontend dependencies..."
|
|
||||||
npm install
|
|
||||||
fi
|
|
||||||
|
|
||||||
if npm test -- --run; then
|
|
||||||
print_success "Frontend tests completed"
|
|
||||||
cd ..
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
print_warning "Frontend tests had failures (this is expected - work in progress)"
|
|
||||||
cd ..
|
|
||||||
return 0 # Don't fail the overall script for frontend test issues
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Test Coverage (optional)
|
|
||||||
generate_coverage() {
|
|
||||||
print_step "Generating Test Coverage (optional)"
|
|
||||||
|
|
||||||
# Backend coverage
|
|
||||||
if command -v cargo-tarpaulin >/dev/null 2>&1; then
|
|
||||||
print_step "Generating backend coverage..."
|
|
||||||
cargo tarpaulin --out Html --output-dir coverage/ >/dev/null 2>&1 || true
|
|
||||||
print_success "Backend coverage generated in coverage/"
|
|
||||||
else
|
|
||||||
print_warning "cargo-tarpaulin not installed. Run: cargo install cargo-tarpaulin"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Frontend coverage
|
|
||||||
if [ -d "frontend" ]; then
|
|
||||||
cd frontend
|
|
||||||
if npm run test:coverage >/dev/null 2>&1; then
|
|
||||||
print_success "Frontend coverage generated in frontend/coverage/"
|
|
||||||
fi
|
|
||||||
cd ..
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Main execution
|
|
||||||
main() {
|
|
||||||
echo "Starting test suite at $(date)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Track overall success
|
|
||||||
overall_success=true
|
|
||||||
|
|
||||||
# Run backend unit tests
|
|
||||||
if ! run_backend_unit_tests; then
|
|
||||||
overall_success=false
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Run backend integration tests
|
|
||||||
if ! run_backend_integration_tests; then
|
|
||||||
overall_success=false
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Run frontend tests (don't fail overall on frontend issues)
|
|
||||||
run_frontend_tests
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Generate coverage if requested
|
|
||||||
if [ "$1" = "--coverage" ]; then
|
|
||||||
generate_coverage
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Summary
|
|
||||||
echo "=============================="
|
|
||||||
if [ "$overall_success" = true ]; then
|
|
||||||
print_success "Test Suite Completed Successfully!"
|
|
||||||
echo ""
|
|
||||||
echo "📊 Test Summary:"
|
|
||||||
echo " ✅ Backend Unit Tests: PASSED"
|
|
||||||
echo " ✅ Backend Integration Tests: PASSED"
|
|
||||||
echo " 🔄 Frontend Tests: IN PROGRESS (28/75 passing)"
|
|
||||||
echo ""
|
|
||||||
echo "🎉 All critical backend tests are passing!"
|
|
||||||
exit 0
|
|
||||||
else
|
|
||||||
print_error "Test Suite Failed"
|
|
||||||
echo ""
|
|
||||||
echo "❌ Some backend tests failed. Check output above for details."
|
|
||||||
echo ""
|
|
||||||
echo "💡 Troubleshooting tips:"
|
|
||||||
echo " • Ensure PostgreSQL is running"
|
|
||||||
echo " • Check DATABASE_URL environment variable"
|
|
||||||
echo " • Start server: cargo run"
|
|
||||||
echo " • Run with debug: RUST_BACKTRACE=1 cargo test"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Handle script arguments
|
|
||||||
case "$1" in
|
|
||||||
--help|-h)
|
|
||||||
echo "Usage: $0 [OPTIONS]"
|
|
||||||
echo ""
|
|
||||||
echo "Options:"
|
|
||||||
echo " --coverage Generate test coverage reports"
|
|
||||||
echo " --help, -h Show this help message"
|
|
||||||
echo ""
|
|
||||||
echo "Examples:"
|
|
||||||
echo " $0 # Run all tests"
|
|
||||||
echo " $0 --coverage # Run all tests and generate coverage"
|
|
||||||
echo ""
|
|
||||||
echo "Prerequisites:"
|
|
||||||
echo " • Rust toolchain"
|
|
||||||
echo " • PostgreSQL (for integration tests)"
|
|
||||||
echo " • Node.js (for frontend tests)"
|
|
||||||
echo ""
|
|
||||||
echo "For detailed testing documentation, see TESTING.md"
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
main "$@"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
83
run_tests.sh
83
run_tests.sh
|
|
@ -1,83 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Test runner script for Readur
|
|
||||||
# This script runs tests in different modes to handle dependencies
|
|
||||||
|
|
||||||
echo "🧪 Readur Test Runner"
|
|
||||||
echo "===================="
|
|
||||||
|
|
||||||
# Function to run tests with specific configuration
|
|
||||||
run_tests() {
|
|
||||||
local mode="$1"
|
|
||||||
local flags="$2"
|
|
||||||
local description="$3"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "📋 Running $description"
|
|
||||||
echo "Command: cargo test $flags"
|
|
||||||
echo "-------------------------------------------"
|
|
||||||
|
|
||||||
if cargo test $flags; then
|
|
||||||
echo "✅ $description: PASSED"
|
|
||||||
else
|
|
||||||
echo "❌ $description: FAILED"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check if Docker is available for integration tests
|
|
||||||
check_docker() {
|
|
||||||
if command -v docker &> /dev/null && docker info &> /dev/null; then
|
|
||||||
echo "🐳 Docker is available - integration tests can run"
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
echo "⚠️ Docker not available - skipping integration tests"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Main test execution
|
|
||||||
echo "Starting test execution..."
|
|
||||||
|
|
||||||
# 1. Run unit tests without OCR dependencies (fastest)
|
|
||||||
run_tests "unit" "--lib --no-default-features -- --skip database --skip integration" "Unit tests (no OCR/DB dependencies)"
|
|
||||||
unit_result=$?
|
|
||||||
|
|
||||||
# 2. Run unit tests with OCR dependencies (requires tesseract)
|
|
||||||
if command -v tesseract &> /dev/null; then
|
|
||||||
echo "📷 Tesseract OCR available - running OCR tests"
|
|
||||||
run_tests "ocr" "--lib --features ocr -- --skip database --skip integration" "Unit tests with OCR support"
|
|
||||||
ocr_result=$?
|
|
||||||
else
|
|
||||||
echo "⚠️ Tesseract not available - skipping OCR tests"
|
|
||||||
echo " Install with: sudo apt-get install tesseract-ocr tesseract-ocr-eng"
|
|
||||||
ocr_result=0 # Don't fail if tesseract isn't available
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 3. Run integration tests (requires Docker for PostgreSQL)
|
|
||||||
if check_docker; then
|
|
||||||
run_tests "integration" "--lib --features ocr" "Integration tests (requires Docker/PostgreSQL)"
|
|
||||||
integration_result=$?
|
|
||||||
else
|
|
||||||
integration_result=0 # Don't fail if Docker isn't available
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Summary
|
|
||||||
echo ""
|
|
||||||
echo "📊 Test Summary"
|
|
||||||
echo "==============="
|
|
||||||
echo "Unit tests (basic): $([ $unit_result -eq 0 ] && echo "✅ PASSED" || echo "❌ FAILED")"
|
|
||||||
echo "Unit tests (with OCR): $([ $ocr_result -eq 0 ] && echo "✅ PASSED" || echo "⚠️ SKIPPED")"
|
|
||||||
echo "Integration tests: $([ $integration_result -eq 0 ] && echo "✅ PASSED" || echo "⚠️ SKIPPED")"
|
|
||||||
|
|
||||||
# Exit with appropriate code
|
|
||||||
if [ $unit_result -eq 0 ]; then
|
|
||||||
echo ""
|
|
||||||
echo "🎉 Core functionality tests passed!"
|
|
||||||
echo "Your code changes are working correctly."
|
|
||||||
exit 0
|
|
||||||
else
|
|
||||||
echo ""
|
|
||||||
echo "💥 Some tests failed. Please check the output above."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
@ -31,8 +31,16 @@ impl Config {
|
||||||
Ok(Config {
|
Ok(Config {
|
||||||
database_url: env::var("DATABASE_URL")
|
database_url: env::var("DATABASE_URL")
|
||||||
.unwrap_or_else(|_| "postgresql://readur:readur@localhost/readur".to_string()),
|
.unwrap_or_else(|_| "postgresql://readur:readur@localhost/readur".to_string()),
|
||||||
server_address: env::var("SERVER_ADDRESS")
|
server_address: {
|
||||||
.unwrap_or_else(|_| "0.0.0.0:8000".to_string()),
|
// Support both SERVER_ADDRESS (full address) and SERVER_PORT (just port)
|
||||||
|
if let Ok(addr) = env::var("SERVER_ADDRESS") {
|
||||||
|
addr
|
||||||
|
} else {
|
||||||
|
let host = env::var("SERVER_HOST").unwrap_or_else(|_| "0.0.0.0".to_string());
|
||||||
|
let port = env::var("SERVER_PORT").unwrap_or_else(|_| "8000".to_string());
|
||||||
|
format!("{}:{}", host, port)
|
||||||
|
}
|
||||||
|
},
|
||||||
jwt_secret: env::var("JWT_SECRET")
|
jwt_secret: env::var("JWT_SECRET")
|
||||||
.unwrap_or_else(|_| "your-secret-key".to_string()),
|
.unwrap_or_else(|_| "your-secret-key".to_string()),
|
||||||
upload_path: env::var("UPLOAD_PATH")
|
upload_path: env::var("UPLOAD_PATH")
|
||||||
|
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Test script for watch folder functionality
|
|
||||||
echo "Testing watch folder functionality..."
|
|
||||||
|
|
||||||
# Create a test watch folder if it doesn't exist
|
|
||||||
mkdir -p ./watch
|
|
||||||
|
|
||||||
echo "Creating test files in watch folder..."
|
|
||||||
|
|
||||||
# Create a test text file
|
|
||||||
echo "This is a test document for OCR processing." > ./watch/test_document.txt
|
|
||||||
|
|
||||||
# Create a test PDF file (mock content)
|
|
||||||
echo "%PDF-1.4 Mock PDF for testing" > ./watch/test_document.pdf
|
|
||||||
|
|
||||||
# Create a test image file (mock content)
|
|
||||||
echo "Mock PNG image content" > ./watch/test_image.png
|
|
||||||
|
|
||||||
echo "Test files created in ./watch/ folder:"
|
|
||||||
ls -la ./watch/
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Watch folder setup complete!"
|
|
||||||
echo "You can now:"
|
|
||||||
echo "1. Start the readur application"
|
|
||||||
echo "2. Copy OCR-able files to the ./watch/ folder"
|
|
||||||
echo "3. Monitor the logs to see files being processed"
|
|
||||||
echo ""
|
|
||||||
echo "Supported file types: PDF, PNG, JPG, JPEG, TIFF, BMP, TXT, DOC, DOCX"
|
|
||||||
echo ""
|
|
||||||
echo "Environment variables for configuration:"
|
|
||||||
echo "- WATCH_FOLDER: Path to watch folder (default: ./watch)"
|
|
||||||
echo "- WATCH_INTERVAL_SECONDS: Polling interval (default: 30)"
|
|
||||||
echo "- FILE_STABILITY_CHECK_MS: File stability check time (default: 500)"
|
|
||||||
echo "- MAX_FILE_AGE_HOURS: Skip files older than this (default: none)"
|
|
||||||
echo "- FORCE_POLLING_WATCH: Force polling mode (default: auto-detect)"
|
|
||||||
Loading…
Reference in New Issue