Swagger ve OpenAPI ile API Dokümantasyonu Oluşturma

API geliştirme süreçlerinde en çok ihmal edilen ama en çok ihtiyaç duyulan şey dokümantasyon. Bir API’yi yazdın, çalışıyor, testleri geçiyor… ama üç ay sonra başka bir geliştirici o API’yi kullanmak istediğinde ne oluyor? Ya da sen kendin altı ay önce yazdığın endpoint’in tam olarak ne döndürdüğünü hatırlamaya çalışıyorsun. İşte tam bu noktada Swagger ve OpenAPI devreye giriyor.

Bu yazıda hem teorik altyapıyı hem de gerçek dünya senaryolarını ele alacağız. Sadece “şunu çalıştır, bu çıkar” değil, neden böyle yapıyoruz, güvenlik açısından nelere dikkat etmeliyiz, production ortamında nasıl yönetmeliyiz gibi sorulara da yanıt vereceğiz.

OpenAPI ve Swagger Arasındaki Fark

Önce şu kavram karışıklığını giderelim. OpenAPI, bir API’nin nasıl göründüğünü tanımlayan bir spesifikasyon standardıdır. YAML veya JSON formatında yazılır ve API’nin endpoint’lerini, parametrelerini, response formatlarını, authentication yöntemlerini tanımlar.

Swagger ise başlangıçta bu spesifikasyonun adıydı. SmartBear firması tarafından satın alındıktan sonra spesifikasyon OpenAPI Initiative’e devredildi ve OpenAPI adını aldı. Swagger artık bu spesifikasyonu görselleştiren ve üzerinde çalışmayı kolaylaştıran araç setinin adı.

Yani:

  • OpenAPI Specification (OAS): Standart, dil
  • Swagger UI: OpenAPI dosyalarını görselleştiren arayüz
  • Swagger Editor: OpenAPI dosyalarını yazmak için web tabanlı editör
  • Swagger Codegen: OpenAPI tanımından client/server kodu üreten araç

OpenAPI Dosyası Anatomisi

Bir OpenAPI dosyasının temel yapısını anlamak, her şeyin başlangıcı. Basit bir örnek ile başlayalım:

# openapi.yaml dosyasini olustur
cat > openapi.yaml << 'EOF'
openapi: 3.0.3
info:
  title: Kullanici Yonetim API
  description: |
    Kullanici kayit, giris ve profil yonetimi icin API.
    Bu API JWT tabanlı kimlik dogrulama kullanmaktadir.
  version: 1.0.0
  contact:
    name: API Ekibi
    email: [email protected]

servers:
  - url: https://api.sirket.com/v1
    description: Production sunucu
  - url: https://staging-api.sirket.com/v1
    description: Staging sunucu
  - url: http://localhost:3000/v1
    description: Lokal gelistirme

security:
  - BearerAuth: []

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

paths:
  /users:
    get:
      summary: Kullanici listesi
      tags:
        - Users
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
            maximum: 100
      responses:
        '200':
          description: Basarili
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/User'
                  total:
                    type: integer
        '401':
          description: Kimlik dogrulama hatasi
EOF

Bu yapı oldukça okunaklı. Herhangi bir geliştirici bu dosyayı açtığında ne tür bir API ile karşılaştığını anında anlıyor.

Swagger UI Kurulumu ve Konfigürasyonu

Docker ile Hızlı Kurulum

Production ortamında Swagger UI’ı Docker ile ayağa kaldırmak en pratik yöntem:

# Temel Swagger UI container'i ayaga kaldir
docker run -d 
  --name swagger-ui 
  -p 8080:8080 
  -e SWAGGER_JSON=/api/openapi.yaml 
  -v $(pwd)/docs:/api 
  swaggerapi/swagger-ui

# Container durumunu kontrol et
docker ps | grep swagger-ui

# Logları incele
docker logs -f swagger-ui

Nginx ile Reverse Proxy Arkasında Yayın

Gerçek dünya senaryolarında Swagger UI’ı doğrudan expose etmezsin. Nginx arkasına alırsın, authentication eklersin:

