Geonode logo
Geonode Team

Geonode Team

Güncellenme: 7 Ekim 2026

Yayınlanma: 2 Eylül 2026

curl ile POST İsteği Nasıl Gönderilir (+Örnekler)

`curl -d "key=value" https://example.com` bir POST isteği gönderir. Temel cevap budur ve aynı zamanda insanların daha sonra karşılaştıkları en yaygın hatanın kaynağıdır. `-d`, form-encoded içerik türünü belirler. Bu başlığı kullanarak JSON gönderirseniz, birçok API sizi 415 hatasıyla reddeder. Bu kılavuz, form verilerini, çoğu kişinin bilmediği bir kısayol da dahil olmak üzere JSON'u, dosya yüklemelerini ve çeşitli veri seçeneklerinden hangisini gerçekten istediğinizi nasıl belirleyeceğinizi ele almaktadır.

Bu konuyla pek ilgisi olmadığı için kısa tutacağımız açıklama: Biz Geonode olarak proxy satışı yapıyoruz. Bir POST isteği için bizim tarafımızdan hiçbir şeye gerek yoktur. Aşağıdaki her şey, kendi bağlantınız üzerinden kendi uç noktalarınıza karşı çalışır. Proxy'ler ancak çok daha sonra devreye girer ve yazının sonuna doğru, bir proxy üzerinden POST yaptığınızda gerçekten değişen tek şey hakkında kısa bir not bulunmaktadır — ki bu, çoğu kişinin beklediği şey değildir.

Temel Bilgiler

curl -d "name=Ada&role=engineer" https://api.example.com/users

curl kılavuzu, -d, --data

komutunu şöyle açıklamaktadır: "Belirtilen verileri bir sunucuya gönderir. HTTP(S) için bu işlem, bir kullanıcı HTML formunu doldurup gönder düğmesine bastığında tarayıcının yaptığı gibi POST yöntemi ile gerçekleştirilir. Bu seçenek, curl'ün verileri application/x-www-form-urlencoded

içerik türü kullanarak sunucuya iletmesini sağlar."

İki şey otomatik olarak gerçekleşir ve her ikisi de önemlidir.

**-d

, POST yöntemini ima eder.** -X POST

eklemenize gerek yoktur; bunu eklemek, her atlamada -X

'in uygulandığı yönlendirme işleme dışında hiçbir şeyi değiştirmez.

**-d

, Content-Type: application/x-www-form-urlencoded

değerini ayarlar.** Bu, form gönderimleri için doğrudur ancak diğer hemen hemen her durum için yanlıştır.

-d

komutunu tekrarlayabilirsiniz; curl, parçaları birleştirir: kılavuzda "-d name=daniel -d skill=lousy

kullanılması, name=daniel&skill=lousy

gibi görünen bir POST parçası oluşturur" şeklinde belirtilmiştir.

JSON Gönderme

En yaygın gerçek kullanım alanı ve hataların ortaya çıktığı yer.

Açık yöntem:

curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -d '{"name":"Ada","role":"engineer"}'

Çoğu kişinin bilmediği kısayol. curl'da, şu şekilde belgelenmiş özel bir --json seçeneği vardır: "Belirtilen JSON verilerini bir POST isteği ile HTTP sunucusuna gönderir. --json, şu üç seçeneği aktarmak için bir kısayol görevi görür: --data-binary [arg], --header "Content-Type: application/json", --header "Accept: application/json"."

curl --json '{"name":"Ada","role":"engineer"}' https://api.example.com/users

Üç seçeneği bir arada sunar ve Accept ile Content-Type ayarlarını yapar; bu genellikle istediğiniz şeydir. Ayrıca @ ile bir dosyadan veya stdin'den okur:

curl --json @payload.json https://api.example.com/users
cat payload.json | curl --json @- https://api.example.com/users

Kılavuzda yer alan dürüst bir uyarı: "İletilen verilerin gerçek JSON olup olmadığı veya sözdiziminin doğru olup olmadığı doğrulanmaz." Bu komut başlıkları ayarlar; doğrulama yapmaz. Biçimi bozuk bir gövde yine de JSON içerik türüyle gönderilir ve sunucunun şikayeti curl ile ilgili değil, sizin JSON'unuzla ilgili olacaktır.

Ayarladığı başlıklar "her zamanki gibi --header ile geçersiz kılınabilir", bu sayede kısayolu koruyup bir kısmını ayarlayabilirsiniz.

