feat(docs): clean up docs and make dev ex easier with variables

This commit is contained in:
perf3ct 2025-06-13 23:21:45 +00:00
parent 68f5da509b
commit f7874f4541
13 changed files with 704 additions and 378 deletions

View File

@ -142,6 +142,25 @@ volumes:
### 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:
```bash
@ -243,6 +262,8 @@ services:
- "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
Add health checks to your Docker configuration:

View File

@ -1,34 +1,100 @@
services:
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
version: '3.8'
services:
postgres:
image: postgres:15
image: postgres:16-alpine
environment:
- POSTGRES_USER=readur
- POSTGRES_PASSWORD=readur_password
- POSTGRES_DB=readur
POSTGRES_USER: readur
POSTGRES_PASSWORD: readur
POSTGRES_DB: readur
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5433:5432"
restart: unless-stopped
- "5432:5432"
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:
uploads:
watch:
postgres_data:
readur_uploads:
readur_watch:

430
docs/REVERSE_PROXY.md Normal file
View File

@ -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

View File

@ -1,12 +1,17 @@
import { defineConfig } from 'vite'
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({
plugins: [react()],
server: {
port: parseInt(CLIENT_PORT),
proxy: {
'/api': {
target: 'http://localhost:8000',
target: `http://localhost:${BACKEND_PORT}`,
changeOrigin: true,
},
},

145
nginx.conf Normal file
View File

@ -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
# }
# }

View File

@ -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

View File

@ -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

View File

@ -31,8 +31,16 @@ impl Config {
Ok(Config {
database_url: env::var("DATABASE_URL")
.unwrap_or_else(|_| "postgresql://readur:readur@localhost/readur".to_string()),
server_address: env::var("SERVER_ADDRESS")
.unwrap_or_else(|_| "0.0.0.0:8000".to_string()),
server_address: {
// 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")
.unwrap_or_else(|_| "your-secret-key".to_string()),
upload_path: env::var("UPLOAD_PATH")

View File

@ -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)"