# Nginx konfigurasyonu olustur
cat > /etc/nginx/sites-available/swagger << 'EOF'
server {
    listen 443 ssl;
    server_name docs.api.sirket.com;

    ssl_certificate /etc/letsencrypt/live/docs.api.sirket.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/docs.api.sirket.com/privkey.pem;

    # Basic Auth ile koruma
    auth_basic "API Dokumantasyon";
    auth_basic_user_file /etc/nginx/.htpasswd;

    location / {
        proxy_pass http://localhost:8080;
        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;
    }

    # OpenAPI dosyasina direkt erisim
    location /openapi.yaml {
        alias /var/www/api-docs/openapi.yaml;
        add_header Content-Type "application/yaml";
        # CORS ayarlari
        add_header Access-Control-Allow-Origin "*";
    }
}
EOF

# htpasswd dosyasi olustur
htpasswd -c /etc/nginx/.htpasswd api-user

# Nginx konfigurasyonunu test et ve yeniden yukle
nginx -t && systemctl reload nginx

Node.js/Express ile Entegrasyon

Eğer Node.js kullanıyorsan, dokümantasyonu kod ile birlikte tutmak çok daha mantıklı. Kod değiştiğinde dokümantasyonu ayrıca güncellemeyi unutma ihtimalin ortadan kalkıyor:

# Gerekli paketleri yukle
npm install swagger-ui-express swagger-jsdoc

# Express uygulamasina Swagger entegre et
cat > swagger-config.js << 'EOF'
const swaggerJsdoc = require('swagger-jsdoc');

const options = {
  definition: {
    openapi: '3.0.3',
    info: {
      title: 'E-Ticaret API',
      version: '2.1.0',
      description: 'Urun, siparis ve kullanici yonetimi API',
    },
    servers: [
      {
        url: process.env.API_BASE_URL || 'http://localhost:3000',
      },
    ],
    components: {
      securitySchemes: {
        ApiKeyAuth: {
          type: 'apiKey',
          in: 'header',
          name: 'X-API-Key',
        },
        BearerAuth: {
          type: 'http',
          scheme: 'bearer',
          bearerFormat: 'JWT',
        },
      },
    },
  },
  // JSDoc yorumlari hangi dosyalardan okunacak
  apis: ['./routes/*.js', './models/*.js'],
};

const specs = swaggerJsdoc(options);
module.exports = specs;
EOF

# Ana app.js dosyasina entegrasyon
cat >> app.js << 'EOF'
const swaggerUi = require('swagger-ui-express');
const specs = require('./swagger-config');

// Production'da dokumantasyona erisimi kisitla
if (process.env.NODE_ENV !== 'production') {
  app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs));
} else {
  // Production'da sadece dahili IP'lerden erisim
  app.use('/api-docs', checkInternalIP, swaggerUi.serve, swaggerUi.setup(specs));
}
EOF

Python/FastAPI ile Otomatik Dokümantasyon

FastAPI kullanıyorsan işin çok daha kolay. Framework doğrudan OpenAPI desteğiyle geliyor:

# FastAPI projesi kur
pip install fastapi uvicorn

# Basit bir FastAPI uygulamasi
cat > main.py << 'EOF'
from fastapi import FastAPI, HTTPException, Depends, Security
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from pydantic import BaseModel, EmailStr
from typing import List, Optional
import uvicorn

app = FastAPI(
    title="Musteri Yonetim API",
    description="""
    ## Musteri Yonetim Sistemi API

    Bu API asagidaki islemleri destekler:
    * Musteri kayit ve listeleme
    * Siparis yonetimi
    * Rapor uretimi

    ### Kimlik Dogrulama
    Tum endpoint'ler JWT token gerektirir.
    """,
    version="1.0.0",
    docs_url="/docs",        # Swagger UI
    redoc_url="/redoc",      # ReDoc UI
    openapi_url="/openapi.json"
)

class Musteri(BaseModel):
    id: Optional[int] = None
    ad: str
    soyad: str
    email: EmailStr
    telefon: Optional[str] = None

    class Config:
        schema_extra = {
            "example": {
                "ad": "Ahmet",
                "soyad": "Yilmaz",
                "email": "[email protected]",
                "telefon": "+90 555 123 4567"
            }
        }

security = HTTPBearer()

