Defina cURL para usar hosts virtuais locais

115

Usando Apache ou Ngnix, sempre crio sites de desenvolvimento baseados em projetos reais, como os http://project1.locquais, após adicionar ao meu.hosts arquivo, o navegador não tem problema de usar.

No entanto, quando tento fazer uma solicitação cURL ( http://project1.loc/post.json) para esse mesmo URL, nunca recebo nada além de um tempo limite. Estou assumindo que o cURL não se preocupa com meus hosts personalizados e vai direto para um servidor de nomes para obter suas informações.

Como posso consertar isso?

ATUALIZAÇÃO Defini um cabeçalho personalizado "HOST: http: //project1.loc " e agora estou recebendo 400 erros - mas eles são instantâneos, então estou assumindo que cURL está pelo menos usando o arquivo hosts ...

Xeoncross
fonte

Respostas:

428

Na verdade, curl tem uma opção explicitamente para isso: --resolve

Ao invés de curl -H 'Host: yada.com' http://127.0.0.1/something

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

Qual é a diferença, você pergunta?

Entre outros, funciona com HTTPS. Supondo que seu servidor local tenha um certificado para yada.com, o primeiro exemplo acima falhará porque o yada.comcertificado não corresponde ao127.0.0.1 nome host no URL.

O segundo exemplo funciona corretamente com HTTPS.

Em essência, passar um cabeçalho "Host" via -Hhack seu Host no conjunto de cabeçalhos, mas ignora toda a inteligência específica do host do curl. O uso --resolveaproveita toda a lógica normal aplicável, mas simplesmente finge que a pesquisa DNS retornou os dados em sua opção de linha de comando. Funciona exatamente como/etc/hosts deveria.

Note --resolveleva um número de porta, então para HTTPS você usaria

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

John Hart
fonte
26
Isso está me matando - alguém pode marcar isso como a resposta certa? É muito mais recente do que a resposta, então não tem os votos .. mas a resposta aceita está errada (ou seja, só funciona para certas situações) = (
John Hart
Esta é de fato uma ótima resposta e recebeu meu voto. Apenas Xenocross pode marcar uma resposta como aceita. Com o tempo, provavelmente outros virão aqui e gradativamente votarão mais no seu.
hobodave
10
Vale a pena notar que --resolve só foi adicionado no curl 7.21.3 - se você estiver preso em um host mais antigo (por exemplo, Ubuntu 10.04 LTS), então a opção -H 'Host ...' ainda é um fallback útil.
Ken
9
Embora eu concorde que essa provavelmente deve ser a resposta aceita (e eu certamente não ficaria ofendido se o OP a alterasse, pelo contrário), dizer que minha resposta está errada, não está certa: é a correta para as versões disponíveis no momento a pergunta e a resposta foram produzidas. ASSIM, usuários que não se incomodam em ler além da primeira resposta e também avaliar as respostas com base em seus carimbos de data / hora, nunca terão a melhor ajuda ...
Bruno
1
Desculpe, Bruno, sem querer ofender.
John Hart
120

EDIT: Embora esta seja uma resposta aceita atualmente, os leitores podem achar esta outra resposta do usuário John Hart mais adaptada às suas necessidades. Utiliza uma opção que, segundo o usuário Ken , foi introduzida na versão 7.21.3 (que foi lançada em dezembro de 2010 , ou seja, após esta resposta inicial).


Em sua pergunta editada, você está usando o URL como o nome do host, ao passo que precisa ser apenas o nome do host.

Experimentar:

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

onde project1.locé apenas o nome do host e 127.0.0.1é o endereço IP de destino.

(Se você estiver usando curl de uma biblioteca e não na linha de comando, certifique-se de não colocar http://o Hostcabeçalho.)

Bruno
fonte
1
Estou recebendo 400 erros com PHP e quando faço a solicitação manualmente com curl.exe, obtenho o índice padrão do servidor, o que significa que ele não está respeitando o HOSTcabeçalho.
Xeoncross
Eu tentei em vários servidores com hosts virtuais e funciona (na linha de comando). Tente Hostnão HOSTapenas no caso (embora eu ache que não deve ser sensível a maiúsculas e minúsculas). Como eu disse, certifique-se de usar apenas o nome do host no Hostcabeçalho, nada mais (não http://e não /somethingdepois). Como você configurou seu arquivo hosts?
Bruno
Postado mais dados sobre os resultados de fazer isso abaixo.
Xeoncross
1
Como Bruno disse abaixo, o problema provavelmente é apenas a configuração do meu servidor, pois a solicitação parece estar fazendo isso e recebendo um erro 403.
Xeoncross
Perdi "127.0.0.1 myvirtualhost.localhost" no arquivo hosts, daí o problema.
Arvind K.
2

Use um nome de domínio totalmente qualificado real (como dev.yourdomain.com) que aponte para 127.0.0.1ou tente editar o arquivo de hosts apropriado (geralmente / etc / hosts em ambientes * nix).

Oli
fonte
Eu desenvolvo no Windows usandosystem32/drivers/etc/hosts
Xeoncross 02 de
Você está usando a compilação nativa do cURL ou alguma compilação cruzada do cygwin? Digo isso porque não tenho certeza de como cada um resolve seu DNS. O nativo deve pegar do arquivo hosts do Windows, mas uma versão cygwin pode querer uma versão cygwin. De qualquer forma, usar um domínio real apontando para 127.0.0.1 funcionaria independentemente da configuração.
Oli
Estou usando a compilação nativa do Windows incluída no PHP 5.3 para Windows (executando como php_fastcgi).
Xeoncross
2

Parece que esse não é um problema incomum.

Verifique isto primeiro.

Se isso não ajudar, você pode instalar um servidor DNS local no Windows, como este . Configure o Windows para usar localhost como servidor DNS. Este servidor pode ser configurado para ser autoritativo para quaisquer domínios falsos de que você precise e para encaminhar solicitações para os servidores DNS reais para todas as outras solicitações.

Eu pessoalmente acho que isso é um pouco exagerado e não consigo ver por que o arquivo hosts não funcionaria. Mas deve resolver o problema que você está tendo. Certifique-se de configurar seus servidores DNS normais como encaminhadores também.

Matt
fonte
Você poderia ler sua própria resposta e reescrevê-la? O inglês na terceira linha não faz sentido!
OmarOthman
Tidied. Puxa, acho que digitei muito rápido sem ler direito.
Matt
1

O servidor realmente recebe as solicitações e você está lidando com o nome do host (alias) corretamente?

depois de adicionar ao meu arquivo .hosts

Verifique o log do seu servidor da web para ver como a solicitação veio ...

curl tem opções para despejar a requisição enviada e a resposta recebida, é chamado de trace, que será salvo em um arquivo.

--vestígio

Se não houver informações de host ou cabeçalho, você pode forçar esses cabeçalhos com a opção de configuração.

Gostaria de obter a solicitação curl funcionando na linha de comando e, em seguida, tentar implementar em PHP.

a opção de configuração é

-K / - config

as opções relevantes no curl estão aqui

--trace Habilita um dump de rastreamento completo de todos os dados de entrada e saída, incluindo informações descritivas, para o arquivo de saída fornecido. Use "-" como nome de arquivo para que a saída seja enviada para 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 Especifique de qual arquivo de configuração ler os argumentos curl. O arquivo de configuração é um arquivo de texto no qual os argumentos da linha de comando podem ser escritos, os quais serão usados ​​como se tivessem sido escritos na linha de comando real. As opções e seus parâmetros devem ser especificados na mesma linha do arquivo de configuração, separados por espaço em branco, dois pontos, o sinal de igual ou qualquer combinação deles (entretanto, o separador preferido é o sinal de igual). Se o parâmetro deve conter espaços em branco, o parâmetro deve ser colocado entre aspas. Entre aspas duplas, as seguintes sequências de escape estão disponíveis: \, \ ", \ t, \ n, \ r e \ v. Uma barra invertida precedendo qualquer outra letra é ignorada. Se a primeira coluna de uma linha de configuração for um '#' caractere, o resto da linha será tratado como um comentário.

      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
fonte
Novamente, estou usando o PHP no Windows para buscar uma página em um vhost nas mesmas janelas que executam o nginx. De qualquer forma, fiz uma solicitação a um vhost http://domain.loc/users/getSettings.xmle é isso que o access.log mostrou 127.0.0.1 - - [09/Aug/2010:11:42:55 -0500] "POST /users/getSettings.xml HTTP/1.1" 499 0 "-" "-"e o curl relatou. Operation timed out after 10000 milliseconds with 0 bytes received Portanto, acho que o cURL está realmente lidando com o vhost, já que o access.log mostra a solicitação. Então, novamente, ele pode estar chegando ao domínio correto ...
Xeoncross
O "499 0" nessa linha é MUITO significativo. O processo retornou zero bytes - que o curl estava esperando. e retornou um HTTP 499 - que é um resultado estranho. chame outro script - que retorna uma string estática em resposta à postagem - e veja se você está obtendo a resposta em curl. Você pode não estar postando os dados como espera ... e o script pode estar expirando ao aguardar a resposta. também altere o script para registrar a entrada em um arquivo temporário e veja se você está "recebendo a postagem esperada de sua solicitação curl"
George Lambert
Adicionar, você tentou curl de linha de comando - para que você pudesse controlar a postagem e ver a resposta do servidor?
George Lambert
Resposta rápida à segunda pergunta - não. Não sei como acessar o cURL da linha de comando no Windows, pois ele está integrado ao PHP e não no terminal do Windows.
Xeoncross de
1
você pode baixar uma versão de linha de comando do curl para windows aqui curl.haxx.se/download.html
George Lambert
1

Fazendo um pedido para

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

Resultou no -Harquivo de log contendo:

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

Meu arquivo hosts se parece com:

# 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
fonte
1
-Hé para o cabeçalho completo, não apenas para o host, então use -H 'Host: project1.loc'. Além disso, apesar do problema, essa solicitação parece funcionar no host correto (obtido corretamente de seu hostsarquivo pelo curl na linha de comando). O que não está funcionando (403) parece ser um problema de autenticação / autorização, então seu servidor parece estar bloqueando essas solicitações. Eu sugiro corrigir a configuração do servidor para isso.
Bruno
0

Para configurar hosts virtuais em servidores HTTP Apache que ainda não estão conectados via DNS, eu gosto de usar:

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

Onde host-name ist o endereço IP ou o nome DNS da máquina na qual o servidor web está sendo executado. Isso também funciona bem para https-Sites.

effhaa
fonte
1
Esta postagem foi enviada há 10 anos e corrigida por meio de comentários, obrigado pela contribuição. Nesse tipo de postagem, verifique as respostas, se houver um asnwear envie um voto senão poste uma nova resposta porque você pode ser marcado como spam.
samuhay