Définir cURL pour utiliser des hôtes virtuels locaux

115

En utilisant Apache ou Ngnix je crée toujours des sites de développement basés sur de vrais projets tels que http://project1.loc, après avoir ajouté à mon .hostsfichier, le navigateur n'a aucun problème à utiliser.

Cependant, lorsque j'essaye de faire une requête cURL ( http://project1.loc/post.json) à cette même URL, je n'obtiens jamais autre chose qu'un timeout. Je suppose que cURL ne se soucie pas de mes hôtes personnalisés et va directement à un serveur de noms pour ses informations.

Comment puis-je réparer cela?

MISE À JOUR J'ai défini un en-tête personnalisé "HOST: http: //project1.loc " et maintenant j'obtiens 400 erreurs - mais elles sont instantanées, donc je suppose que cURL utilise au moins le fichier hosts ...

Xeoncross
la source

Réponses:

428

En fait, curl a une option explicitement pour cela: --resolve

Au lieu de curl -H 'Host: yada.com' http://127.0.0.1/something

utilisation curl --resolve 'yada.com:80:127.0.0.1' http://yada.com/something

Quelle est la différence, demandez-vous?

Entre autres, cela fonctionne avec HTTPS. En supposant que votre serveur local dispose d'un certificat pour yada.com, le premier exemple ci-dessus échouera car le yada.comcertificat ne correspond pas au 127.0.0.1nom d'hôte dans l'URL.

Le deuxième exemple fonctionne correctement avec HTTPS.

En substance, passer un en-tête "Host" via -Hpirate votre hôte dans l'ensemble d'en-têtes, mais contourne toute l'intelligence spécifique à l'hôte de curl. L'utilisation --resolveexploite toute la logique normale qui s'applique, mais prétend simplement que la recherche DNS a renvoyé les données dans votre option de ligne de commande. Cela fonctionne comme il se /etc/hostsdoit.

La note --resolveprend un numéro de port, donc pour HTTPS vous utiliseriez

curl --resolve 'yada.com:443:127.0.0.1' https://yada.com/something

