API’leri test etmek, webhook’ları debug etmek ya da bir servisin ayakta olup olmadığını kontrol etmek istediğinde aklına ilk gelen araç muhtemelen curl oluyor. Haklısın da. curl, neredeyse her Linux sistemde hazır olarak gelen, öğrenmesi kolay ama derinlemesine incelediğinde gerçekten güçlü bir araç. Ben yıllardır production ortamlarında, CI/CD pipeline’larında ve günlük troubleshooting senaryolarında curl’ü kullanıyorum. Bu yazıda curl’ün temel kullanımından başlayıp gerçek dünya API test senaryolarına kadar her şeyi ele alacağım.
curl Nedir ve Neden Bu Kadar Popüler?
curl, “Client URL” kelimelerinin kısaltmasıdır ve komut satırından URL’lere istek gönderip veri almana yarayan bir araçtır. HTTP, HTTPS, FTP, SFTP, SCP ve daha onlarca protokolü destekler. Ama biz bugün ağırlıklı olarak HTTP/HTTPS üzerinde duracağız çünkü modern sysadmin’lerin en çok ihtiyaç duyduğu alan bu.
curl’ün bu kadar sevilmesinin birkaç temel nedeni var. Her şeyden önce neredeyse her Linux dağıtımında, macOS’ta ve artık Windows’ta bile standart olarak geliyor. İkincisi, basit senaryolarda tek satır komutla işini hallederken karmaşık API çağrılarında da son derece esnek. Üçüncüsü ise Postman gibi GUI araçlarının aksine script’lere ve otomasyona entegre etmek çok kolay.
Temel HTTP GET İstekleri
En basit curl kullanımı bir URL’e GET isteği göndermektir:
curl https://jsonplaceholder.typicode.com/posts/1
Bu kadar. Ama bu çıktı biraz dağınık görünebilir. JSON döndüren bir API ile çalışıyorsan çıktıyı daha okunaklı hale getirmek için jq aracını kullanabilirsin:
curl https://jsonplaceholder.typicode.com/posts/1 | jq .
Eğer jq kurulu değilse sudo apt install jq ya da sudo yum install jq ile kurabilirsin. Production’da çalışan sistemlerde JSON logları parse ederken jq ile curl kombinasyonu gerçekten hayat kurtarıcı oluyor.
Şimdi birkaç önemli temel parametreye bakalım:
- -v: Verbose mod, istek ve yanıtın tüm başlıklarını gösterir
- -s: Silent mod, progress bar ve hata mesajlarını gizler
- -o dosya.json: Çıktıyı terminale yazmak yerine dosyaya kaydeder
- -O: URL’deki dosya adıyla kaydeder
- -L: Yönlendirmeleri (redirect) takip eder
- -i: Response header’larını çıktıya dahil eder
- -I: Sadece header’ları getirir, body’yi getirmez (HEAD isteği)
Bir servisin canlı olup olmadığını hızlıca kontrol etmek için -I seçeneği oldukça kullanışlıdır:
curl -I https://orneksite.com
Bu komut sadece HTTP başlıklarını döndürür, sayfa içeriğini indirmez. Monitoring scriptlerinde bant genişliği tasarrufu açısından bunu tercih ediyorum.
HTTP Response Kodlarını Yakalamak
Script yazarken en sık ihtiyaç duyduğum şey HTTP response kodunu almaktır. Bunun için -o /dev/null ve -w parametrelerinin kombinasyonunu kullanıyorum:
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" https://orneksite.com/api/health)
echo "Response kodu: $HTTP_CODE"
if [ "$HTTP_CODE" -eq 200 ]; then
echo "Servis ayakta"
else
echo "Servis sorunlu! Kod: $HTTP_CODE"
fi
-w parametresi çok güçlüdür. Sadece response kodunu değil, şunları da alabilirsin:
- %{http_code}: HTTP durum kodu
- %{time_total}: Toplam istek süresi
- %{time_connect}: TCP bağlantı süresi
- %{time_starttransfer}: İlk byte’ın geldiği süre (TTFB)
- %{size_download}: İndirilen veri boyutu
- %{speed_download}: İndirme hızı
Performans testi yaparken bu değerlerin hepsini bir arada çekmek istiyorum:
curl -s -o /dev/null -w "Kod: %{http_code} | Toplam: %{time_total}s | TTFB: %{time_starttransfer}s | Boyut: %{size_download} byten" https://orneksite.com
POST İstekleri ve JSON Göndermek
REST API’leriyle çalışırken POST istekleri kaçınılmaz. Bir kullanıcı oluşturma endpoint’ine JSON veri gönderelim:
curl -X POST https://jsonplaceholder.typicode.com/posts
-H "Content-Type: application/json"
-d '{"title": "Test Post", "body": "Bu bir test", "userId": 1}'
Burada birkaç önemli nokta var. -X POST ile HTTP metodunu belirtiyoruz. -H ile header ekliyoruz, JSON gönderirken Content-Type: application/json header’ı şart. -d ise gönderilecek data.
Gerçek dünya senaryolarında JSON genellikle çok daha karmaşık oluyor. Böyle durumlarda JSON’ı bir dosyaya yazıp o dosyayı göndermek çok daha temiz:
# payload.json dosyası oluştur
cat > /tmp/payload.json << 'EOF'
{
"username": "testuser",
"email": "[email protected]",
"role": "admin",
"permissions": ["read", "write", "delete"]
}
EOF
# Dosyadan gönder
curl -X POST https://api.orneksite.com/users
-H "Content-Type: application/json"
-H "Authorization: Bearer TOKEN_BURAYA"
-d @/tmp/payload.json
-d @dosya.json syntax’ı dosyadan okuyarak gönderir. Çok büyük payload’larla çalışırken bu yöntemi her zaman tercih ediyorum.
Authentication Yöntemleri
Gerçek API’lerin büyük çoğunluğu authentication ister. En yaygın yöntemlere bakalım.
Bearer Token ile Authentication
Modern REST API’lerin büyük çoğunluğu JWT veya benzeri Bearer token kullanır:
TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
curl -H "Authorization: Bearer $TOKEN"
https://api.orneksite.com/protected/resource
Token’ı değişkende tutmak hem okunabilirliği artırır hem de script içinde birden fazla yerde kullanmayı kolaylaştırır.
Basic Authentication
Eski stil veya bazı dahili servisler Basic Auth kullanır:
curl -u kullanici:sifre https://api.orneksite.com/data
# Ya da base64 encode edilmiş haliyle
curl -H "Authorization: Basic $(echo -n 'kullanici:sifre' | base64)"
https://api.orneksite.com/data
Önemli uyarı: Şifreyi doğrudan komut satırına yazarsan bash history’de görünür. Bunun yerine değişkenden okumayı ya da read -s ile interaktif girişi tercih et.
API Key Authentication
Bazı servisler API key’i header’da veya query string’de bekler:
# Header'da
curl -H "X-API-Key: abc123def456" https://api.orneksite.com/data
# Query string'de
curl "https://api.orneksite.com/data?api_key=abc123def456"
PUT, PATCH ve DELETE İstekleri
CRUD operasyonlarının tamamını curl ile yapabilirsin.
PUT ile var olan bir kaydı tamamen güncellemek:
curl -X PUT https://jsonplaceholder.typicode.com/posts/1
-H "Content-Type: application/json"
-d '{"id": 1, "title": "Güncellenmiş Başlık", "body": "Yeni içerik", "userId": 1}'
PATCH ile kısmi güncelleme:
curl -X PATCH https://jsonplaceholder.typicode.com/posts/1
-H "Content-Type: application/json"
-d '{"title": "Sadece başlık değişti"}'
DELETE ile kayıt silmek:
curl -X DELETE https://jsonplaceholder.typicode.com/posts/1
SSL/TLS ile İlgili Durumlar
Geliştirme ortamlarında self-signed sertifika kullanan servislere bağlanmak gerekebilir. Bu durumda -k veya --insecure parametresi sertifika doğrulamasını devre dışı bırakır:
curl -k https://dev.orneksite.com/api/test
Dikkat: Bunu sadece development ve test ortamlarında kullan. Production’da asla -k kullanma. Eğer production’da sertifika hatası alıyorsan düzgün bir sertifika kurmanın yolunu bul.
Kendi CA sertifikanı belirtmek istiyorsan:
curl --cacert /path/to/ca-bundle.crt https://internal.orneksite.com/api
İstemci sertifikası (mutual TLS) gerektiren servislerde:
curl --cert /path/to/client.crt
--key /path/to/client.key
https://mtls.orneksite.com/api
Proxy Arkasında curl Kullanmak
Kurumsal ortamlarda internet erişimi çoğu zaman proxy üzerinden gelir. curl ile proxy ayarlamak oldukça basit:
curl -x http://proxy.sirket.com:8080 https://api.disservis.com/data
# Proxy authentication gerekiyorsa
curl -x http://proxy.sirket.com:8080
-U proxykullanici:proxysifre
https://api.disservis.com/data
Bunları her seferinde yazmak yerine ~/.curlrc dosyasına ekleyebilirsin:
proxy = http://proxy.sirket.com:8080
Gerçek Dünya Senaryosu: Health Check Script’i
Şimdi bunların hepsini bir araya getirerek gerçekçi bir senaryo çözelim. Birden fazla mikro servisi izleyen bir health check script’i yazalım:
#!/bin/bash
# Servis listesi
SERVICES=(
"UserService|https://api.orneksite.com/users/health"
"PaymentService|https://payment.orneksite.com/health"
"NotificationService|https://notify.orneksite.com/ping"
)
AUTH_TOKEN="Bearer ${API_TOKEN}"
ALERT_EMAIL="[email protected]"
FAILED_SERVICES=()
echo "=== Health Check Başlıyor: $(date) ==="
for SERVICE_ENTRY in "${SERVICES[@]}"; do
SERVICE_NAME=$(echo "$SERVICE_ENTRY" | cut -d'|' -f1)
SERVICE_URL=$(echo "$SERVICE_ENTRY" | cut -d'|' -f2)
# 5 saniye timeout ile istek at
RESPONSE=$(curl -s -o /tmp/health_response.json
-w "%{http_code}|%{time_total}"
--connect-timeout 5
--max-time 10
-H "Authorization: $AUTH_TOKEN"
"$SERVICE_URL")
HTTP_CODE=$(echo "$RESPONSE" | cut -d'|' -f1)
RESPONSE_TIME=$(echo "$RESPONSE" | cut -d'|' -f2)
if [ "$HTTP_CODE" -eq 200 ]; then
echo "✓ $SERVICE_NAME - OK (${RESPONSE_TIME}s)"
else
echo "✗ $SERVICE_NAME - HATA! Kod: $HTTP_CODE"
FAILED_SERVICES+=("$SERVICE_NAME")
fi
done
# Başarısız servis varsa alert gönder
if [ ${#FAILED_SERVICES[@]} -gt 0 ]; then
ALERT_BODY="Sorunlu servisler: ${FAILED_SERVICES[*]}"
curl -s -X POST https://alerts.orneksite.com/notify
-H "Content-Type: application/json"
-d "{"message": "$ALERT_BODY", "severity": "critical"}"
echo "Alert gönderildi: $ALERT_BODY"
fi
echo "=== Health Check Tamamlandı ==="
Bu script’i crontab’a ekleyerek düzenli aralıklarla çalıştırabilirsin. Ben bunu production’da her 2 dakikada bir çalıştırıyorum.
Timeout Ayarları
Network timeout’larını doğru ayarlamak production script’lerinde kritik öneme sahiptir. Ayarlamazsan bir servis cevap vermediğinde script’in sonsuza kadar beklediğini görebilirsin:
- –connect-timeout N: TCP bağlantısı kurulması için maksimum süre (saniye)
- –max-time N: Tüm işlem için maksimum toplam süre (saniye)
- –retry N: Başarısız istekleri kaç kez tekrar deneyeceği
- –retry-delay N: Yeniden denemeler arasındaki bekleme süresi (saniye)
- –retry-max-time N: Tüm retry döngüsü için maksimum süre
curl --connect-timeout 5
--max-time 30
--retry 3
--retry-delay 2
--retry-max-time 60
https://api.orneksite.com/data
Form Data ve Dosya Yükleme
Sadece JSON değil, form verileri ve dosya yükleme işlemlerini de curl ile yapabilirsin:
# URL-encoded form data
curl -X POST https://orneksite.com/login
-d "username=admin&password=gizli123"
# Multipart form data (dosya yükleme)
curl -X POST https://api.orneksite.com/upload
-H "Authorization: Bearer $TOKEN"
-F "file=@/path/to/dosya.pdf"
-F "description=Önemli döküman"
-F "category=finance"
-F parametresi otomatik olarak Content-Type: multipart/form-data header’ı ekler, bunu ayrıca belirtmene gerek yok.
Debug ve Troubleshooting
Bir API çağrısı beklendiği gibi çalışmıyorsa verbose mode devreye girer:
curl -v https://api.orneksite.com/endpoint 2>&1 | head -50
Çıktıda > ile başlayan satırlar gönderilen, < ile başlayanlar alınan header’lardır. * ile başlayanlar ise curl’ün kendi bilgi mesajlarıdır.
Daha da detaylı debug için --trace kullanabilirsin:
curl --trace /tmp/curl_trace.txt https://api.orneksite.com/endpoint
Bu komut tüm binary veriyi hex dump olarak kaydeder, gerçekten derin bir inceleme gerektiğinde kullanışlıdır.
Bir isteği önce test edip sonra göndermek istiyorsan --dry-run benzeri bir özellik olan -o /dev/null ile birlikte verbose kullanabilirsin. Ama daha pratik bir yöntem şu: API çağrısını önce --trace-ascii - ile stdout’a bas:
curl -v -s -o /dev/null https://api.orneksite.com/endpoint 2>&1
curl ile Rate Limiting Test Etmek
Production’a geçmeden önce API’nizin rate limiting davranışını test etmek isteyebilirsiniz. Basit bir döngüyle bunu yapabilirsiniz:
#!/bin/bash
API_URL="https://api.orneksite.com/limited-endpoint"
TOKEN="Bearer abc123"
for i in $(seq 1 20); do
HTTP_CODE=$(curl -s -o /dev/null
-w "%{http_code}"
-H "Authorization: $TOKEN"
"$API_URL")
echo "İstek $i: HTTP $HTTP_CODE"
# 429 Too Many Requests gelirse dur
if [ "$HTTP_CODE" -eq 429 ]; then
echo "Rate limit'e ulaşıldı! $i. istekte."
break
fi
sleep 0.1
done
Sık Yapılan Hatalar ve Çözümleri
Yıllar içinde gördüğüm en yaygın curl hatalarına ve çözümlerine değineyim:
“Could not resolve host” hatası: DNS çözümlenemiyordur. --dns-servers 8.8.8.8 ekleyerek test edebilirsin ya da /etc/resolv.conf dosyasını kontrol et.
SSL certificate problem: Sertifika zinciri eksik ya da tarih problemi var. curl -v ile detayları gör, sertifikanı güncelle veya geliştirme ortamındaysan -k kullan.
Connection timed out: Firewall engeli olabilir ya da servis gerçekten ayakta değil. --connect-timeout süresini artırıp tekrar dene, aynı zamanda traceroute ile network yolunu incele.
“Empty reply from server”: Servis bağlantıyı kabul edip hemen kapatıyor. Genellikle yanlış port veya protokol (HTTP yerine HTTPS gibi) kullanıldığında görülür.
.curlrc ile Varsayılan Ayarlar
Sürekli aynı parametreleri yazıyorsan bunları kullanıcı home dizinindeki .curlrc dosyasına ekleyebilirsin:
# ~/.curlrc
silent
show-error
location
connect-timeout = 10
max-time = 60
Bu ayarlarla artık her curl komutuna -s, -S, -L eklemeye gerek kalmaz.
Sonuç
curl, yüzeysel bakıldığında basit bir URL fetcher gibi görünse de aslında tam teşekküllü bir HTTP client. Temel GET isteklerinden başlayıp mTLS ile güvenli bağlantılara, health check script’lerinden rate limit testlerine kadar gerçekten geniş bir kullanım alanı var.
Benim için curl’ün en büyük değeri scriptlere entegrasyon kolaylığı. Postman güzel bir araç ama bir bash script’in içine Postman koyamazsın. Otomasyonun olduğu her yerde curl kaçınılmaz oluyor. Özellikle -w parametresiyle response metriklerini almak, jq ile birleştirip JSON’ı parse etmek ve bunu monitoring script’lerine entegre etmek iş akışını ciddi ölçüde hızlandırıyor.
Eğer curl’ü henüz sadece basit download işlemleri için kullanıyorsan bu yazıdaki örnekleri kendi ortamında denemen seni bir üst seviyeye taşıyacaktır. Özellikle health check script örneğini alıp kendi servislerine uyarlamanı tavsiye ediyorum. Bir kez kurduğunda “bunu daha önce neden yapmadım” diyeceksin.