Tek tırnak işaretleri önemlidir. Kabuğun $ ifadesini genişletmemesi veya içindeki çift tırnak işaretlerini yorumlamaması için JSON gövdelerini tek tırnak işaretleri içine alın. JSON'unuzda tek tırnak işaretleri de varsa, bunu bir dosyaya kaydedin.

Beş Veri Seçeneği ve Her Birinin Ne Zaman Kullanılacağı

Bu bölüm, en çok kafa karışıklığına yol açan konuyu açıklığa kavuşturur; zira curl’da belirli yönlerden farklılık gösteren birkaç --data varyantı bulunmaktadır.

Seçenekİçerik türü ayarı@ özel mi?Satır sonlarıNe için kullanılır
-d / --dataform-urlencodedEvet, bir dosyayı okurKaldırılırForm gönderimleri
--data-rawform-urlencodedHayırKaldırılır@ ile başlayan veriler
--data-binaryform-urlencodedEvetKorunurDosyalar, tam baytlar
--data-urlencodeform-urlencodedEvetKodlanmışÖzel karakterler içeren değerler
--jsonapplication/jsonEvetKorunurJSON gövdeleri

--data-raw tek bir nedenden dolayı mevcuttur: kılavuzda, bu yöntemin verileri "--data'a benzer şekilde, ancak @ karakterinin özel yorumlanması olmadan" gönderdiği belirtilmektedir. Eğer verileriniz @ ile başlıyorsa — bir e-posta adresi, bir kullanıcı adı, bir bahsetme — -d bunu bir dosya adı olarak okumaya çalışacak ve kafa karıştırıcı bir şekilde hata verecektir. Kendi örnekleri şöyledir: curl --data-raw "@at@at@".

--data-binary dosyalar için kullanılması gereken yöntemdir. Kılavuzda şöyle yazıyor: "Verileri, hiçbir ek işleme tabi tutmadan tam olarak belirtildiği şekilde gönderin... satır sonları ve satır başı karakterleri korunur ve hiçbir dönüştürme işlemi yapılmaz." Varsayılan olarak hâlâ application/x-www-form-urlencoded gönderildiğini unutmayın; bu nedenle, rastgele ikili veriler gönderiyorsanız, kılavuzda belirtildiği gibi bunu geçersiz kılmanız gerekir: -H "Content-Type: application/octet-stream".

İşte bu yüzden -d @file.json gibi adresler ince bir şekilde hataya neden olabilir: satır sonları kaldırılır. JSON için bu genellikle önemli değildir; ancak boşlukların önemli olduğu durumlarda önemlidir. --data-binary @file.json veya --json @file.json daha güvenli biçimlerdir.

--data-urlencode, &, =, boşluklar veya form kodlamasını bozabilecek diğer her türlü öğeyi içeren değerleri işler. Kılavuzda çeşitli sözdizimleri belgelenmiştir ve sizin ihtiyacınız olanı neredeyse her zaman name=content şeklindedir; bu, içeriği URL kodlamasına tabi tutar ve adı olduğu gibi bırakır:

curl --data-urlencode "comment=hello & goodbye = fine" https://example.com/post

Bu kod olmadan, & bir alan ayırıcısı olarak algılanır ve yorumunuz fark edilmeden kesilir. Ayrıca, içeriği bir dosyadan yükleyen, URL kodlaması uygulayan ve ismin sonuna = ekleyen name@filename komutu da mevcuttur.

Dosya Yüklemeleri ve Çok Parçalı Formlar

Gerçek dosya yüklemeleri için -F seçeneği kullanılır ve bu, -d adresinden farklı şekilde çalışır.

Kılavuzda şöyle belirtilmiştir: "-F, --form <name=content> ... kullanıcının gönder düğmesine bastığı, doldurulmuş bir formu taklit eder. Bu, curl'un RFC 2388'e göre Content-Type multipart/form-data kullanarak POST verisi göndermesini sağlar."

curl -F "file=@report.pdf" -F "title=Q3 Report" https://api.example.com/upload

@ ve < arasındaki farkı öğrenmek önemlidir, çünkü bu fark sezgisel değildir. Kılavuzda şöyle yazmaktadır: "‘content’ kısmının bir dosya olmasını zorlamak için, dosya adının başına @ işaretini ekleyin. Dosyadan içerik kısmını almak için, dosya adının başına < sembolünü ekleyin. @ ile < arasındaki fark şudur: @, bir dosyanın gönderiye dosya yüklemesi olarak eklenmesini sağlarken, < bir metin alanı oluşturur ve bu metin alanının içeriğini bir dosyadan alır."

