# Releasebird Image Service

Backend-Service für Image-Rendering mit Puppeteer. Dieses System ermöglicht es, HTML-Content vom Frontend zu empfangen und serverseitig als Image zu rendern, wodurch CORS-Probleme mit externen Ressourcen vermieden werden.

## Architektur

```
┌─────────────────┐      ┌──────────────────┐      ┌─────────────────────┐
│                 │      │                  │      │                     │
│  JavaScript SDK │─────▶│  Spring Boot API │─────▶│  Puppeteer Service  │
│  (Frontend)     │      │  (Controller)    │      │  (Node.js + Docker) │
│                 │      │                  │      │                     │
└─────────────────┘      └──────────────────┘      └─────────────────────┘
    1. Sendet HTML        2. Forwarded zu         3. Rendert HTML → Bild
                            Puppeteer Service         und gibt zurück
```

## Komponenten

### 1. JavaScript SDK (Frontend)
- Exportiert HTML mit inline Styles
- Sendet an Spring Boot Backend
- Keine CORS-Probleme mehr!

### 2. Spring Boot Controller
- Empfängt HTML vom Frontend
- Leitet an Puppeteer Service weiter
- Gibt Image zurück

**Dateien:**
- `spring-boot/ImageController.java` - Main Controller
- `spring-boot/RestTemplateConfig.java` - RestTemplate Bean

### 3. Puppeteer Service (Node.js)
- Rendert HTML zu Bild mit Puppeteer
- Läuft in Docker Container
- Wiederverwendbare Browser-Instanz für Performance

**Dateien:**
- `image-service/server.js` - Express Server mit Puppeteer
- `image-service/package.json` - Dependencies
- `image-service/Dockerfile` - Docker Image
- `docker-compose.yml` - Docker Compose Setup

## Installation & Setup

### Schritt 1: Puppeteer Service mit Docker starten

#### Option A: Mit Docker Compose (Empfohlen)

```bash
cd backend-image-service
docker-compose up -d
```

#### Option B: Manuell mit Docker

```bash
cd backend-image-service/image-service
docker build -t releasebird-image-service .
docker run -d -p 3000:3000 --name image-service releasebird-image-service
```

#### Option C: Lokal ohne Docker (Development)

```bash
cd backend-image-service/image-service
npm install
npm start
```

**Health Check:**
```bash
curl http://localhost:3000/health
```

### Schritt 2: Spring Boot Integration

#### 1. Kopiere die Java-Dateien in dein Spring Boot Projekt:

```
src/main/java/com/releasebird/api/
├── config/
│   └── RestTemplateConfig.java
└── controller/
    └── ImageController.java
```

#### 2. Konfiguriere die Puppeteer Service URL in `application.properties`:

```properties
# Image Service Configuration
image.service.url=http://localhost:3000

# Für Production (Docker):
# image.service.url=http://image-service:3000
```

#### 3. Füge Maven/Gradle Dependencies hinzu (falls noch nicht vorhanden):

**Maven (pom.xml):**
```xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
```

**Gradle (build.gradle):**
```gradle
implementation 'org.springframework.boot:spring-boot-starter-web'
```

### Schritt 3: JavaScript SDK deployen

Das Frontend-SDK wurde bereits gebaut:

```bash
cd /Users/christianzillmann/IdeaProjects/releasebird-javascript-sdk
npm run build
# Output: build/index.js (104 KiB)
```

Deploy die `build/index.js` Datei zu deinem CDN oder Static Hosting.

## API Endpoints

### Puppeteer Service (Node.js)

#### POST /render
Rendert HTML zu Image.

**Request:**
```json
{
  "html": "<!DOCTYPE html><html>...</html>",
  "width": 1920,
  "height": 1080,
  "url": "https://example.com"
}
```

**Response:**
```json
{
  "image": "data:image/jpeg;base64,/9j/4AAQSkZJRg...",
  "width": 1920,
  "height": 1080
}
```

#### GET /health
Health Check Endpoint.

**Response:**
```json
{
  "status": "healthy",
  "browser": "connected"
}
```

### Spring Boot Controller

#### POST /ewidget/image/render
Proxy für Puppeteer Service.

**Request:** Gleich wie Puppeteer Service
**Response:** Gleich wie Puppeteer Service

#### GET /ewidget/image/health
Prüft ob Image Service erreichbar ist.

**Response:**
```json
{
  "status": "ok",
  "puppeteer_service": "healthy"
}
```

## Production Deployment

### Docker Compose Setup (Empfohlen)

```yaml
version: '3.8'

services:
  spring-boot-api:
    image: your-spring-boot-app:latest
    environment:
      - SCREENSHOT_SERVICE_URL=http://image-service:3000
    ports:
      - "8080:8080"
    depends_on:
      - image-service

  image-service:
    image: releasebird-image-service:latest
    environment:
      - NODE_ENV=production
      - PORT=3000
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 2G
```

### Kubernetes Deployment

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: image-service
spec:
  replicas: 2
  selector:
    matchLabels:
      app: image-service
  template:
    metadata:
      labels:
        app: image-service
    spec:
      containers:
      - name: puppeteer
        image: releasebird-image-service:latest
        ports:
        - containerPort: 3000
        resources:
          limits:
            memory: "2Gi"
            cpu: "2"
          requests:
            memory: "1Gi"
            cpu: "1"
        livenessProbe:
          httpGet:
            path: /health
            port: 3000
          initialDelaySeconds: 30
          periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
  name: image-service
