Stellen Sie cURL so ein, dass lokale virtuelle Hosts verwendet werden

115

Mit Apache oder Ngnix erstelle ich immer Entwicklungsseiten, die auf realen Projekten basieren, z. B. http://project1.locdie .hostsder Browser nach dem Hinzufügen zu meiner Datei problemlos verwenden kann.

Wenn ich jedoch versuche, eine cURL-Anfrage ( http://project1.loc/post.json) an dieselbe URL zu senden, wird nur eine Zeitüberschreitung angezeigt. Ich gehe davon aus, dass cURL sich nicht um meine benutzerdefinierten Hosts kümmert und direkt zu einem Nameserver geht, um Informationen zu erhalten.

Wie kann ich das beheben?

UPDATE Ich habe einen benutzerdefinierten Header "HOST: http: //project1.loc " gesetzt und jetzt werden 400 Fehler angezeigt - diese treten jedoch sofort auf, sodass ich davon ausgehe, dass cURL mindestens die Hosts-Datei verwendet ...

Xeoncross
quelle

Antworten:

428

Tatsächlich hat Curl eine explizite Option dafür: --resolve

Anstatt curl -H 'Host: yada.com' http://127.0.0.1/something

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

Was ist der Unterschied, fragst du?

Dies funktioniert unter anderem mit HTTPS. Angenommen, Ihr lokaler Server verfügt über ein Zertifikat für yada.com, yada.comschlägt das erste Beispiel oben fehl, da das Zertifikat nicht mit dem 127.0.0.1Hostnamen in der URL übereinstimmt .

Das zweite Beispiel funktioniert korrekt mit HTTPS.

Im Wesentlichen -Hhackt das Übergeben eines "Host" -Headers über Ihren Host in den Header-Satz, umgeht jedoch die gesamte hostspezifische Intelligenz von curl. Die Verwendung --resolvenutzt die gesamte geltende normale Logik, gibt jedoch einfach vor, dass die DNS-Suche die Daten in Ihrer Befehlszeilenoption zurückgegeben hat. Es funktioniert genau wie /etc/hostssollte.

Hinweis --resolvenimmt eine Portnummer an, also würden Sie für HTTPS verwenden

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

John Hart
quelle
26
Das bringt mich um - kann jemand dies bitte als die richtige Antwort markieren? Es ist viel neuer als die Antwort, hat also keine Stimmen. Aber die akzeptierte Antwort ist falsch (dh funktioniert nur in bestimmten Situationen) = (
John Hart
Dies ist in der Tat eine großartige Antwort und hat meine Stimme erhalten. Nur Xenocross kann eine Antwort als akzeptiert markieren. Mit der Zeit werden wahrscheinlich andere hierher kommen und Ihre nach und nach höher stimmen.
Hobodave
10
Es ist erwähnenswert, dass --resolve nur in Curl 7.21.3 hinzugefügt wurde - wenn Sie auf einem älteren Host (z. B. Ubuntu 10.04 LTS) stecken bleiben, ist die Option -H 'Host ...' immer noch ein nützlicher Fallback.
Ken
9
Obwohl ich damit einverstanden bin, dass dies wahrscheinlich die akzeptierte Antwort sein sollte (und ich würde mich sicherlich nicht beleidigen, wenn das OP sie im Gegenteil ändern würde), ist es nicht richtig zu sagen, dass meine Antwort falsch ist: Sie ist für die zu diesem Zeitpunkt verfügbaren Versionen korrekt Die Frage und Antwort wurde produziert. SO Benutzer, die Sie nicht die Mühe haben, nach der ersten Antwort zu lesen und auch Antworten basierend auf ihren Zeitstempeln zu bewerten, werden nie die beste Hilfe bekommen ...
Bruno
1
Entschuldigung, Bruno, nichts für ungut.
John Hart
120

BEARBEITEN: Während diese Antwort derzeit akzeptiert wird, finden Leser diese andere Antwort von Benutzer John Hart möglicherweise besser an ihre Bedürfnisse angepasst. Es wird eine Option verwendet, die laut Benutzer Ken in Version 7.21.3 eingeführt wurde (die im Dezember 2010 veröffentlicht wurde , dh nach dieser ersten Antwort).


In Ihrer bearbeiteten Frage verwenden Sie die URL als Hostnamen, während es sich nur um den Hostnamen handeln muss.

Versuchen:

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

Dabei project1.locist nur der Hostname und 127.0.0.1die Ziel-IP-Adresse angegeben.

(Wenn Sie Curl aus einer Bibliothek verwenden und nicht in der Befehlszeile, stellen Sie sicher, dass Sie nicht http://in die HostKopfzeile einfügen.)

Bruno
quelle
1
Ich erhalte 400 Fehler mit PHP und wenn ich die Anfrage manuell mit curl.exe stelle, erhalte ich den Standardindex des Servers, was bedeutet, dass der HOSTHeader nicht berücksichtigt wird .
Xeoncross
Ich habe es auf verschiedenen Servern mit virtuellen Hosts versucht und es funktioniert (über die Befehlszeile). Versuchen Sie es Hostnicht HOSTnur für den Fall (obwohl ich denke, dass es nicht zwischen Groß- und Kleinschreibung unterscheiden sollte). Wie gesagt, stellen Sie sicher, dass Sie nur den Hostnamen in der HostKopfzeile verwenden, sonst nichts (nein http://und nein /somethingdanach). Wie haben Sie Ihre Hosts-Datei eingerichtet?
Bruno
Veröffentlichte unten weitere Daten zu den Ergebnissen.
Xeoncross
1
Wie Bruno unten sagte, ist das Problem wahrscheinlich nur meine Serverkonfiguration, da die Anfrage es zu machen scheint und einen 403-Fehler empfängt.
Xeoncross
Ich habe "127.0.0.1 myvirtualhost.localhost" in der Hosts-Datei verpasst, daher das Problem.
Arvind K.
2

Verwenden Sie entweder einen echten vollqualifizierten Domänennamen (wie dev.yourdomain.com), der auf 127.0.0.1die richtige Hosts-Datei verweist, oder versuchen Sie, diese zu bearbeiten (normalerweise / etc / hosts in * nix-Umgebungen).

Oli
quelle
Ich entwickle unter Windows mitsystem32/drivers/etc/hosts
Xeoncross
Verwenden Sie den nativen Build von cURL oder einen Cygwin-Crossbuild? Ich sage das, weil ich nicht sicher bin, wie jeder sein DNS auflöst. Der native sollte aus der Windows-Hosts-Datei abrufen, aber eine Cygwin-Version möchte möglicherweise eine Cygwin-Version. In beiden Fällen würde die Verwendung einer realen Domain, die auf 127.0.0.1 verweist, funktionieren, unabhängig davon, wie die Dinge eingerichtet sind.
Oli
Ich verwende den nativen Windows-Build, der in PHP 5.3 für Windows enthalten ist (läuft als php_fastcgi).
Xeoncross
2

Es scheint, dass dies kein ungewöhnliches Problem ist.

Überprüfen Sie dies zuerst.

Wenn dies nicht hilft, können Sie unter Windows einen lokalen DNS-Server wie diesen installieren . Konfigurieren Sie Windows so, dass localhost als DNS-Server verwendet wird. Dieser Server kann so konfiguriert werden, dass er für alle von Ihnen benötigten gefälschten Domänen autorisierend ist und Anforderungen für alle anderen Anforderungen an die echten DNS-Server weiterleitet.

Ich persönlich denke, das ist etwas übertrieben und kann nicht verstehen, warum die Hosts-Datei nicht funktioniert. Aber es sollte das Problem lösen, das Sie haben. Stellen Sie sicher, dass Sie Ihre normalen DNS-Server auch als Weiterleitungen einrichten.

Matt
quelle
Könnten Sie bitte Ihre eigene Antwort lesen und neu schreiben? Das Englisch in der dritten Zeile macht keinen Sinn!
OmarOthman
Aufgeräumt. Ich habe das wohl zu schnell getippt, ohne es richtig zu lesen.
Matt
1

Erhält der Server tatsächlich die Anforderungen und behandeln Sie den Hostnamen (Alias) ordnungsgemäß?

nach dem Hinzufügen zu meiner .hosts-Datei

Überprüfen Sie Ihr Webserver-Protokoll, um festzustellen, wie die Anfrage eingegangen ist ...

curl hat Optionen zum Speichern der gesendeten Anforderung und der empfangenen Antwort. Sie wird als Trace bezeichnet und in einer Datei gespeichert.

--Spur

Wenn Sie Host- oder Header-Informationen vermissen, können Sie diese Header mit der Konfigurationsoption erzwingen.

Ich würde die Curl-Anfrage in der Kommandozeile zum Laufen bringen und dann versuchen, sie in PHP zu implementieren.

Die Konfigurationsoption ist

-K / - config

Hier finden Sie die Optionen, die für Curl relevant sind

--trace Ermöglicht einen vollständigen Trace-Dump aller eingehenden und ausgehenden Daten, einschließlich beschreibender Informationen, in die angegebene Ausgabedatei. Verwenden Sie "-" als Dateinamen, um die Ausgabe an stdout zu senden.

      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 Geben Sie an, aus welcher Konfigurationsdatei Curl-Argumente gelesen werden sollen. Die Konfigurationsdatei ist eine Textdatei, in die Befehlszeilenargumente geschrieben werden können, die dann so verwendet werden, als ob sie in die eigentliche Befehlszeile geschrieben würden. Optionen und ihre Parameter müssen in derselben Konfigurationsdateizeile angegeben werden, getrennt durch Leerzeichen, Doppelpunkt, Gleichheitszeichen oder eine beliebige Kombination davon (der bevorzugte Trennzeichen ist jedoch das Gleichheitszeichen). Wenn der Parameter Leerzeichen enthalten soll, muss der Parameter in Anführungszeichen gesetzt werden. In doppelten Anführungszeichen stehen die folgenden Escape-Sequenzen zur Verfügung: \, \ ", \ t, \ n, \ r und \ v. Ein Backslash vor einem anderen Buchstaben wird ignoriert. Wenn die erste Spalte einer Konfigurationszeile ein '#' ist. Zeichen wird der Rest der Zeile als Kommentar behandelt.

      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
quelle
Wieder verwende ich PHP unter Windows, um eine Seite auf einem vhost unter denselben Fenstern abzurufen, auf denen nginx ausgeführt wird. Wie auch immer, ich habe eine Anfrage an einen vhost gestellt http://domain.loc/users/getSettings.xmlund dies wurde im access.log angezeigt 127.0.0.1 - - [09/Aug/2010:11:42:55 -0500] "POST /users/getSettings.xml HTTP/1.1" 499 0 "-" "-"und im Curl gemeldet. Operation timed out after 10000 milliseconds with 0 bytes received Ich denke also, dass cURL den vhost tatsächlich verarbeitet, da das access.log die Anfrage anzeigt.
Andererseits
Die "499 0" in dieser Zeile ist SEHR signifikant. Der Prozess gab null Bytes zurück - auf welche Locke gewartet wurde. und gab ein HTTP 499 zurück - was ein seltsames Ergebnis ist. Rufen Sie ein anderes Skript auf, das als Antwort auf den Beitrag eine statische Zeichenfolge zurückgibt, und stellen Sie sicher, dass Sie die Antwort in Curl erhalten. Viele veröffentlichen die Daten nicht wie erwartet ... und das Skript wartet möglicherweise nicht mehr auf die Antwort. Ändern Sie auch das Skript, um die Eingabe in einer temporären Datei zu protokollieren, und stellen Sie sicher, dass Sie "den erwarteten Beitrag von Ihrer Curl-Anfrage erhalten"
George Lambert
Haben Sie versucht, die Befehlszeile zu kräuseln, damit Sie den Beitrag steuern und die Serverantwort sehen können?
George Lambert
Schnelle Antwort auf die zweite Frage - nein. Ich weiß nicht, wie ich unter Windows auf die Befehlszeilen-cURL zugreifen soll, da sie in PHP integriert ist und nicht in das Windows-Terminal.
Xeoncross
1
Sie können eine Befehlszeilenversion von Curl für Windows von hier herunterladen. curl.haxx.se/download.html
George Lambert
1

Anfrage stellen an

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

Ergebnis in der -HProtokolldatei mit:

== 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

Meine Hosts-Datei sieht folgendermaßen aus:

# 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
quelle
1
-Hist für den vollständigen Header, nicht nur Host, also verwenden -H 'Host: project1.loc'. Darüber hinaus scheint diese Anforderung trotz dieses Problems auf dem richtigen Host zu funktionieren (der korrekt aus Ihrer hostsDatei durch Curl in der Befehlszeile abgerufen wurde ). Was nicht funktioniert (403), scheint ein Authentifizierungs- / Autorisierungsproblem zu sein, sodass Ihr Server diese Anforderungen zu blockieren scheint. Ich würde vorschlagen, die Serverkonfiguration dafür zu korrigieren.
Bruno
0

Zum Einrichten von virtuellen Hosts auf Apache-HTTP-Servern, die noch nicht über DNS verbunden sind, verwende ich Folgendes:

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

Dabei ist Hostname die IP-Adresse oder der DNS-Name des Computers, auf dem der Webserver ausgeführt wird. Dies funktioniert auch gut für https-Sites.

effhaa
quelle
1
Dieser Beitrag wurde vor 10 Jahren gesendet und über Kommentare korrigiert, danke für den Beitrag. Bei dieser Art von Posts suchen Sie bitte nach Antworten. Wenn es eine Asnwear-Abstimmung gibt, senden Sie eine neue Antwort, da Sie als Spam markiert werden könnten.
Samuhay