HTTPie ile Modern HTTP İstemcisi Kullanımı ve REST API Testi

Yıllarca curl kullandım, hala da kullanıyorum ama artık günlük API testlerimin büyük çoğunluğunu httpie ile yapıyorum. Nedeni basit: curl ile bir POST isteği atmak için 3-4 flag ezberlemeniz gerekiyor, httpie’de ise neredeyse düz İngilizce yazıyorsunuz. Bu yazıda httpie’yi sıfırdan ele alacağız, gerçek senaryolarla REST API testini ve günlük kullanımını inceleyeceğiz.

HTTPie Nedir ve Neden Kullanmalısınız

HTTPie, Python ile yazılmış modern bir komut satırı HTTP istemcisidir. Curl’ün yerini almaktan ziyade, geliştiriciler ve sistem yöneticileri için okunabilirliği ön plana çıkaran bir araç olarak konumlanıyor. Syntax renklendirmesi, JSON desteği, oturum yönetimi ve eklenti sistemi ile öne çıkıyor.

Şunu söyleyeyim: Production ortamında bir API’nin neden hatalı cevap verdiğini araştırıyorsunuz, acele ediyorsunuz ve terminalden hızlıca bir istek atmanız gerekiyor. Curl ile o anda Content-Type header’ını nasıl yazacağınızı, body’yi nasıl formatlayacağınızı düşünmek zorunda kalıyorsunuz. HTTPie’de bu sıkıntı yok.

Temel avantajları:

  • Renkli ve formatlanmış çıktı (JSON otomatik güzelleştirme)
  • İnsan dostu sözdizimi
  • Oturum desteği (cookie ve header’ları session bazında saklama)
  • Form ve JSON gönderimi için ayrı notasyon
  • Dosya yükleme desteği
  • HTTPS doğrulama kontrolü
  • Plugin sistemi

Kurulum

Farklı platformlarda kurulum oldukça basit:

# Ubuntu/Debian
sudo apt update && sudo apt install httpie

# RHEL/CentOS/Rocky Linux
sudo dnf install httpie

# macOS (Homebrew)
brew install httpie

# pip ile (her platform)
pip install httpie

# pipx ile (izole ortam, önerilen)
pipx install httpie

Kurulumdan sonra http komutu ile erişebilirsiniz. Bazı sistemlerde https komutu da otomatik olarak gelir (HTTPS kısayolu olarak).

# Versiyon kontrolü
http --version

# Yardım
http --help

Temel Kullanım

HTTPie sözdizimi şu şekilde:

http [METOD] URL [ÖĞELER...]

En basit GET isteği:

# Basit GET
http GET https://jsonplaceholder.typicode.com/posts/1

# Metod belirtmezseniz GET kabul eder
http https://jsonplaceholder.typicode.com/posts/1

# Sadece body çıktısı (header olmadan)
http --body https://jsonplaceholder.typicode.com/posts/1

Çıktıda hem istek hem yanıt header’larını, hem de güzelleştirilmiş JSON body’yi göreceksiniz. İlk kez kullandığınızda bu kadar temiz bir çıktıya alışmak biraz zaman alıyor.

Header, Query String ve Authentication

# Custom header eklemek: isim:değer notasyonu
http GET https://api.example.com/users 
  Authorization:"Bearer eyJhbGc..." 
  Accept:application/json 
  X-Request-ID:abc123

# Query string parametreleri: isim==değer notasyonu
http GET https://api.example.com/users 
  page==2 
  per_page==20 
  status==active

# Basic Auth
http -a kullanici:sifre GET https://api.example.com/protected

# Digest Auth
http --auth-type=digest -a kullanici:sifre GET https://api.example.com/digest

Notasyona dikkat edin, bu httpie’nin en önemli özelliklerinden biri:

  • : (tek noktalı virgül) header için
  • == (çift eşittir) query string için
  • = (tek eşittir) JSON/form string değeri için
  • := (iki noktalı eşittir) JSON için raw değer (sayı, boolean, array) için

POST, PUT, PATCH İstekleri ve JSON Gönderimi

# JSON POST - otomatik Content-Type: application/json ekler
http POST https://jsonplaceholder.typicode.com/posts 
  title="HTTPie Test Yazisi" 
  body="Bu bir test icerigi" 
  userId:=1

# Nested JSON ve array göndermek
http POST https://api.example.com/orders 
  customer_id:=42 
  items:='[{"product_id": 1, "qty": 2}, {"product_id": 5, "qty": 1}]' 
  metadata:='{"source": "web", "campaign": "summer2024"}'

# PUT isteği
http PUT https://jsonplaceholder.typicode.com/posts/1 
  id:=1 
  title="Guncellenmis Baslik" 
  body="Guncellenmis icerik" 
  userId:=1

# PATCH - kısmi güncelleme
http PATCH https://jsonplaceholder.typicode.com/posts/1 
  title="Sadece Baslik Degisti"

Form verisi göndermek için --form ya da -f flag’ini kullanıyorsunuz:

# Form POST (application/x-www-form-urlencoded)
http --form POST https://httpbin.org/post 
  username=admin 
  password=secret123 
  remember_me=true

# Multipart form (dosya yükleme)
http --form POST https://api.example.com/upload 
  file@/home/user/rapor.pdf 
  description="Aylik rapor" 
  category=finance

Gerçek Dünya Senaryosu 1: Servis Sağlık Kontrolü Script’i

Diyelim ki birden fazla microservice’iniz var ve bunların health endpoint’lerini hızlıca kontrol etmeniz gerekiyor. Bash script ile httpie’yi birleştirince oldukça temiz bir çözüm çıkıyor:

#!/bin/bash

SERVICES=(
    "api-gateway:https://api-gateway.internal/health"
    "auth-service:https://auth.internal/health"
    "payment-service:https://payment.internal/health"
    "notification-service:https://notify.internal/health"
)

FAILED=0

for service_entry in "${SERVICES[@]}"; do
    service_name="${service_entry%%:*}"
    service_url="${service_entry#*:}"
    
    response=$(http --check-status --timeout=5 GET "$service_url" 2>&1)
    exit_code=$?
    
    if [ $exit_code -eq 0 ]; then
        status=$(echo "$response" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('status','unknown'))" 2>/dev/null)
        echo "[OK] $service_name - Status: ${status:-up}"
    else
        echo "[FAIL] $service_name - Yanit alinamadi veya hata kodu dondu"
        FAILED=$((FAILED + 1))
    fi
done

echo ""
echo "Toplam: ${#SERVICES[@]} servis, $FAILED adet basarisiz"
exit $FAILED

--check-status flag’i önemli: HTTP 4xx veya 5xx dönerse script exit code olarak hata veriyor, böylece CI/CD pipeline’ınızda bunu yakalayabiliyorsunuz.

Oturum Yönetimi

HTTPie’nin bence en underrated özelliği oturum desteği. Bir kez giriş yapıyorsunuz, cookie ve header’lar otomatik saklanıyor:

# İlk istek: giriş ve session oluşturma
http --session=myapi POST https://api.example.com/auth/login 
  username=admin 
  password=supersecret

# Sonraki isteklerde session kullanma (token/cookie otomatik gönderilir)
http --session=myapi GET https://api.example.com/dashboard

http --session=myapi GET https://api.example.com/users

# Session dosyasını görmek (hangi bilgilerin saklandığını anlamak için)
cat ~/.config/httpie/sessions/api.example.com/myapi.json

Session dosyaları JSON formatında saklanıyor ve içinde header’lar, cookie’ler, auth bilgileri bulunuyor. Bu özellik özellikle staginge karşı manuel testler yaparken inanılmaz zaman kazandırıyor.

Gerçek Dünya Senaryosu 2: Token Bazlı API Testi

JWT bearer token kullanan bir API’yi test ederken tipik akış şöyle:

# 1. Token al
TOKEN=$(http POST https://api.example.com/auth/token 
  grant_type=client_credentials 
  client_id=myapp 
  client_secret=gizlisifre 
  --body | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")

echo "Token alindi: ${TOKEN:0:20}..."

# 2. Token ile istek at
http GET https://api.example.com/api/v1/customers 
  "Authorization:Bearer $TOKEN" 
  page==1 
  limit==50

# 3. Oluşturma isteği
http POST https://api.example.com/api/v1/customers 
  "Authorization:Bearer $TOKEN" 
  name="Test Musterisi" 
  email="[email protected]" 
  phone="+905551234567" 
  tier:=2 
  active:=true

Çıktı Kontrolü ve Debug

# Sadece response header'larını gör
http --headers GET https://api.example.com/users

# Sadece response body'yi gör
http --body GET https://api.example.com/users

# Verbose mod: istek + yanıt tamamı
http --verbose GET https://api.example.com/users

# Çok daha detaylı debug (TLS bilgisi dahil)
http --debug GET https://api.example.com/users

# Gerçekte ne gönderdiğini gör ama isteği ATMA (dry-run)
http --offline POST https://api.example.com/users 
  name="Test" 
  email="[email protected]"

# Response'u dosyaya kaydet
http GET https://api.example.com/report/monthly 
  "Authorization:Bearer $TOKEN" 
  --output monthly_report.json

# İlerleme çubuğu ile büyük dosya indir
http --download GET https://releases.example.com/app-v2.1.tar.gz

--offline modu çok işe yarıyor: İsteği gerçekten göndermeden önce nasıl görüneceğini kontrol edebiliyorsunuz. Özellikle auth header’larını veya body formatını doğrulamak için ideal.

HTTPS ve Sertifika Yönetimi

# Self-signed sertifika doğrulamasını atla (test ortamları için)
http --verify=no GET https://staging-internal.example.com/api/health

# Özel CA sertifikası kullan
http --verify=/etc/ssl/certs/internal-ca.crt GET https://internal-api.example.com/

# Client sertifikası ile mutual TLS
http --cert=/path/to/client.crt 
  --cert-key=/path/to/client.key 
  GET https://api.example.com/secure-endpoint

# Sertifika bilgilerini görüntüle
http --debug --verify=no GET https://self-signed.example.com 2>&1 | grep -i cert

Production’da --verify=no kullanmaktan kaçının, ama test ve geliştirme ortamlarında self-signed sertifikalarla uğraşırken hayat kurtarıcı.

Gerçek Dünya Senaryosu 3: Elasticsearch API’si ile Çalışmak

Elasticsearch gibi JSON ağırlıklı servislerle çalışırken httpie gerçekten parlıyor:

# Cluster sağlık durumu
http GET localhost:9200/_cluster/health?pretty

# Index oluştur
http PUT localhost:9200/log-2024-01 
  settings:='{"number_of_shards": 3, "number_of_replicas": 1}' 
  mappings:='{"properties": {"timestamp": {"type": "date"}, "level": {"type": "keyword"}, "message": {"type": "text"}}}'

# Doküman ekle
http POST localhost:9200/log-2024-01/_doc 
  timestamp="2024-01-15T14:30:00Z" 
  level="ERROR" 
  service="payment-service" 
  message="Veritabani baglantisi kurulamadi" 
  host="app-server-03"

# Arama sorgusu
http POST localhost:9200/log-2024-01/_search 
  query:='{"bool": {"must": [{"term": {"level": "ERROR"}}, {"range": {"timestamp": {"gte": "2024-01-15T00:00:00Z"}}}]}}'

# Index istatistikleri
http GET localhost:9200/log-2024-01/_stats/docs,store

Curl ile aynı Elasticsearch sorgularını yazmayı deneyin, farkı anlarsınız.

Pipe ve Diğer Araçlarla Entegrasyon

# jq ile birlikte kullanım
http GET https://api.example.com/users 
  "Authorization:Bearer $TOKEN" 
  --body | jq '.data[] | {id: .id, name: .name, email: .email}'

# Sadece belirli field'ı çek
http GET https://api.example.com/users --body | 
  jq -r '.data[].email' | 
  sort > emails.txt

# Response'u başka bir isteğe pipe et
USER_ID=$(http POST https://api.example.com/users 
  name="Yeni Kullanici" 
  email="[email protected]" 
  --body | jq -r '.id')

echo "Oluşturulan kullanıcı ID: $USER_ID"

# İzin ata
http POST https://api.example.com/users/$USER_ID/roles 
  "Authorization:Bearer $TOKEN" 
  roles:='["viewer", "reporter"]'

Proxy Kullanımı

Kurumsal ortamlarda proxy arkasında çalışmak kaçınılmaz:

# HTTP proxy
http --proxy=http:http://proxy.sirket.com:8080 GET https://external-api.example.com/

# HTTPS proxy
http --proxy=https:http://proxy.sirket.com:8080 GET https://external-api.example.com/

# Environment variable ile (daha pratik)
export HTTP_PROXY=http://proxy.sirket.com:8080
export HTTPS_PROXY=http://proxy.sirket.com:8080
http GET https://external-api.example.com/

# Proxy bypass (no_proxy)
export NO_PROXY=localhost,127.0.0.1,.internal.sirket.com

Konfigürasyon Dosyası ile Varsayılan Değerler

Sürekli aynı header’ları yazmaktan sıkıldıysanız, default ayarları config dosyasına yazabilirsiniz:

# Config dosyası konumu
cat ~/.config/httpie/config.json
# Örnek config.json içeriği (bash heredoc ile oluşturma)
cat > ~/.config/httpie/config.json << 'EOF'
{
    "default_options": [
        "--style=monokai",
        "--timeout=30",
        "--verify=yes"
    ]
}
EOF

Belirli bir projeye özel config için environment variable kullanabilirsiniz:

export HTTPIE_CONFIG_DIR=~/.config/httpie/myproject
mkdir -p $HTTPIE_CONFIG_DIR

cat > $HTTPIE_CONFIG_DIR/config.json << 'EOF'
{
    "default_options": [
        "--session=default",
        "--timeout=60"
    ]
}
EOF

Kullanışlı Flag’ler Özeti

–check-status: HTTP hata kodlarında non-zero exit code döndürür, scripting için kritik

–timeout=SANIYE: İstek timeout süresi (varsayılan 0, yani sınırsız)

–follow: 301/302 yönlendirmelerini takip et

–max-redirects=N: Maksimum yönlendirme sayısı

–download / -d: Response’u dosyaya indir

–continue / -c: Yarım kalan indirmeye devam et (–download ile birlikte)

–quiet / -q: Çıktıyı bastır (sadece hata durumunda bir şey yazar)

–print=hHbB: Neyin yazdırılacağını seç (h: istek header, H: yanıt header, b: istek body, B: yanıt body)

–style=STIL: Renk teması (monokai, solarized, autumn, vs.)

–pretty=all/colors/format/none: Çıktı biçimlendirme seviyesi

–stream: Streaming yanıtlar için (Server-Sent Events gibi)

HTTPie vs Curl: Ne Zaman Hangisi?

Bu tartışmayı açmadan geçemezdim. Cevap aslında net: ikisi de lazım.

Curl her sistemde var, script’lerde curl kullanmak daha taşınabilir. Ama günlük API testlerinde, interaktif kullanımda, JSON ağırlıklı REST API’lerini keşfederken httpie çok daha verimli. Özellikle renkli çıktı ve otomatik JSON formatlaması, büyük response’ları okuyrken ciddi fark yaratıyor.

Scripting için curl, interaktif test için httpie diye düşünebilirsiniz. Zamanla her ikisini de refleks olarak kullanmaya başlıyorsunuz.

Sonuç

HTTPie’yi ilk kurduğumda “bu sadece curl’ün süslü versiyonu” diye düşünmüştüm. Yanılmışım. Özellikle oturum yönetimi, offline modu, –check-status ile scripting entegrasyonu ve JSON notasyonu, onu gerçekten ayrı bir araç olarak konumlandırıyor.

Eğer ekibinizde herkes farklı curl one-liner’ları ezberlemiş durumdaysa ve API testleri her seferinde “bu header nasıl yazılıyordu?” sorusuyla başlıyorsa, httpie geçişi yapmanın tam zamanı. Öğrenme eğrisi neredeyse yok, iki üç istek attıktan sonra notasyona alışıyorsunuz.

Elasticsearch, Kubernetes API, GitHub API gibi JSON ağırlıklı servislerle düzenli çalışıyorsanız, httpie iş akışınızın kalıcı bir parçası haline gelecek. Benim oldu en azından.

Bir yanıt yazın

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