@app.get(
    "/musteriler",
    response_model=List[Musteri],
    tags=["Musteriler"],
    summary="Tum musterileri listele",
    description="Sistemdeki tum musterileri sayfalama destegi ile listeler."
)
async def musterileri_listele(
    sayfa: int = 1,
    limit: int = 20,
    credentials: HTTPAuthorizationCredentials = Security(security)
):
    # Token dogrulama burada yapilir
    return []

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)
EOF

# Uygulamayi calistir
python main.py

# Dokumantasyon URL'leri:
# Swagger UI: http://localhost:8000/docs
# ReDoc: http://localhost:8000/redoc
# OpenAPI JSON: http://localhost:8000/openapi.json

Güvenlik Açısından Dikkat Edilmesi Gerekenler

Bu kısım çok önemli ve çoğu zaman atlanıyor. Swagger UI’ı yanlış yapılandırmak ciddi güvenlik açıkları yaratabilir.

Production Ortamında Swagger UI Yönetimi

# Environment bazli Swagger kontrolu
cat > swagger-security.sh << 'EOF'
#!/bin/bash

ENVIRONMENT=${NODE_ENV:-development}
SWAGGER_ENABLED=${SWAGGER_ENABLED:-false}
ALLOWED_IPS="10.0.0.0/8 172.16.0.0/12 192.168.0.0/16"

case $ENVIRONMENT in
  production)
    if [ "$SWAGGER_ENABLED" = "true" ]; then
      echo "UYARI: Production'da Swagger UI aktif!"
      echo "Erisimi IP bazli kisitlama uygulaniyor..."

      # iptables ile sadece dahili aglardan erisim
      iptables -A INPUT -p tcp --dport 8080 -s 10.0.0.0/8 -j ACCEPT
      iptables -A INPUT -p tcp --dport 8080 -s 172.16.0.0/12 -j ACCEPT
      iptables -A INPUT -p tcp --dport 8080 -j DROP

      echo "Swagger UI sadece dahili IP'lerden erisime acik"
    else
      echo "Production: Swagger UI devre disi"
    fi
    ;;
  staging)
    echo "Staging: Swagger UI aktif, Basic Auth ile korunuyor"
    ;;
  development)
    echo "Development: Swagger UI tamamen acik"
    ;;
esac
EOF

chmod +x swagger-security.sh

API Key ve Token Bilgilerini Koruma

Swagger UI’da gerçek API key’leri test ederken dikkatli olmak gerekiyor. Özellikle paylaşılan ortamlarda:

# Swagger UI icin guvenli environment variables ayarla
cat > docker-compose.swagger.yml << 'EOF'
version: '3.8'
services:
  swagger-ui:
    image: swaggerapi/swagger-ui
    ports:
      - "127.0.0.1:8080:8080"  # Sadece localhost'tan erisim
    environment:
      - SWAGGER_JSON=/api/openapi.yaml
      # Varsayilan olarak try-it-out'u devre disi birak
      - TRY_IT_OUT_ENABLED=false
      # CORS kisitlamasi
      - CORS_ORIGINS=https://docs.sirket.com
    volumes:
      - ./docs:/api:ro  # Read-only mount
    networks:
      - internal
    restart: unless-stopped

networks:
  internal:
    internal: true
EOF

OpenAPI Dosyalarını Versiyonlama ve CI/CD Entegrasyonu

Dokümantasyonu kod ile birlikte versiyonlamak en iyi pratik. Git repository’sine ekle, her değişikliği takip et:

# openapi dosyasini validate eden script
cat > validate-openapi.sh << 'EOF'
#!/bin/bash

echo "OpenAPI dosyasi validate ediliyor..."

# swagger-cli yuklu degil ise yukle
if ! command -v swagger-cli &> /dev/null; then
    npm install -g @apidevtools/swagger-cli
fi

# Validation calistir
swagger-cli validate openapi.yaml

if [ $? -eq 0 ]; then
    echo "Validation basarili!"
else
    echo "HATA: OpenAPI dosyasinda sorunlar var!"
    exit 1
fi

# Referanslari coz ve tek dosyaya birlestir
swagger-cli bundle openapi.yaml 
    --outfile dist/openapi-bundled.yaml 
    --type yaml

echo "Bundle dosyasi olusturuldu: dist/openapi-bundled.yaml"
EOF

