Configurar cURL para usar hosts virtuales locales

115

Usando Apache o Ngnix siempre creo sitios de desarrollo basados ​​en proyectos reales como los http://project1.locque, después de agregar a mi .hostsarchivo, el navegador no tiene problemas para usar.

Sin embargo, cuando intento hacer una solicitud cURL ( http://project1.loc/post.json) a esa misma URL, nunca obtengo nada más que un tiempo de espera. Supongo que a cURL no le importan mis hosts personalizados y va directamente a un servidor de nombres para obtener su información.

¿Cómo puedo arreglar esto?

ACTUALIZAR Establecí un encabezado personalizado "HOST: http: //project1.loc " y ahora recibo 400 errores, pero son instantáneos, así que supongo que cURL al menos está usando el archivo de hosts ...

Xeoncross
fuente

Respuestas:

428

En realidad, curl tiene una opción explícita para esto: --resolve

En vez de curl -H 'Host: yada.com' http://127.0.0.1/something

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

¿Cuál es la diferencia, preguntas?

Entre otros, esto funciona con HTTPS. Suponiendo que su servidor local tiene un certificado para yada.com, el primer ejemplo anterior fallará porque el yada.comcertificado no coincide con el 127.0.0.1nombre de host en la URL.

El segundo ejemplo funciona correctamente con HTTPS.

En esencia, pasar un encabezado de "Host" a través de -Hpiratea tu Host en el conjunto de encabezados, pero omite toda la inteligencia específica del host de curl. El uso --resolveaprovecha toda la lógica normal que se aplica, pero simplemente pretende que la búsqueda de DNS devolvió los datos en su opción de línea de comandos. Funciona como /etc/hostsdebería.

Nota --resolvetoma un número de puerto, por lo que para HTTPS usaría

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

John Hart
fuente
26
Esto me está matando, ¿alguien puede marcar esto como la respuesta correcta? Es mucho más nuevo que la respuesta, por lo que no tiene los votos ... pero la respuesta aceptada es incorrecta (es decir, solo funciona para ciertas situaciones) = (
John Hart
De hecho, esta es una gran respuesta y recibió mi voto. Solo Xenocross puede marcar una respuesta como aceptada. Con el tiempo, es probable que otros vengan aquí y gradualmente voten más alto por el suyo.
hobodave
10
Vale la pena señalar que --resolve solo se agregó en curl 7.21.3 - si está atascado en un host más antiguo (por ejemplo, Ubuntu 10.04 LTS), la opción -H 'Host ...' sigue siendo una alternativa útil.
Ken
9
Si bien estoy de acuerdo, esta probablemente debería ser la respuesta aceptada (y ciertamente no me ofendería si el OP la cambiara, por el contrario), decir que mi respuesta es incorrecta no es correcta: es correcta para las versiones disponibles en ese momento se produjo la pregunta y la respuesta. Así que los usuarios a los que no se les puede molestar leer más allá de la primera respuesta y también evaluar las respuestas en función de sus marcas de tiempo nunca obtendrán la mejor ayuda ...
Bruno
1
Lo siento, Bruno, no quise ofender.
John Hart
120

EDITAR: Si bien esta es una respuesta actualmente aceptada, los lectores pueden encontrar esta otra respuesta del usuario John Hart más adaptada a sus necesidades. Utiliza una opción que, según el usuario Ken , se introdujo en la versión 7.21.3 (que fue lanzada en diciembre de 2010 , es decir, después de esta respuesta inicial).


En su pregunta editada, está utilizando la URL como nombre de host, mientras que solo debe ser el nombre de host.

Tratar:

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

donde project1.loces solo el nombre de host y 127.0.0.1es la dirección IP de destino.

(Si está usando curl de una biblioteca y no en la línea de comando, asegúrese de no poner http://el Hostencabezado).

Bruno
fuente
1
Recibo 400 errores con PHP y cuando realizo manualmente la solicitud con curl.exe obtengo el índice predeterminado del servidor, lo que significa que no está respetando el HOSTencabezado.
Xeoncross
Lo probé en varios servidores con hosts virtuales y funciona (desde la línea de comandos). Intente Hostno HOSTsolo por si acaso (aunque creo que no debería distinguir entre mayúsculas y minúsculas). Como dije, asegúrese de usar solo el nombre de host en el Hostencabezado, nada más (no http://y no /somethingdespués). ¿Cómo configuró su archivo de hosts?
Bruno
Publicó más datos sobre los resultados de hacer esto a continuación.
Xeoncross
1
Como dijo Bruno a continuación, el problema probablemente sea solo la configuración de mi servidor, ya que la solicitud parece estar haciendo y recibiendo un error 403.
Xeoncross
Me perdí "127.0.0.1 myvirtualhost.localhost" en el archivo de hosts, de ahí el problema.
Arvind K.
2

Utilice un nombre de dominio real y completo (como dev.yourdomain.com) que apunte 127.0.0.1o intente editar el archivo de hosts adecuado (generalmente / etc / hosts en entornos * nix).

Oli
fuente
Desarrollo en Windows usandosystem32/drivers/etc/hosts
Xeoncross
¿Está utilizando la compilación nativa de cURL o alguna compilación cruzada de cygwin? Digo esto porque no estoy seguro de cómo cada uno resuelve su DNS. El nativo debería tomar del archivo de hosts de Windows, pero una versión cygwin podría querer una versión cygwin. De cualquier manera, usar un dominio real que apunte a 127.0.0.1 funcionaría sin importar cómo estén configuradas las cosas.
Oli
Estoy usando la compilación nativa de Windows incluida con PHP 5.3 para Windows (se ejecuta como php_fastcgi).
Xeoncross
2

Parece que este no es un problema infrecuente.

Compruebe esto primero.

Si eso no ayuda, puede instalar un servidor DNS local en Windows, como este . Configure Windows para usar localhost como servidor DNS. Este servidor se puede configurar para que sea autorizado para cualquier dominio falso que necesite y para reenviar solicitudes a los servidores DNS reales para todas las demás solicitudes.

Personalmente, creo que esto es un poco exagerado y no veo por qué el archivo de hosts no funciona. Pero debería resolver el problema que tienes. Asegúrese de configurar sus servidores DNS normales también como reenviadores.

Mate
fuente
¿Podría leer su propia respuesta y reescribirla? ¡El inglés en la tercera línea no tiene sentido!
OmarOthman
Arreglado. Vaya, supongo que lo escribí demasiado rápido sin leerlo correctamente.
Matt
1

¿El servidor realmente recibe las solicitudes y está manejando el nombre de host (alias) correctamente?

después de agregar a mi archivo .hosts

Consulte el registro de su servidor web para ver cómo llegó la solicitud ...

curl tiene opciones para volcar la solicitud enviada y la respuesta recibida, se llama rastreo, que se guardará en un archivo.

--rastro

Si le falta información de host o encabezado, puede forzar esos encabezados con la opción de configuración.

Obtendría la solicitud curl funcionando en la línea de comando y luego intentaría implementarla en PHP.

la opción de configuración es

-K / - config

las opciones que son relevantes en curl están aquí

--trace Habilita un volcado de seguimiento completo de todos los datos entrantes y salientes, incluida la información descriptiva, en el archivo de salida dado. Utilice "-" como nombre de archivo para que la salida se envíe a 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 Especifica desde qué archivo de configuración leer los argumentos curl. El archivo de configuración es un archivo de texto en el que se pueden escribir argumentos de la línea de comandos que luego se usarán como si estuvieran escritos en la línea de comandos real. Las opciones y sus parámetros deben especificarse en la misma línea del archivo de configuración, separados por espacios en blanco, dos puntos, el signo igual o cualquier combinación de los mismos (sin embargo, el separador preferido es el signo igual). Si el parámetro debe contener espacios en blanco, el parámetro debe ir entre comillas. Entre comillas dobles, están disponibles las siguientes secuencias de escape: \, \ ", \ t, \ n, \ r y \ v. Se ignora una barra invertida que precede a cualquier otra letra. Si la primera columna de una línea de configuración es un '#' carácter, el resto de la línea se tratará como un comentario.

      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
fuente
Nuevamente, estoy usando PHP en Windows para buscar una página en un vhost en las mismas ventanas que ejecutan nginx. De todos modos, hice una solicitud a un vhost http://domain.loc/users/getSettings.xmly esto es lo que mostró el access.log 127.0.0.1 - - [09/Aug/2010:11:42:55 -0500] "POST /users/getSettings.xml HTTP/1.1" 499 0 "-" "-"y curl informó. Operation timed out after 10000 milliseconds with 0 bytes received Así que supongo que cURL está manejando el vhost ya que el access.log muestra la solicitud. Por otra parte, ahora podría estar llegando al dominio correcto ...
Xeoncross
El "499 0" en esa línea es MUY significativo. El proceso devolvió cero bytes, lo que curl estaba esperando. y devolvió un HTTP 499, que es un resultado extraño. llame a otro script, que devuelve una cadena estática en respuesta a la publicación, y vea que obtiene la respuesta en curl. Es posible que no publique los datos como espera ... y el script puede estar agotando el tiempo esperando la respuesta. también cambie la secuencia de comandos para registrar la entrada en un archivo temporal y ver que está "recibiendo la publicación esperada de su solicitud curl"
George Lambert
Agregue, ¿probó la línea de comandos curl para poder controlar la publicación y ver la respuesta del servidor?
George Lambert
Respuesta rápida a la segunda pregunta: no. No sé cómo acceder a la línea de comando cURL en Windows, ya que está integrado en PHP y no en la terminal de Windows.
Xeoncross
1
puede descargar una versión de línea de comandos de curl para Windows desde aquí curl.haxx.se/download.html
George Lambert
1

Hacer una solicitud a

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

Resultó en el -Harchivo de registro que contiene:

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

Mi archivo de hosts se ve así:

# 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
fuente
1
-Hes para el encabezado completo, no solo para el host, así que use -H 'Host: project1.loc'. Además, a pesar de este problema, esta solicitud parece funcionar en el host correcto (obtenida correctamente de su hostsarchivo al menos mediante curl en la línea de comando). Lo que no funciona (403) parece un problema de autenticación / autorización, por lo que su servidor parece estar bloqueando estas solicitudes. Sugeriría arreglar la configuración del servidor para esto.
Bruno
0

Para configurar hosts virtuales en servidores http Apache que aún no están conectados a través de DNS, me gusta usar:

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

Donde nombre de host es la dirección IP o el nombre DNS de la máquina en la que se ejecuta el servidor web. Esto también funciona bien para los sitios https.

efhaa
fuente
1
Esta publicación se envió hace 10 años y se corrigió a través de comentarios, gracias por la contribución. En este tipo de publicaciones, verifique las respuestas, si hay un voto de asnwear, envíe una nueva respuesta porque podría marcarla como spam.
samuhay