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.