chmod +x validate-openapi.sh

# GitHub Actions workflow
mkdir -p .github/workflows
cat > .github/workflows/openapi-check.yml << 'EOF'
name: OpenAPI Validation

on:
  push:
    paths:
      - 'openapi.yaml'
      - 'docs/**/*.yaml'
  pull_request:
    paths:
      - 'openapi.yaml'

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Node.js kur
        uses: actions/setup-node@v3
        with:
          node-version: '18'

      - name: swagger-cli yukle
        run: npm install -g @apidevtools/swagger-cli

      - name: OpenAPI validate et
        run: swagger-cli validate openapi.yaml

      - name: Breaking changes kontrol et
        run: |
          npm install -g @opticdev/api-diff
          # Onceki versiyonla karsilastir
          git show HEAD~1:openapi.yaml > /tmp/old-openapi.yaml || true
          if [ -f /tmp/old-openapi.yaml ]; then
            api-diff /tmp/old-openapi.yaml openapi.yaml
          fi
EOF

Gerçek Dünya Senaryosu: Microservice Mimarisinde Merkezi Dokümantasyon

Birden fazla microservice’in olduğu bir ortamda her servisin ayrı OpenAPI dosyası olur. Bunları tek bir yerde toplamak için Swagger aggregation yapısı kurabilirsin:

# Merkezi dokumantasyon toplama scripti
cat > aggregate-docs.sh << 'EOF'
#!/bin/bash

SERVICES=(
    "user-service:http://user-service:3001"
    "order-service:http://order-service:3002"
    "payment-service:http://payment-service:3003"
    "notification-service:http://notification-service:3004"
)

OUTPUT_DIR="./combined-docs"
mkdir -p $OUTPUT_DIR

echo "Servis dokumantasyonlari toplanıyor..."

for service_info in "${SERVICES[@]}"; do
    SERVICE_NAME="${service_info%%:*}"
    SERVICE_URL="${service_info#*:}"

    echo "$SERVICE_NAME servisi icin OpenAPI dosyasi indiriliyor..."

    curl -sf "$SERVICE_URL/openapi.json" 
        -o "$OUTPUT_DIR/${SERVICE_NAME}.json"

    if [ $? -eq 0 ]; then
        echo "$SERVICE_NAME: Basarili"
    else
        echo "$SERVICE_NAME: HATA - Servis erisilebilir degil"
    fi
done

# Swagger UI icin urls config olustur
cat > "$OUTPUT_DIR/urls-config.json" << JSONEOF
[
    {"name": "Kullanici Servisi", "url": "/docs/user-service.json"},
    {"name": "Siparis Servisi", "url": "/docs/order-service.json"},
    {"name": "Odeme Servisi", "url": "/docs/payment-service.json"},
    {"name": "Bildirim Servisi", "url": "/docs/notification-service.json"}
]
JSONEOF

echo "Tum dokumantasyonlar $OUTPUT_DIR dizininde hazir"

# Swagger UI'i multiple API destekli baslat
docker run -d 
    --name api-hub 
    -p 8080:8080 
    -e URLS="$(cat $OUTPUT_DIR/urls-config.json)" 
    -v $OUTPUT_DIR:/usr/share/nginx/html/docs 
    swaggerapi/swagger-ui

echo "API Hub hazir: http://localhost:8080"
EOF

chmod +x aggregate-docs.sh

Postman Koleksiyonuna Dönüştürme

OpenAPI dosyasını Postman’e import ederek test koleksiyonu oluşturabilirsin. Bu özellikle QA ekipleri ve yeni geliştiriciler için çok işe yarıyor:

# openapi2postman kurulumu ve kullanimi
npm install -g openapi-to-postmanv2

# OpenAPI dosyasini Postman koleksiyonuna donustur
openapi2postmanv2 convert 
    -s openapi.yaml 
    -o postman-collection.json 
    --options '{"requestParametersResolution": "Example", "exampleParametersResolution": "Example"}'

# Postman CLI ile otomatik test calistir (Newman)
npm install -g newman

newman run postman-collection.json 
    --environment postman-env.json 
    --reporters cli,html 
    --reporter-html-export test-results.html