spec:
  selector:
    app: image-service
  ports:
  - port: 3000
    targetPort: 3000
```

## Performance & Skalierung

### Ressourcen-Empfehlungen

**Minimum:**
- 1 CPU Core
- 1 GB RAM

**Empfohlen (Production):**
- 2 CPU Cores
- 2 GB RAM

**Hohe Last:**
- 4+ CPU Cores
- 4+ GB RAM
- Mehrere Replicas

### Browser-Instanz Management

Der Puppeteer Service verwendet eine wiederverwendbare Browser-Instanz:
- **Cold Start:** ~2-3 Sekunden (beim ersten Request)
- **Warm Requests:** ~500ms - 1s pro Image

### Horizontal Scaling

Für hohe Last, skaliere den Puppeteer Service horizontal:

```bash
# Docker Compose
docker-compose up -d --scale image-service=3

# Kubernetes
kubectl scale deployment image-service --replicas=5
```

Verwende einen Load Balancer (z.B. Nginx, Traefik) vor den Puppeteer Instances.

## Monitoring & Troubleshooting

### Logs anzeigen

**Docker:**
```bash
docker-compose logs -f image-service
```

**Kubernetes:**
```bash
kubectl logs -f deployment/image-service
```

### Häufige Probleme

#### 1. Browser startet nicht
```
Error: Failed to launch the browser process
```

**Lösung:**
- Stelle sicher, dass `/dev/shm` genug Platz hat
- Erhöhe Docker Memory Limit
- Nutze `--disable-dev-shm-usage` Flag (bereits in Dockerfile)

#### 2. Out of Memory
```
FATAL ERROR: Reached heap limit
```

**Lösung:**
- Erhöhe Container Memory Limit
- Reduziere parallele Requests
- Implementiere Request Queue

#### 3. Timeout Errors
```
TimeoutError: Navigation timeout of 30000 ms exceeded
```

**Lösung:**
- Erhöhe Timeout in Spring Boot RestTemplate
- Optimiere HTML (weniger externe Ressourcen)
- Prüfe Netzwerk-Latenz

### Health Monitoring

Verwende die Health Endpoints für Monitoring:

```bash
# Puppeteer Service
curl http://localhost:3000/health

# Spring Boot Controller
curl http://localhost:8080/ewidget/image/health
```

Integriere mit Prometheus/Grafana für Production Monitoring.

## Sicherheit

### Best Practices

1. **Rate Limiting:** Implementiere Rate Limiting im Spring Boot Controller
2. **Input Validation:** Validiere HTML Input (max size, content type)
3. **Network Isolation:** Puppeteer Service sollte nur von Spring Boot erreichbar sein
4. **Resource Limits:** Setze CPU/Memory Limits in Docker
5. **Sandbox:** Puppeteer läuft bereits mit `--no-sandbox` (für Docker notwendig)

### Beispiel Rate Limiting (Spring Boot)

```java
@Configuration
public class RateLimitConfig {
    @Bean
    public Bucket createBucket() {
        Bandwidth limit = Bandwidth.classic(10, Refill.intervally(10, Duration.ofMinutes(1)));
        return Bucket.builder()
            .addLimit(limit)
            .build();
    }
}
```

## Testing

### Unit Test (Puppeteer Service)

```bash
cd image-service
npm test
```

### Integration Test (Spring Boot)

```java
@SpringBootTest
@AutoConfigureMockMvc
class ImageControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @Test
    void testRenderImage() throws Exception {
        String html = "<!DOCTYPE html><html><body>Test</body></html>";

        mockMvc.perform(post("/ewidget/image/render")
                .contentType(MediaType.APPLICATION_JSON)
                .content("{\"html\":\"" + html + "\",\"width\":800,\"height\":600}"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.image").exists());
    }
}
```

### Manual Test (curl)

```bash
# Test Puppeteer Service direkt
curl -X POST http://localhost:3000/render \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<!DOCTYPE html><html><body><h1>Test Image</h1></body></html>",
    "width": 1280,
    "height": 720
  }'

# Test via Spring Boot
curl -X POST http://localhost:8080/ewidget/image/render \
  -H "Content-Type: application/json" \
  -H "apiKey: YOUR_API_KEY" \
  -d '{
    "html": "<!DOCTYPE html><html><body><h1>Test Image</h1></body></html>",
    "width": 1280,
    "height": 720,
    "url": "https://example.com"
  }'
```

## Migration vom alten System

### Vorher (html-to-image im Browser)
- ❌ CORS Probleme mit externen CSS/Fonts
- ❌ Broken Images von S3
- ❌ Browser-Kompatibilitätsprobleme
- ❌ Große JavaScript Bundle Size

### Nachher (Puppeteer Backend)
- ✅ Keine CORS Probleme
- ✅ Alle externen Ressourcen laden korrekt
- ✅ Konsistente Images über alle Browser
- ✅ Kleinere JavaScript Bundle Size (104 KB statt 120 KB)

### Rollout Plan

1. **Phase 1:** Deploy Puppeteer Service
2. **Phase 2:** Deploy Spring Boot Controller
3. **Phase 3:** Deploy neues JavaScript SDK
4. **Phase 4:** Monitoring & Fine-Tuning

## Support & Kontakt

Bei Problemen oder Fragen:
- GitHub Issues: https://github.com/bxt-team/releasebird-javascript-sdk/issues
- Email: support@releasebird.com

## Lizenz

Commercial License - buildnext GmbH