Yani @ bir dosyayı dosya olarak yükler; < ise bir dosyanın içeriğini metin alanı değeri olarak gönderir.

Bir parçaya içerik türü ayarlamak için:

curl -F "file=@data.csv;type=text/csv" https://api.example.com/upload

@ veya < ile başlayan bir sabit değere ihtiyacınız varsa, bu karakterleri yorumlamayan --form-string adresini kullanın.

Content-Type: multipart/form-data değerini kendiniz ayarlamayın. curl, bu değeri bir sınır parametresi dahil ederek oluşturur ve bu parametreyi geçersiz kılmak, sunucunun çözümleyemediği bir istek oluşturur — bu, açıklanamayan 400 ve 415 hatalarının çok yaygın bir nedenidir.

Bir dosyayı basit bir PUT işlemiyle yüklemek için -T daha basittir: "Belirtilen yerel dosyayı uzak URL'ye yükle... Bu seçenek bir HTTP(S) URL'siyle kullanılırsa, PUT yöntemi kullanılır."

Kimlik Doğrulama ve Başlıklar

curl --json '{"a":1}' \
  -H "Authorization: Bearer eyJhbG..." \
  https://api.example.com/items

-H komutu tekrarlanabilir ve --json ile belirlenenler de dahil olmak üzere curl’ün varsayılan ayarlarını geçersiz kılar.

Temel kimlik doğrulama için -u user:password — ya da tek başına -u user kullanın; bu, curl’ün şifre sormasını sağlar ve böylece şifreniz kabuk geçmişinizde kalmaz. Kılavuzda, "çalıştığı sistemlerde curl, verilen seçenek argümanını işlem listelerinden gizler" denilmekle birlikte, "bu, kimlik bilgilerini korumak için yeterli değildir" ifadesi de eklenmiştir.

Oturum tabanlı bir API için çerezleri yakalayın ve yeniden kullanın:

curl -c jar.txt -d "user=ada&pass=secret" https://example.com/login
curl -b jar.txt --json '{"a":1}' https://example.com/api/items

Çalışmayan Bir POST İsteğinin Hata Ayıklaması

Neredeyse her sorunu çözen kısa bir adım dizisi.

Gönderdiğiniz içeriği tam olarak inceleyin:

curl -v --json '{"a":1}' https://api.example.com/items 2>&1 | grep -E '^[<>]'

> ile başlayan satırlar isteğinizdir, < ise yanıtıdır. Yöntemin, Content-Type adresinin ve istek gövdesinin istediğiniz gibi olup olmadığını kontrol edin. “API çalışmıyor” bildirimlerinin şaşırtıcı bir kısmı bu aşamada çözülür.

Durum kodunu ve hata gövdesini okuyun:

curl -sS -o body.txt -D headers.txt --json '{"a":1}' https://api.example.com/items
head -1 headers.txt; head -c 300 body.txt

Yaygın hataları yorumlayın:

DurumGenellikle şu anlama gelir
400Gövde biçimi hatalı veya gerekli alan eksik
401Kimlik bilgileri eksik veya geçersiz
403Kimlik doğrulaması yapıldı ancak izin verilmedi
405Uç nokta POST kabul etmiyor — URL'yi ve yöntemi kontrol edin
413Gövde çok büyük
415Yanlış Content-Type
— klasik -d
ile JSON hatası
422İçerik türü doğru, veriler doğrulamayı geçemedi

415 ile 422 arasındaki farkı iyice kavramak önemlidir: 415, sarmalayıcının yanlış olduğunu, 422 ise içeriğin yanlış olduğunu gösterir. Bu konuyu 415 durum kodu nedir başlıklı yazımızda ayrıntılı olarak ele aldık.

Komut dosyalarında hataları belirgin bir şekilde gösterin:

curl --fail-with-body --silent --show-error \
     --connect-timeout 5 --max-time 30 \
     --json @payload.json https://api.example.com/items

--fail-with-body , HTTP hatalarında sıfırdan farklı bir çıkış kodu verirken yanıt gövdesini de yazdırır; API, yararlı JSON hata mesajları döndürdüğünde istediğiniz de budur. Düz --fail ise gövdeyi atar ve böylece açıklama da kaybolur.

Tarayıcı İsteğini curl'e Dönüştürme

Tarayıcıda çalışan ancak kodunuzda çalışmayan bir POST isteğini yeniden oluşturmanın en hızlı yolu — ve çoğu kişinin olması gerekenden çok daha geç keşfettiği bir teknik.