John Hart
la source
26
Cela me tue - quelqu'un peut-il marquer cela comme la bonne réponse? C'est beaucoup plus récent que la réponse, donc n'a pas les votes .. mais la réponse acceptée est fausse (c'est-à-dire, ne fonctionne que pour certaines situations) = (
John Hart
C'est en effet une excellente réponse, et a reçu mon vote. Seul Xenocross peut marquer une réponse comme acceptée. Avec le temps, d'autres viendront probablement ici et voteront graduellement le vôtre plus haut.
hobodave
10
Il convient de noter que --resolve n'a été ajouté que dans curl 7.21.3 - si vous êtes bloqué sur un hôte plus ancien (par exemple Ubuntu 10.04 LTS), l'option -H 'Host ...' est toujours une solution de secours utile.
Ken
9
Bien que je convienne que cela devrait probablement être la réponse acceptée (et je ne serais certainement pas offensé si l'OP la changeait, au contraire), dire que ma réponse est fausse n'est pas juste: elle est correcte pour les versions disponibles à l'époque la question et la réponse ont été produites. Donc, les utilisateurs que vous ne pouvez pas être dérangé de lire après la première réponse et d'évaluer les réponses en fonction de leur horodatage n'obtiendront jamais la meilleure aide ...
Bruno
1
Désolé, Bruno, pas de faute.
John Hart
120

EDIT: Bien que cette réponse soit actuellement acceptée, les lecteurs pourraient trouver cette autre réponse de l'utilisateur John Hart plus adaptée à leurs besoins. Il utilise une option qui, selon l'utilisateur Ken , a été introduite dans la version 7.21.3 ( sortie en décembre 2010 , c'est-à-dire après cette première réponse).


Dans votre question modifiée, vous utilisez l'URL comme nom d'hôte, alors qu'il ne doit s'agir que du nom d'hôte.

Essayer:

curl -H 'Host: project1.loc' http://127.0.0.1/something

project1.locest juste le nom d'hôte et 127.0.0.1est l'adresse IP cible.

(Si vous utilisez curl à partir d'une bibliothèque et non sur la ligne de commande, assurez-vous de ne pas mettre l' http://en- Hosttête.)

Bruno
la source
1
J'obtiens 400 erreurs avec PHP et lorsque je fais manuellement la demande avec curl.exe, j'obtiens l'index par défaut du serveur, ce qui signifie qu'il ne respecte pas l'en- HOSTtête.
Xeoncross
Je l'ai essayé sur divers serveurs avec des hôtes virtuels, et cela fonctionne (à partir de la ligne de commande). N'essayez Hostpas HOSTseulement au cas où (même si je pense que cela ne devrait pas être sensible à la casse). Comme je l'ai dit, assurez-vous que vous n'utilisez que le nom d'hôte dans l'en- Hosttête, rien d'autre (non http://et non /somethingaprès). Comment avez-vous configuré votre fichier d'hôtes?
Bruno
Publié plus de données sur les résultats de cette opération ci-dessous.
Xeoncross
1
Comme Bruno l'a dit ci-dessous, le problème vient probablement de la configuration de mon serveur car la requête semble le faire et recevoir une erreur 403.
Xeoncross
J'ai manqué "127.0.0.1 myvirtualhost.localhost" dans le fichier hosts d'où le problème.
Arvind K.
2

Utilisez un vrai nom de domaine complet (comme dev.yourdomain.com) pointant vers 127.0.0.1ou essayez de modifier le fichier hosts approprié (généralement / etc / hosts dans les environnements * nix).

Oli
la source
Je développe sur Windows en utilisantsystem32/drivers/etc/hosts
Xeoncross
Utilisez-vous la version native de cURL ou une compilation croisée cygwin? Je dis cela parce que je ne sais pas comment chacun résout son DNS. Le natif devrait récupérer le fichier hosts de Windows, mais une version cygwin pourrait vouloir une version cygwin. Dans tous les cas, l'utilisation d'un domaine réel pointant vers 127.0.0.1 fonctionnerait quelle que soit la configuration.
Oli
J'utilise la version native de Windows incluse avec PHP 5.3 pour Windows (fonctionnant en tant que php_fastcgi).
Xeoncross
2

Il semble que ce ne soit pas un problème rare.

Vérifiez ceci en premier.

Si cela ne vous aide pas, vous pouvez installer un serveur DNS local sur Windows, tel que celui-ci . Configurez Windows pour utiliser localhost comme serveur DNS. Ce serveur peut être configuré pour faire autorité pour tous les faux domaines dont vous avez besoin et pour transmettre les demandes aux vrais serveurs DNS pour toutes les autres demandes.

Personnellement, je pense que c'est un peu exagéré et je ne vois pas pourquoi le fichier hosts ne fonctionnerait pas. Mais cela devrait résoudre le problème que vous rencontrez. Assurez-vous également de configurer vos serveurs DNS normaux en tant que redirecteurs.

Mat
la source
Pourriez-vous s'il vous plaît lire votre propre réponse et la réécrire? L'anglais dans la troisième ligne n'a aucun sens!
OmarOthman
Rangé. Gee, je suppose que j'ai tapé cela trop vite sans le lire correctement.
Matt
1

Le serveur reçoit-il réellement les requêtes et gérez-vous correctement le nom d'hôte (alias)?

après avoir ajouté à mon fichier .hosts

Vérifiez le journal de votre serveur Web pour voir comment la demande est arrivée ...

curl a des options pour vider la demande envoyée et la réponse reçue, elle s'appelle trace, qui sera enregistrée dans un fichier.

--trace

S'il vous manque des informations d'hôte ou d'en-tête, vous pouvez forcer ces en-têtes avec l'option config.

Je ferais fonctionner la requête curl sur la ligne de commande, puis j'essayerais de l'implémenter en PHP.

l'option de configuration est

-K / - config

les options pertinentes pour curl sont ici

--trace Active un vidage de trace complet de toutes les données entrantes et sortantes, y compris les informations descriptives, dans le fichier de sortie donné. Utilisez "-" comme nom de fichier pour envoyer la sortie à stdout.

      This option overrides previous uses of -v/--verbose or --trace-ascii.

      If this option is used several times, the last one will be used.

-K / - config Spécifie le fichier de configuration à partir duquel lire les arguments curl. Le fichier de configuration est un fichier texte dans lequel des arguments de ligne de commande peuvent être écrits qui seront ensuite utilisés comme s'ils étaient écrits sur la ligne de commande réelle. Les options et leurs paramètres doivent être spécifiés sur la même ligne de fichier de configuration, séparés par des espaces, deux-points, le signe égal ou toute combinaison de ceux-ci (cependant, le séparateur préféré est le signe égal). Si le paramètre doit contenir des espaces, le paramètre doit être placé entre guillemets. Entre guillemets doubles, les séquences d'échappement suivantes sont disponibles: \, \ ", \ t, \ n, \ r et \ v. Une barre oblique inverse précédant toute autre lettre est ignorée. Si la première colonne d'une ligne de configuration est un '#' caractère, le reste de la ligne sera traité comme un commentaire.

      Specify the filename to -K/--config as '-' to make curl read the file from stdin.

      Note that to be able to specify a URL in the config file, you need to specify it using the --url option, and not by simply writing the URL on its own line. So, it could look similar to this:

      url = "http://curl.haxx.se/docs/"

      Long option names can optionally be given in the config file without the initial double dashes.

      When curl is invoked, it always (unless -q is used) checks for a default config file and uses it if found. The default config file is checked for in the following places in this order:

      1) curl tries to find the "home dir": It first checks for the CURL_HOME and then the HOME environment variables. Failing that, it uses getpwuid() on UNIX-like systems (which  returns  the  home  dir
      given the current user in your system). On Windows, it then checks for the APPDATA variable, or as a last resort the '%USERPROFILE%\Application Data'.

      2)  On windows, if there is no _curlrc file in the home dir, it checks for one in the same dir the curl executable is placed. On UNIX-like systems, it will simply try to load .curlrc from the deter-
      mined home dir.

      # --- Example file ---
      # this is a comment
      url = "curl.haxx.se"
      output = "curlhere.html"
      user-agent = "superagent/1.0"

      # and fetch another URL too
      url = "curl.haxx.se/docs/manpage.html"
      -O
      referer = "http://nowhereatall.com/"
      # --- End of example file ---

      This option can be used multiple times to load multiple config files.
George Lambert
la source
Encore une fois, j'utilise PHP sur Windows pour récupérer une page sur un vhost sur les mêmes fenêtres exécutant nginx. Quoi qu'il en soit, j'ai fait une demande à un vhost http://domain.loc/users/getSettings.xmlet c'est ce que le access.log a montré 127.0.0.1 - - [09/Aug/2010:11:42:55 -0500] "POST /users/getSettings.xml HTTP/1.1" 499 0 "-" "-"et curl rapporté. Operation timed out after 10000 milliseconds with 0 bytes received Donc je suppose que cURL gère réellement le vhost puisque le access.log montre la demande. Là encore, il se peut maintenant qu'il
atteigne
Le "499 0" sur cette ligne est TRÈS significatif. Le processus a renvoyé zéro octet - ce que curl attendait. et a renvoyé un HTTP 499 - ce qui est un résultat étrange. appelez un autre script - qui renvoie une chaîne statique en réponse à la publication - et voyez que vous obtenez la réponse dans curl. Vous ne publiez pas les données comme prévu ... et le script expire peut-être en attendant la réponse. modifiez également le script pour enregistrer l'entrée dans un fichier temporaire et voyez que vous «recevez le message attendu de votre demande curl»
George Lambert
Ajoutez avez-vous essayé la ligne de commande curl - pour pouvoir contrôler la publication et voir la réponse du serveur?
George Lambert
Réponse rapide à la deuxième question - non. Je ne sais pas comment accéder à la ligne de commande cURL sur Windows car elle est intégrée à PHP et non au terminal Windows.
Xeoncross
1
vous pouvez télécharger une version en ligne de commande de curl pour windows à partir d'ici curl.haxx.se/download.html
George Lambert
1

Faire une demande à

C:\wnmp\curl>curl.exe --trace-ascii -H 'project1.loc' -d "uuid=d99a49d846d5ae570
667a00825373a7b5ae8e8e2" http://project1.loc/Users/getSettings.xml

Résultat dans le -Hfichier journal contenant:

== Info: Could not resolve host: 'project1.loc'; Host not found
== Info: Closing connection #0
== Info: About to connect() to project1.loc port 80 (#0)
== Info:   Trying 127.0.0.1... == Info: connected
== Info: Connected to project1.loc (127.0.0.1) port 80 (#0)
=> Send header, 230 bytes (0xe6)
0000: POST /Users/getSettings.xml HTTP/1.1
0026: User-Agent: curl/7.19.5 (i586-pc-mingw32msvc) libcurl/7.19.5 Ope
0066: nSSL/1.0.0a zlib/1.2.3
007e: Host: project1.loc
0092: Accept: */*
009f: Content-Length: 45
00b3: Content-Type: application/x-www-form-urlencoded
00e4: 
=> Send data, 45 bytes (0x2d)
0000: uuid=d99a49d846d5ae570667a00825373a7b5ae8e8e2
<= Recv header, 24 bytes (0x18)
0000: HTTP/1.1 403 Forbidden
<= Recv header, 22 bytes (0x16)
0000: Server: nginx/0.7.66
<= Recv header, 37 bytes (0x25)
0000: Date: Wed, 11 Aug 2010 15:37:06 GMT
<= Recv header, 25 bytes (0x19)
0000: Content-Type: text/html
<= Recv header, 28 bytes (0x1c)
0000: Transfer-Encoding: chunked
<= Recv header, 24 bytes (0x18)
0000: Connection: keep-alive
<= Recv header, 25 bytes (0x19)
0000: X-Powered-By: PHP/5.3.2
<= Recv header, 56 bytes (0x38)
0000: Set-Cookie: SESSION=m9j6caghb223uubiddolec2005; path=/
<= Recv header, 57 bytes (0x39)
0000: P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"
<= Recv header, 2 bytes (0x2)
0000: 
<= Recv data, 118 bytes (0x76)
0000: 6b
0004: <html><head><title>HTTP/1.1 403 Forbidden</title></head><body><h
0044: 1>HTTP/1.1 403 Forbidden</h1></body></html>
0071: 0
0074: 
== Info: Connection #0 to host project1.loc left intact
== Info: Closing connection #0

Mon fichier d'hôtes ressemble à:

# Copyright (c) 1993-1999 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host

127.0.0.1       localhost
...
...
127.0.0.1   project1.loc
Xeoncross
la source
1
-Hest pour l'en-tête complet, pas seulement pour l'hôte, alors utilisez -H 'Host: project1.loc'. De plus, malgré ce problème, cette requête semble fonctionner sur le bon hôte (obtenu correctement à partir de votre hostsfichier par curl sur la ligne de commande au moins). Ce qui ne fonctionne pas (403) semble être un problème d'authentification / autorisation, donc votre serveur semble bloquer ces demandes. Je suggère de corriger la configuration du serveur pour cela.
Bruno
0

Pour configurer des hôtes virtuels sur des serveurs http Apache qui ne sont pas encore connectés via DNS, j'aime utiliser:

curl -s --connect-to ::host-name: http://project1.loc/post.json

Où host-name est l'adresse IP ou le nom DNS de la machine sur laquelle le serveur Web est exécuté. Cela fonctionne également bien pour les sites https.

effhaa
la source
1
Ce message a été envoyé il y a 10 ans et corrigé via des commentaires, merci pour votre contribution. Dans ce type de messages, veuillez vérifier les réponses, s'il y a un vote pour envoyer un message, sinon postez une nouvelle réponse car vous pourriez être marqué comme spam.
samuhay