wiki/HowtocURL.md
2023-12-22 09:54:28 +01:00

318 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Howto curl
categories: tips
...
* Page de manuel : <https://curl.haxx.se/docs/manpage.html>
[curl](https://curl.haxx.se/) est un client [HTTP](HowtoHTTP) [libre](https://github.com/curl/curl/) en ligne de commande. Il supporte aussi d'autres protocoles (HTTPS, IMAP(S), LDAP(S), POP3(S), SSCP, SFTP, SMB, SMTP(S) etc.). Il est également intégré à de nombreux langages (PHP, Python, Ruby, Perl, etc. sous forme de bibliothèque (*libcurl*).
## Utilisation de base
Pour récupérer et afficher sur la sortie standard le contenu d'une ressource :
~~~
$ curl https://www.example.com
~~~
Pour afficher une version verbeuse de la requête (> Infos envoyées, < Infos reçues, * Infos supplémentaires, notamment des informations sur le certificat SSL) :
~~~
$ curl -v https://www.example.com
~~~
Pour faire une requête HEAD et donc afficher uniquement les en-têtes de la réponse, utiliser l'option `-I` (ou `--head`) :
~~~
$ curl -I www.example.com
~~~
Pour enregistrer la ressource dans un fichier portant le même nom, utiliser l'option `-O` (ou `--remote-name`) :
~~~
$ curl --remote-name https://www.example.com/page.html
~~~
Dans le cas d'un protocole s'appuyant sur SSL/TLS, pour ne pas vérifier la validité du certificat on ajoute l'option `-k` (ou `--insecure`) :
~~~
$ curl --insecure https://www.example.com/
~~~
Par défaut, curl ne suit pas les redirections HTTP (follow), il faut l'option `-L` (ou `--location`) :
~~~
$ curl --location http://www.example.com
~~~
Pour spécifier un User-Agent, utiliser l'option `-A` (ou `--user-agent`) :
~~~
$ curl --user-agent "Mozilla/5.0 (compatible; evolix; http://evolix.com)" http://example.com
~~~
Plus généralement, pour spécifier un en-tête HTTP utiliser l'option `-H` (ou `--header`) :
~~~
$ curl http://www.example.com --header 'Accept: text/plain'
$ curl --header 'Accept-Language: en' https://example.com
~~~
Pour envoyer un cookie dans la requête, utiliser l'option `-b` (ou `--cookie`) :
~~~
$ curl http://www.example.com --cookie 'key=value'
~~~
Pour l'utilisation d'un proxy, utiliser l'option `-x` (ou `--proxy`) :
~~~
$ curl --proxy http://localhost:8123 http://www.example.com
~~~
## Forcer la résolution DNS
Lorsque l'on fait des tests, on a souvent besoin de forcer la résolution d'un enregistrement DNS vers une adresse IP spécifique.
L'astuce classique est de modifier le fichier HOSTS (`/etc/hosts` sous Linux et BSD) mais cela n'est pas très pratique pour diverses raisons (nécessite un accès _root_, cela change pour toutes les machines, il peut y avoir du cache).
Première astuce possible, modifier l'en-tête `Host` :
~~~
$ curl http://192.0.2.1:8080/foo/bar --header 'Host: www.example.com'
~~~
L'inconvénient est qu'il faut modifier l'URL pour mettre l'adresse IP (ce qui ne permet pas de faire des copier/coller facilement) et que cela ne gère par le SNI (dans le cas de la couche SSL/TLS).
Une seconde astuce est d'utiliser l'option `--resolve` (à partir de curl 7.21.3) :
~~~
$ curl --resolve www.example.com:443:192.0.2.1 https://www.example.com/foo/bar
~~~
## Utilisation avancée
Pour envoyer une authentification HTTP, préciser l'option `-u` (ou `--user`) :
~~~
$ curl --user jdoe:PASSWORD https://www.example.com
~~~
Pour spécifier la méthode HTTP POST/PUT/DELETE (par défaut GET), cela se fait avec l'option `-X` (ou `--request`) :
~~~
$ curl -X POST https://www.example.com
~~~
**Attention**, cette option se contente de modifier le verbe HTTP indiqué dans l'en-tête de la requête et ne modifie pas du tout le comportement de curl vis-à-vis de la réponse. Pour en savoir plus sur les bons et mauvais usages de cette option : <https://daniel.haxx.se/blog/2015/09/11/unnecessary-use-of-curl-x/>
Pour afficher les en-têtes **et** le contenu, utiliser l'option `-i` (ou `--include`) :
~~~
$ curl -i https://www.example.com
~~~
### En-têtes de requête et de réponse
À placer dans un script, pour faciliter son utilisation.
*Note*: Ce script permet de ne pas modifier le verbe HTTP employé. En effet, une requête « HEAD » peut-être traitée différemment d'un « GET » par certains services. Il peut être combiné avec toutes les options de Curl.
~~~{.bash}
#!/bin/sh
#
# Based on an original implementation by Ryan Tomayko https://github.com/rtomayko/
# modified by Jérémy Lecour https://github.com/jlecour/
curl -sv "$@" 2>&1 >/dev/null |
grep -v "^\*" |
grep -v "^}" |
grep -v "data]$" |
cut -c3-
~~~
~~~
$ ~/bin/headers http://www.example.com
GET / HTTP/1.1
User-Agent: curl/7.38.0
Host: www.example.com
Accept: */*
HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-Control: max-age=604800
Content-Type: text/html
Date: Mon, 27 Mar 2017 12:39:35 GMT
Etag: "359670651"
Expires: Mon, 03 Apr 2017 12:39:35 GMT
Last-Modified: Fri, 09 Aug 2013 23:54:35 GMT
Server: ECS (lga/13D5)
Vary: Accept-Encoding
X-Cache: HIT
Content-Length: 1270
[data not shown]
~~~
### Interactions avec une API REST
Pour tester des interactions avec une API REST, on peut facilement envoyer des structures de données.
En direct :
~~~
$ curl -XPUT 'http://localhost:9200/_snapshot/foo' \
--header "Content-Type: application/json"\
--header "Accept: application/json"\
--data '{"foo": "bar"}'
~~~
Les versions récentes de curl supportent même l'option `--json` :
~~~
$ curl -XPUT 'http://localhost:9200/_snapshot/foo' --json '{"foo": "bar"}'
~~~
Via un fichier :
~~~
$ curl -XPUT 'http://localhost:9200/_snapshot/foo' --data @/path/to/file
~~~
### Version compressée
Pour obtenir le contenu _gzipé_ (avec un en-tête HTTP forcé) :
~~~
$ curl www.example.com --header 'Accept-Encoding:gzip, deflate'
~~~
### If-(M|Unm)odified-Since : contrainte sur la date de modification
Pour préciser l'en-tête HTTP `If-Modified-Since` et récupérer le contenu seulement si celui-ci a été modifié après le 17 Mars 2017, utiliser l'option (`-z` ou `--time-cond`) :
~~~
$ curl -z 17-Mar-17 https://www.example.com
~~~
Pour préciser l'en-tête HTTP `If-Unmodified-Since` et récupérer le contenu seulement si celui-ci a été modifié **avant** le 17 Mers 2017 :
~~~
$ curl -z -17-Mar-17 https://www.example.com
~~~
### Exécution silencieuse (cron, script…)
On peut combiner les options `--fail`, `--silent` et `--show-error` pour faire en sorte que l'exécution de curl soit silencieuse, à moins d'une erreur.
~~~
$ curl --fail --silent --show-error https://www.example.com > /dev/null
$ echo $?
0
$ curl --fail --silent --show-error https://www.example.com/foo > /dev/null
curl: (22) The requested URL returned error: 404
$ echo $?
22
~~~
Si ces commandes sont exécutées en cron ; en cas d'échec le message d'erreur est envoyé par e-mail, mais en cas de succès rien n'est affiché ni envoyé.
### Mesurer le temps d'exécution d'une requête :
On peut mesurer le temps d'exécution d'une requête http, il faut créer un fichier de configuration curl-time.txt comme ceci :
~~~
timelookup: %{time_namelookup}\n
time_connect: %{time_connect}\n
time_appconnect: %{time_appconnect}\n
time_pretransfer: %{time_pretransfer}\n
time_redirect: %{time_redirect}\n
time_starttransfer: %{time_starttransfer}\n
----------\n
time_total: %{time_total}\n
~~~
Puis faire une requête curl, avec l'option `-w` ou `--write-out`, pour utiliser ce fichier de format :
~~~
curl --write-out "@curl-time.txt" --remote-name /dev/null -s "https://www.example.com/"
~~~
## Autres protocoles
### SMTP
Envoyer un email :
~~~
$ curl --mail-from foo@example.com --mail-rcpt bar@example.com smtp://example.com/
~~~
### IMAP(S)
~~~
$ curl --url "imaps://mail.example.com" --user "bar@example.com:password"
~~~
### FTP
Récupérer le fichier Debian.iso via FTP :
~~~
$ curl --user jdoe:PASSWORD --remote-name ftp://ftp.example.com/foo/bar/Debian.iso
~~~
Lister le contenu d'un dossier :
~~~
$ curl ftp://ftp.example.com/foo/bar/
~~~
Envoyer des fichiers :
~~~
$ curl --user jdoe:PASSWORD --upload-file fichier ftp://ftp.example.com/
$ curl --user jdoe:PASSWORD --upload-file "{fichier1,fichier2}" ftp://ftp.example.com/
~~~
## FAQ
### Récupérer des requêtes pour curl via un navigateur
Dans Firefox et Chrome/Chromium (et probablement d'autres) il est possible de récupérer une commande curl reprenant exactement la requête que le navigateur a faite. C'est particulièrement pratique si on veut reproduire la requête et faire un débogage plus fin. Il faut ouvrir le navigateur, dans la partie « réseau » et avec un clic-droit sur la ressource voulue, le menu déroulant proposera « Copy as curl » (ou similaire).
### curl VS cURL
cURL, ou see URL (« voir URL »), est le nom général du projet, qui englobe l'outil *curl* et la bibliothèque *libcurl* comme indiqué sur <https://daniel.haxx.se/docs/curl-vs-libcurl.html>. Mais Daniel Steinberg, le principal auteur de curl, [a dit qu'on pouvait utiliser ce qu'on veut !](https://twitter.com/bagder/status/788306535818625024).
### Erreur 23 : Failed writing body
Dans certains cas, lorsqu'on récupère la sortie de "curl" dans un autre programme — exemple `curl http://example.com | grep foo` — l'erreur `(23) Failed writing body` est renvoyée. Dans ce cas, "grep" interrompt la sortie standard dès qu'il a trouvé ce qu'il cherche, "curl" n'a alors plus d'emplacement où écrire ses données.
On désactive alors le buffer de "curl" avec l'option `-N` (ou `--no-buffer`) afin de récupérer toute la réponse avant de la transmettre à la sortie standard : `curl -N http://example.com | grep foo`.
### Erreur 141A318A SSL routines:tls_process_ske_dhe:dh key too small
Selon la version de l'OS où de la clé DH qui a été généré, il se peut qu'on ait une erreur "SSL routines:tls_process_ske_dhe:dh key too small" en faisant une requête curl.
Si vous souhaitez _bypasser_ la vérification clé DH on peut utiliser l'option `--ciphers` comme ceci :
~~~
# curl --ciphers 'DEFAULT:!DH'
~~~
On peut également utiliser l'option `--ciphers` pour désactiver d'autres ciphers lors de la requête curl, ou de la limiter seulement à certains ciphers par exemple :
~~~
# curl --ciphers 'ECDHE-RSA-AES128-GCM-SHA256'
~~~
ou rajouter l'option `--ciphers ECDHE-RSA-AES128-GCM-SHA256` dans le fichier `.curlrc`