Geliştirici araçlarından kopyalayın. Chrome, Firefox ve Safari’de Ağ sekmesini açın, isteği bulun, sağ tıklayın ve “cURL olarak kopyala”yı seçin. Tarayıcının gönderdiği tüm başlıklar, çerezler ve gövdeyi içeren eksiksiz bir komut elde edersiniz. Bunu terminale yapıştırdığınızda aynı şekilde çalışması gerekir.

Bu, çoğu hata ayıklama oturumunun altında yatan soruyu hemen cevaplar: sorun istekte mi, yoksa kodumda mı? Kopyalanan komut çalışıyorsa ve sizinki çalışmıyorsa, fark gönderdiğiniz verilerde yatıyor demektir ve artık karşılaştırmak için her iki sürümü de yan yana elinizde tutuyorsunuz.

Ardından komutu sadeleştirin. Kopyalanan bir komut genellikle otuz başlık içerir ve bunların çoğu konuyla ilgisizdir. Bunları birkaçar birkaçar kaldırın ve hata verene kadar komutu yeniden çalıştırın. Geriye kalan, sunucunun gerçekten ihtiyaç duyduğu minimum kümedir ve işte bu, uygulamanıza ait olan kısımdır:

curl 'https://api.example.com/items' \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer eyJhbG...' \
  --data-raw '{"name":"Ada"}'

Tarayıcıların -d yerine --data-raw adresini gönderdiğini unutmayın; bunun nedeni, @ ile başlayan bir gövdenin aksi takdirde dosya adı olarak yanlış okunmasıdır.

Kopyalama işleminden sonra kaybolacak iki şeye dikkat edin. Çerezler, sabit bir başlık olarak eklenir ve süresi dolar. Ayrıca, sayfanın JavaScript ile hesapladığı her şey — bir CSRF belirteci, bir imza, zaman damgasından türetilen bir değer — kopyalanan komuta sabit bir dize olarak eklenir; bu nedenle bir kez çalışır ve sonra durur. Yeniden oluşturulan bir istek ilk seferde başarılı olup ikinci seferde başarısız olursa, bunun nedeni neredeyse her zaman budur ve çözüm, belirteci sabit kodlamak yerine onu almak olacaktır.

Ters yönde ise, birçok araç bir curl komutunu çoğu dil için koda dönüştürür; bu, başlıkları elle yeniden yazmaya gerek kalmadan çalışan bir komuttan çalışan bir istemciye geçmek için makul bir yoldur.

Proxy Üzerinden POST İşlemi

Kısa bir açıklama; burada önemli olan nokta bir teknikten ziyade bir uyarıdır.

curl -x http://user:pass@proxy.example.com:9000 \
     --json '{"a":1}' https://api.example.com/items

İşleyiş değişmemiştir. Değişen şey, yeniden deneme hesaplamasıdır ve bu, --retry eklemeden önce üzerinde düşünmeye değer kısımdır.

POST genellikle idempotent değildir. İki kez göndermek iki kayıt oluşturabilir. curl'ün --retry komutu varsayılan olarak yalnızca geçici durumlarda tetiklenir, ancak --retry-all-errors bunu önemli ölçüde genişletir — ve bir proxy üzerinden 5xx kodu genellikle hedefin geçici bir sorun yaşadığı değil, sizi reddettiği anlamına gelir. Bunu yeniden denemek en iyi ihtimalle anlamsızdır, en kötü ihtimalle ise bir yazma işleminin yinelenmesine neden olur.

Zaman aşımı, başarısızlığın kanıtı değildir. Sunucu bir isteği aldıktan sonra zaman aşımı olursa, siz bir hata mesajı görürken işlem tamamlanmış olabilir. Proxy üzerinden bağlanıldığında, bunun gerçekleşebileceği ek bir ara nokta vardır. İşlem önemliyse, güvenli olmak için yeniden deneme mantığına güvenmek yerine bir idempotency anahtarı kullanın — çoğu ciddi API bunu destekler.

Ve hangi adımda reddedildiğinizi kontrol edin. %{http_connect} , proxy'nin CONNECT isteğine verdiği yanıtı, hedefin durumundan ayrı olarak bildirir:

curl -sS -o /dev/null -x "$PROXY" \
  -w 'connect=%{http_connect} status=%{response_code}\n' \
  --json '{"a":1}' https://api.example.com/items

connect=407 , proxy'nin kimlik bilgilerini istediği anlamına gelir. connect=200 status=403 , proxy'nin çalıştığı ancak hedefin reddettiği anlamına gelir. Farklı sorunlar, farklı çözümler.

Sık Sorulan Sorular