echo "Test sonuclari: test-results.html"

Sık Yapılan Hatalar ve Çözümleri

Yıllar içinde sık karşılaştığım hataları ve çözümlerini paylaşayım:

Hata 1: Circular reference hatası

OpenAPI dosyanda $ref kullanırken döngüsel referans oluşabilir. swagger-cli validate komutu bunu yakalar ama bazen anlamsız hata mesajı verir.

Hata 2: CORS sorunları

Swagger UI farklı bir domain’de çalışırken API’ye istek atarken CORS hatası alırsın. API sunucunda Swagger UI domain’ini CORS whitelist’e eklemen gerekir.

Hata 3: Büyük response body’leri

Swagger UI çok büyük response’ları render etmekte zorlanabilir. maxDisplayedTags ve response boyut limitlerini ayarlamak gerekebilir.

Hata 4: Authentication token’ının Swagger’da saklanması

Swagger UI token’ı browser’ın local storage’ında tutar. Shared bilgisayarlarda bu ciddi güvenlik riski oluşturur. Session timeout eklemek şart.

# Swagger UI icin oturum timeout ayari
cat > swagger-custom.js << 'EOF'
// Swagger UI acildiginda 30 dakika sonra token temizle
window.onload = function() {
    setTimeout(function() {
        // Swagger UI store'dan token temizle
        if (window.ui) {
            window.ui.authActions.logout({auth: {name: 'BearerAuth'}});
            console.log('Guvenlik: Oturum suresi doldu, token temizlendi');
        }
    }, 30 * 60 * 1000); // 30 dakika
};
EOF

Monitoring ve Kullanım Analizi

Swagger UI’ın ne kadar kullanıldığını, hangi endpoint’lerin dokümantasyonunun yetersiz olduğunu takip etmek de önemli:

# Nginx access log'larindan Swagger kullanimi analiz et
cat > analyze-swagger-usage.sh << 'EOF'
#!/bin/bash

LOG_FILE="/var/log/nginx/access.log"
DATE=$(date +%Y-%m-%d)

echo "=== Swagger UI Kullanim Analizi ($DATE) ==="

echo ""
echo "Toplam Swagger UI ziyareti:"
grep "/api-docs" $LOG_FILE | grep "$DATE" | wc -l

echo ""
echo "En cok goruntulenen endpoint dokumantasyonlari:"
grep "swagger" $LOG_FILE | 
    awk '{print $7}' | 
    sort | uniq -c | 
    sort -rn | head -10

echo ""
echo "Kullanici bazli erisim (IP bazli):"
grep "/api-docs" $LOG_FILE | 
    awk '{print $1}' | 
    sort | uniq -c | 
    sort -rn | head -5
EOF

chmod +x analyze-swagger-usage.sh

Sonuç

Swagger ve OpenAPI, API dokümantasyonunu “sonra yaparım” kategorisinden çıkarıp geliştirme sürecinin ayrılmaz bir parçası haline getiriyor. Kod ile birlikte yaşayan, otomatik olarak güncellenen ve test edilebilir bir dokümantasyon sistemi kurmak artık çok daha kolay.

Bu yazıda öğrendiklerimizi özetleyelim:

  • OpenAPI spec’ini kod ile birlikte tut, ayrı bir wiki’de değil. Git repository’sine ekle, her değişikliği takip et.
  • CI/CD pipeline’ına validation ekle. Bozuk OpenAPI dosyasının production’a gitmesini engelle.
  • Production’da Swagger UI’ı koruma altına al. Basic auth, IP kısıtlaması veya VPN arkasına al.
  • Microservice mimarilerinde merkezi dokümantasyon hub’ı kur, her servisi ayrı ayrı dolaşmak zorunda kalma.
  • Token ve key güvenliğine dikkat et. Swagger UI’daki test kimlik bilgileri yetkisiz ellere geçebilir.
  • Postman entegrasyonu ile QA ekibinin işini kolaylaştır.

Dokümantasyon yazmak sıkıcı gelebilir, ama altı ay sonra gece 2’de production’daki bir API’yi debug etmeye çalışırken iyi bir Swagger dosyasının değerini anlıyorsun. O gece seni kurtaran kişi çoğunlukla geçmişteki kendindir.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir