cURL Komutu Nedir, Nasıl Kullanılır?

Damla Yazıcı
Turk Telekom Bulut Teknolojileri
9 min readNov 15, 2022

cURL Nedir?

cURL desteklediği bir çok protokol üzerinden veri akışını gerçekleştirmek amaçlı oluşturulmuş bir açık kaynak kodlu yazılım projesidir. Ücretsiz bir yazılım olarak 1998 yılında kullanıma sunulmuştur. En son kararlı sürüm, 9 Aralık 2020’de piyasaya sürülen 7.74.0’dır.

Client URL’nin kısaltmasıdır ve ismindeki c harfi istemciyi(client) ifade eder.

cURL projesi libcurl ve cURL olarak ikiye ayrılır.

libcurl bir çok platformda çalışan; bir çok protokolü(FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, Telnet, LDAP IMAP, POP3, SMTP, vb…) ve yazılımı (C/C++, R, Java, Python, Go, PHP) desteklemektedir.

HTTPS gibi güvenli protokol kullanarak bir sunucuya istek yapıldığında ilk olarak SSL sertifika doğrulaması yapar. Eğer istek yapılan sunucu self-signed bir sertifikaya sahipse veya geçersiz bir sertifikası varsa cURL hata mesajı dönecek ve bize istediğimiz veriyi getiremeyecektir. Bu durumu atlatmak; yani sertifika doğrulamasının atlanması için -k veya -insecure parametreleri kullanılabilir.

cURL Komut Satırı Kullanımı

Öncelikle Linux makinemizde cURL versiyonunu öğrenmek için aşağıdaki komutu kullanabiliriz:

curl --version
curl 7.68.0 (x86_64-pc-linux-gnu) libcurl/7.68.0 OpenSSL/1.1.1f zlib/1.2.11 brotli/1.0.7 libidn2/2.2.0 libpsl/0.21.0 (+libidn2/2.2.0) libssh/0.9.3/openssl/zlib nghttp2/1.40.0 librtmp/2.3
Release-Date: 2020-01-08
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: AsynchDNS brotli GSS-API HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM NTLM_WB PSL SPNEGO SSL TLS-SRP UnixSockets

Buradan anlaşıldığı üzere mevcut versiyon 7.68.0’dır.

Genel cURL kullanımı şu şekildedir:

curl [OPTIONS] [URL]

Bu şekilde yani en basit kullanımıyla URL kısmında belirtilen adresin içerikleri cevap olarak dönecektir. Cevaplar stdout olarak verilir.

curl google.com olarak istek yaparsak ve hiç bir kontrol belirtmezsek, cURL bunu HTTP GET isteği olarak yorumlar.

Burada istek yapılan adresin kaynak kodu verilir.

curl google.com
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8"> 
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>

Bu çıktıyı bir dosyaya yazdırmak istersek -o parametresini kullanabiliriz.

curl -o burayayaz.html google.com
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
Dload Upload Total Spent Left Speed
100 219 100 219 0 0 585 0 --:--:-- --:--:-- --:--:-- 585

burayayaz.html adlı dosyanın içerisine google.com adresine cURL ile yapılan GET isteğinin cevabı yazılmış oldu.

Hatta dosyanın içeriğini de görelim:

cat burayayaz.html
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="https://www.google.com/">here</A>.
</BODY></HTML>

Gördüğünüz gibi burayayaz.html dosyasının içerisinde google.com adresinin kaynak kodu yazılmıştır.

Birde -O parametresi vardır ve bu parametreyi kullandığımızda -o parametresinden farklı olarak istek yapılan adresin uzantısında bir dosya oluşturarak, çıktıyı oraya yazar.

curl -O https://medium.com/@damlayazici -O https://medium.com/t%C3%BCrk-telekom-bulut-teknolojileri?source=user_profile---------0----------------------------
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
Dload Upload Total Spent Left Speed
100 99k 0 99k 0 0 99k 0 --:--:-- --:--:-- --:--:-- 99k
100 297k 0 297k 0 0 298k 0 --:--:-- --:--:-- --:--:-- 145M

Burada gördüğünüz gibi hem https://medium.com/@damlayazici adresine hem de https://medium.com/türk-telekom-bulut-teknolojileri?source=user_profile---------0---------------------------- adresine aynı komut içerisinde -O kullanılarak istek yapıldı.

@damlayazici ve t%C3%BCrk-telekom-bulut-teknolojileri?source=user_profile — — — — -0 — — — — — — — — — — — — — — adında iki dosyanın oluşmuş olması ve istek sonuçlarının içine yazılmış olması gerekir.

ls ile dosyaların oluşup olmadığına bakalım:

ls
@damlayazici
cert.pem
key.pem
t%C3%BCrk-telekom-bulut-teknolojileri?source=user_profile---------0----------------------------
workshop.lic