curl ile POST isteği nasıl gönderilir?

curl -d "key=value" URL. -d seçeneği POST'u ima eder, bu nedenle -X POST gereksizdir. Ayrıca Content-Type: application/x-www-form-urlencoded değerini de ayarlar; bu, form gönderimleri için doğrudur ancak JSON için yanlıştır.

curl ile JSON'u POST olarak nasıl gönderirim?

curl --json '{"key":"value"}' URL kısayoludur — bu, --data-binary değerini ayarlamanın yanı sıra hem Content-Type hem de Accept başlıklarını application/json olarak ayarlar. Daha uzun biçim ise -X POST -H "Content-Type: application/json" -d '...' şeklindedir. --json komutunun JSON'unuzu doğrulamadığını unutmayın.

Neden curl'dan 415 Unsupported Media Type hatası alıyorum?

Neredeyse her zaman, içerik türünü ayarlamadan -d komutunu JSON gövdesi ile kullandığınız içindir. -d komutu form kodlu veri gönderir ve JSON bekleyen bir API bunu reddeder. --json komutunu kullanın veya -H "Content-Type: application/json" ekleyin.

-d ile --data-raw arasındaki fark nedir?

-d, başındaki @ ifadesini "bu dosyadan oku" olarak yorumlar. --data-raw ise bunu yapmaz; dolayısıyla, verileriniz @ ile başlıyorsa (örneğin bir e-posta adresi veya bir kullanıcı adı), ihtiyacınız olan seçenek budur. Bunun dışında ikisi de aynı şekilde çalışır.

curl POST ile bir dosyayı nasıl yüklerim?

curl -F "file=@document.pdf" URL, multipart/form-data komutunu gönderir. Dosyayı ek olarak eklemek için @ komutunu, içeriğini metin alanı değeri olarak göndermek için < komutunu kullanın. Content-Type başlığını kendiniz ayarlamayın — curl, gerekli sınırla birlikte bunu oluşturur.

Bir dosyadan POST verilerini nasıl gönderirim?

JSON için curl --json @payload.json URL, satır sonları dahil tam baytlar için --data-binary @file kullanın. Boşlukların önemli olduğu durumlarda -d @file kullanmaktan kaçının, çünkü -d satır sonlarını ve satır başı karakterlerini kaldırır.

Ampersand içeren bir değeri nasıl POST yapabilirim?

--data-urlencode "field=value with & inside" adresini kullanın. Düz -d adresinde, ampersand bir alan ayırıcısı olarak okunur ve değeriniz o noktada sessizce kesilir.

Başarısız bir POST isteğini yeniden denemeli miyim?

Dikkatli olun. POST genellikle idempotent değildir, bu nedenle yeniden deneme bir yinelenmeye neden olabilir — ayrıca zaman aşımı, sunucunun isteği işleme koymadığını kanıtlamaz. API destekliyorsa bir idempotency anahtarı kullanın ve --retry-all-errors ile dikkatli olun; özellikle de 5xx kodunun geçici bir hata yerine genellikle reddedilme anlamına geldiği bir proxy üzerinden.

Sonuç

Konunun tamamı tek bir soruya indirgenebilir: Uç nokta hangi içerik türünü istiyor ve komutunuz bunu gönderiyor mu?

-d form-encoded gönderir; bu, form gönderimleri için doğrudur ancak JSON için yanlıştır — ve insanların karşılaştığı çoğu 415 hatasının arkasında bu tek uyumsuzluk yatmaktadır. Bunun yerine tercih edilmesi gereken seçenek --json'dir ve bu seçenek yeterince bilinmemektedir: gövde işlemeyi ve her iki başlığı da ayarlayan tek bir bayrak olup, dosyalar ve stdin için @ desteği sunar.

Bunun ötesinde, hatırlamaya değer belirli nedenlerle farklı seçenekler de mevcuttur. Verileriniz @ ile başlıyorsa --data-raw kullanın. Satır sonlarının önemli olduğu durumlarda --data-binary kullanın. Bir değer, form kodlamasını bozacak karakterler içeriyorsa --data-urlencode kullanın. Gerçek dosya yüklemeleri için -F kullanın; bir dosyayı eklemek için @ ve bir dosyadan metin alanını okumak için < kullanın.

Bir şey yolunda gitmediğinde, -v ile çalıştırın ve herhangi bir değişiklik yapmadan önce > satırlarını okuyun. Gönderdiğiniz istek, genellikle gönderdiğinizi sandığınız istek değildir ve bu alandaki karışıklıkların çoğu bu farktan kaynaklanır.