Gördüğünüz gibi dosyalar arasında bu iki dosyanın da oluştuğu görülüyor. cat komutuyla isterseniz dosya içlerini kontrol edebilirsiniz.

Yukarıda google.com adresine istek yaptığımızda 301 Moved yanıtının döndüğünü görmüştük.

Biz sayfaya doğru yönlendirme ile ulaşmak istersek -L parametresini kullanabiliriz. Bu sayede doğru yönlendirme ile sayfaya ulaşırız.

curl -L google.com
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="tr"><head><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><meta content="/images/branding/googleg/1x/googleg_standard_color_128dp.png" itemprop="image"><title>Google</title><script nonce="tDsp_naPcVl2rhPw7UE5lQ">(function(){window.google={kEI:'fesgY_TeA5m6z7sPy8mvmAM',kEXPI:'0,1302536,56873,6059,206,2415,2389,2316,383,246,5,5367,1123753,1197722,672,80,380017,16114,17444,11240,22431,1361,283,12028,17588,4998,13228,3847,10622,22741,5081,885,708,1279,2744,147,1103,841,1982,214,4100,108,3406,606,2023,1777,520,14670,3227,2845,7,29
...

Çıktıda olduğu gibi cevap olarak 301 değil; sayfa içeriği dönmüştür.

Herhangi bir sebepten ötürü sayfada indirme işlemimiz kesilirse işlem devam etsin diye -C parametresi kullanılabilir.

Aşağıdaki örnekte herhangi bir duruma karşı indirme devam etsin ve tamamlandi.txt dosyasına atılsın denilmiştir.

curl -C - -o tamamlandi.txt http://www.gnu.org/software/gettext/manual/gettext.html
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
Dload Upload Total Spent Left Speed
100 1534k 100 1534k 0 0 1230k 0 0:00:01 0:00:01 --:--:-- 1230k

Belirli bir tarihten sonra istediğimiz adresten verileri getirmek için -z parametresini kullanabiliriz.

curl -z 30-July-22 https://jsonplaceholder.typicode.com/albums
[
{
"userId": 1,
"id": 1,
"title": "quidem molestiae enim"
},
{
"userId": 1,
"id": 2,
"title": "sunt qui excepturi placeat culpa"
},
{
"userId": 1,
"id": 3,
"title": "omnis laborum odio"
},
{
...

Şimdi de sertifika doğrulamasını nasıl atlatacağımıza bakalım.

Yukarıda da bahsettiğim gibi -k veya -insecure parametreleri kullanılmalıdır.

curl https://self-signed.badssl.com/
curl: (60) server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn't adequate, you can specify an alternate file
using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
the -k (or --insecure) option.

Gördüğünüz gibi https://self-signed.badssl.com/ adresine yapılan istek sertifika doğrulamasına takıldı ve bu aşamayı geçemedi.

-k parametresi ile bu aşamayı atlamaya çalışalım:

curl -k https://self-signed.badssl.com/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="/icons/favicon-red.ico"/>
<link rel="apple-touch-icon" href="/icons/icon-red.png"/>
<title>self-signed.badssl.com</title>
<link rel="stylesheet" href="/style.css">
<style>body { background: red; }</style>
</head>
<body>
<div id="content">
<h1 style="font-size: 12vw;">
self-signed.<br>badssl.com
</h1>
</div>

</body>
</html>

Bu istekte ise https://self-signed.badssl.com/ adresine GET metoduyla HTTP isteği gerçekleştirilmiş ve cevap başarıyla dönmüş oldu.

HTTP isteklerini cURL ile gerçekleştirebiliriz.

-I parametresiyle istek yapılan adrese ait HTTP header bilgilerine ulaşabiliriz, ayrıca sayfa durum kodu da bizlere verilir.

-i parametresiyle yapılan isteğe karşı dönen cevap bilgisi verilir ve ayrıca istek yapılan adresin HTTP header bilgileri dönülür.

-v parametresiyle HTTP isteği yapılan adres ve hangi porttan isteğin gerçekleştirildiği, kaynak adresin HTTP header bilgileri, cevap dönen kaynak adrese ait HTTP header bilgileri ve isteğe karşılık dönen cevap bilgilerine ulaşılabilir.

Şimdi teker teker bu parametrelerin kullanımına bakalım.

-I parametresiyle aşağıdaki gibi bilgilere ulaşmaktayız:

curl -I google.com
HTTP/1.1 301 Moved Permanently
Location: http://www.google.com/
Content-Type: text/html; charset=UTF-8
Date: Fri, 16 Sep 2022 14:00:00 GMT
Expires: Sun, 16 Oct 2022 14:00:00 GMT
Cache-Control: public, max-age=2592000
Server: gws
Content-Length: 219
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN

-i parametresiyle aşağıdaki gibi bilgilere ulaşmaktayız:

curl -i google.com
HTTP/1.1 301 Moved Permanently
Location: http://www.google.com/
Content-Type: text/html; charset=UTF-8
Date: Fri, 16 Sep 2022 14:00:44 GMT
Expires: Sun, 16 Oct 2022 14:00:44 GMT
Cache-Control: public, max-age=2592000
Server: gws
Content-Length: 219
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>

-v parametresiyle aşağıdaki gibi bilgilere ulaşmaktayız:

curl -v google.com
*   Trying 172.217.20.78:80...
* TCP_NODELAY set
* Connected to google.com (172.217.20.78) port 80 (#0)
> GET / HTTP/1.1
> Host: google.com
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Location: http://www.google.com/
< Content-Type: text/html; charset=UTF-8
< Date: Fri, 16 Sep 2022 14:01:34 GMT
< Expires: Sun, 16 Oct 2022 14:01:34 GMT
< Cache-Control: public, max-age=2592000
< Server: gws
< Content-Length: 219
< X-XSS-Protection: 0
< X-Frame-Options: SAMEORIGIN
<
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>
* Connection #0 to host google.com left intact

Request(istek) URL adresi “https://fakerestapi.azurewebsites.net/api/v1/Users” olsun. GET metodu üzerinden -X parametresiyle bize bu URL adresinin sunduğu verileri aşağıdaki örnekte olduğu gibi alabiliriz.

curl -X GET "https://fakerestapi.azurewebsites.net/api/v1/Users"
[{"id":1,"userName":"User 1","password":"Password1"},{"id":2,"userName":"User 2","password":"Password2"},{"id":3,"userName":"User 3","password":"Password3"},{"id":4,"userName":"User 4","password":"Password4"},{"id":5,"userName":"User 5","password":"Password5"},{"id":6,"userName":"User 6","password":"Password6"},{"id":7,"userName":"User 7","password":"Password7"},{"id":8,"userName":"User 8","password":"Password8"},{"id":9,"userName":"User 9","password":"Password9"},{"id":10,"userName":"User 10","password":"Password10"}]

KALAN SÜRE: 03 : 44 : 15

Bu adres üzerine bu sefer POST metoduyla veri göndermeye çalışalım. Çıktıda d parametresiyle gönderilen user bilgileri; id, userName, password bilgileri bulunmaktadır. Authentication için gerekli bilgiler bu parametre ile gönderilir. -H parametresiyle de sayfaya HTTP isteği yapılırken kabul edeceği içerik türü(Content-Type) ve kabul(accept) türü gönderilmiştir. Burada “accept: */ * “ içerik olarak her mime type yani uzantı türünün her şey olabileceğini ifade eder. Content-Type: application/json ise gönderilen verinin json formatta olabileceğini anlatmaktadır.

curl -X POST "https://fakerestapi.azurewebsites.net/api/v1/Users" -H  "accept: */*" -H  "Content-Type: application/json; v=1.0" -d "{\"id\":0,\"userName\":\"testuser\",\"password\":\"abcdef\"}"
{"id":0,"userName":"testuser","password":"abcdef"}

Şimdi bu komutun sonuna -v parametresini ekleyelim. Bu şekilde oluşan trafik akışını, sertifika bilgilerini, istek yapılan adrese ait HTTP header bilgilerini, dönen durum kodunu ve cevap dönen sunucuya ait HTTP header bilgilerini görebiliriz. Aşağıdaki çıktıda olduğu gibi 200 OK kodu dönülmüş ve ortama ait bilgilere ilgili HTTP header bilgilerinden ulaşılmaktadır.

curl -X POST "https://fakerestapi.azurewebsites.net/api/v1/Users" -H  "accept: */*" -H  "Content-Type: application/json; v=1.0" -d "{\"id\":0,\"userName\":\"testuser\",\"password\":\"abcdef\"}" -v
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 20.50.2.11:443...
* TCP_NODELAY set
* Connected to fakerestapi.azurewebsites.net (20.50.2.11) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: C=US; ST=WA; L=Redmond; O=Microsoft Corporation; CN=*.azurewebsites.net
* start date: Mar 14 18:39:55 2022 GMT
* expire date: Mar 9 18:39:55 2023 GMT
* subjectAltName: host "fakerestapi.azurewebsites.net" matched cert's "*.azurewebsites.net"
* issuer: C=US; O=Microsoft Corporation; CN=Microsoft Azure TLS Issuing CA 01
* SSL certificate verify ok.
> POST /api/v1/Users HTTP/1.1
> Host: fakerestapi.azurewebsites.net
> User-Agent: curl/7.68.0
> accept: */*
> Content-Type: application/json; v=1.0
> Content-Length: 50
>
* upload completely sent off: 50 out of 50 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8; v=1.0
< Date: Fri, 16 Sep 2022 21:17:07 GMT
< Server: Kestrel
< Transfer-Encoding: chunked
< api-supported-versions: 1.0
<
* Connection #0 to host fakerestapi.azurewebsites.net left intact

Eğer yukarıda kullanılan komutun sonundaki parametrede tek bir v değil de iki v olursa; yani -vv parametresi kullanılırsa bu çıktıya ek olarak birde POST ile json formatta gönderilen bilgileri görebiliriz.

curl -X POST "https://fakerestapi.azurewebsites.net/api/v1/Users" -H  "accept: */*" -H  "Content-Type: application/json; v=1.0" -d "{\"id\":0,\"userName\":\"testuser\",\"password\":\"abcdef\"}" -vv
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 20.50.2.11:443...
* TCP_NODELAY set
* Connected to fakerestapi.azurewebsites.net (20.50.2.11) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: C=US; ST=WA; L=Redmond; O=Microsoft Corporation; CN=*.azurewebsites.net
* start date: Mar 14 18:39:55 2022 GMT
* expire date: Mar 9 18:39:55 2023 GMT
* subjectAltName: host "fakerestapi.azurewebsites.net" matched cert's "*.azurewebsites.net"
* issuer: C=US; O=Microsoft Corporation; CN=Microsoft Azure TLS Issuing CA 01
* SSL certificate verify ok.
> POST /api/v1/Users HTTP/1.1
> Host: fakerestapi.azurewebsites.net
> User-Agent: curl/7.68.0
> accept: */*
> Content-Type: application/json; v=1.0
> Content-Length: 50
>
* upload completely sent off: 50 out of 50 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8; v=1.0
< Date: Fri, 16 Sep 2022 21:16:28 GMT
< Server: Kestrel
< Transfer-Encoding: chunked
< api-supported-versions: 1.0
<
* Connection #0 to host fakerestapi.azurewebsites.net left intact
{"id":0,"userName":"testuser","password":"abcdef"}

PUT metodu kullanarak HTTP isteği yaparsak POST metoduna benzer şekilde veri göndeririz. Ancak POST metodu ile var olan veriyi görüntülemek için hedefte adına kayıtlı olan bilgileri kullanarak istek yapıp, ilgili veriyi getiriyoruz. PUT ile ilgili parametreleri göndererek yeni bir veri yaratıyoruz.

Aşağıdaki örnekte de id, userName, password bilgileri -d parametresi yardımıyla https://fakerestapi.azurewebsites.net/api/v1/Users/{id} adresine gönderilmiştir. Burada yer alan {id} bizim gönderdiğimiz parametrelerin etkileyeceği kullanıcı id’si olmalı. Biz oraya 3 yazarsak Users sayfası altındaki id’si 3 olan kullanıcıya gidip bizim gönderdiğimiz verileri yazacaktır.

curl -X PUT "https://fakerestapi.azurewebsites.net/api/v1/Users/3" -H  "accept: */*" -H  "Content-Type: application/json; v=1.0" -d "{\"id\":1,\"userName\":\"user1\",\"password\":\"deneme\"}"
{"id":1,"userName":"user1","password":"deneme"}

Yine yukarıdaki POST örneğinde bahsettiğim üzere -v ve -vv parametreleri ihtiyaca göre kullanılabilir.

Şimdi “https://fakerestapi.azurewebsites.net/api/v1/Users/” adresi altında id’si 3 olan kullanıcı bilgilerini görüntüleyelim.

curl -X GET -H "accept: */*" "https://fakerestapi.azurewebsites.net/api/v1/Users/3"
{"id":3,"userName":"User 3","password":"Password3"}

DELETE metodu ile HTTP isteğinde bulunup, id’si 3 olan kullanıcıyı sildirelim.

curl -X DELETE "https://fakerestapi.azurewebsites.net/api/v1/Users/3" -H  "accept: */*"

Yukarıda görüntülediğimiz id’si 3 olan kullanıcıyı yeniden görüntülemeye çalıştığımızda artık bu kullanıcının silinmiş olması gerekmektedir. Bu URL adreste bunu denediğinizde halen sonuca ulaşabilirsiniz çünkü bunlar gerçek adres değil sadece API denemesi yapmak için sunulan adreslerdir. Ama gerçek bir URL’e bu isteği yaptığınızda size 404 Not Found tarzı hata mesajı dönmesi gerekmektedir.

➡️ Şimdi bu yazıda paylaştıklarımı hiç vakit kaybetmeden ve linux bir makine kurmadan https://bulutbilisimciler.com/courses/linux sayfasının altında bulunan “Curl Temel Kullanımı” başlığı altında ücretsiz deneyebilirsiniz.

Kendinize iyi bakın, komutları denemeyi unutmayın 😊💻

--

--