Установите cURL для использования локальных виртуальных хостов

115

Используя Apache или Ngnix, я всегда создаю сайты разработки на основе реальных проектов, например, http://project1.locкоторые после добавления в мой .hostsфайл браузер без проблем использует.

Однако, когда я пытаюсь сделать запрос cURL ( http://project1.loc/post.json) к тому же URL, я никогда не получаю ничего, кроме тайм-аута. Я предполагаю, что cURL не заботится о моих пользовательских хостах и ​​отправляется прямо на сервер имен для получения информации.

Как я могу это исправить?

ОБНОВЛЕНИЕ Я установил собственный заголовок «HOST: http: //project1.loc », и теперь я получаю 400 ошибок, но они возникают мгновенно, поэтому я предполагаю, что cURL, по крайней мере, использует файл hosts ...

Xeoncross
источник

Ответы:

428

Собственно, у curl есть опция явно для этого: --resolve

Вместо того curl -H 'Host: yada.com' http://127.0.0.1/something

использование curl --resolve 'yada.com:80:127.0.0.1' http://yada.com/something

Вы спросите, какая разница?

Среди прочего, это работает с HTTPS. Предполагая, что у вашего локального сервера есть сертификат для yada.com, первый пример выше не удастся, потому что yada.comсертификат не соответствует имени 127.0.0.1хоста в URL-адресе.

Второй пример корректно работает с HTTPS.

По сути, передача заголовка "Host" через -Hдействительно взламывает ваш Host в наборе заголовков, но обходит весь специфический для хоста интеллект curl. Использование --resolveиспользует всю применяемую обычную логику, но просто делает вид, что поиск DNS вернул данные в параметре командной строки. Работает как и /etc/hostsдолжно.

Примечание --resolveпринимает номер порта, поэтому для HTTPS вы должны использовать

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

Джон Харт
источник
26
Это меня убивает - может кто-нибудь отметить это как правильный ответ? Он намного новее, чем ответ, поэтому у него нет голосов .. но принятый ответ неверен (т.е. работает только в определенных ситуациях) = (
Джон Харт
Это действительно отличный ответ, и он получил мой голос. Только Xenocross может отметить ответ как принятый. Со временем сюда, скорее всего, придут другие и постепенно проголосуют за вас.
hobodave
10
Стоит отметить, что --resolve был добавлен только в curl 7.21.3 - если вы застряли на более старом хосте (например, Ubuntu 10.04 LTS), то опция -H 'Host ...' по-прежнему является полезным запасным вариантом.
Кен
9
Хотя я согласен, что, вероятно, это должен быть принятый ответ (и я бы, конечно, не обиделся, если бы OP изменил его, наоборот), говоря, что мой ответ неправильный, неправильный: он верен для версий, доступных в то время вопрос и ответ был произведен. Итак, пользователи, которых вы не должны беспокоить, читая после первого ответа, а также оценивая ответы на основе их временных меток, никогда не получат наилучшей помощи ...
Бруно,
1
Извини, Бруно, без обид.
Джон Харт
120

РЕДАКТИРОВАТЬ: хотя в настоящее время это принятый ответ, читатели могут найти этот другой ответ пользователя Джона Харта более адаптированным к своим потребностям. Он использует опцию, которая, по словам пользователя Кена , была представлена ​​в версии 7.21.3 ( выпущенной в декабре 2010 года , то есть после этого первоначального ответа).


В отредактированном вопросе вы используете URL-адрес в качестве имени хоста, тогда как это должно быть только имя хоста.

Пытаться:

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

где project1.loc- это просто имя хоста, а 127.0.0.1- целевой IP-адрес.

(Если вы используете завиток из библиотеки , а не в командной строке, убедитесь , что вы не ставите http://в Hostзаголовке) .

Bruno
источник
1
Я получаю 400 ошибок с PHP, и когда я вручную делаю запрос с помощью curl.exe, я получаю индекс сервера по умолчанию, что означает, что он не соблюдает HOSTзаголовок.
Xeoncross
Я пробовал его на разных серверах с виртуальными хостами, и он работает (из командной строки). Старайтесь Hostне на HOSTвсякий случай (хотя я думаю, что регистр не должен учитываться). Как я уже сказал, убедитесь, что вы используете только имя хоста в Hostзаголовке, ничего больше (нет http://и нет /somethingпосле). Как вы настроили файл hosts?
Бруно
Ниже размещены дополнительные данные о результатах этого.
Xeoncross
1
Как сказал Бруно ниже, проблема, вероятно, связана только с конфигурацией моего сервера, поскольку запрос, похоже, делает это и получает ошибку 403.
Xeoncross
Я пропустил "127.0.0.1 myvirtualhost.localhost" в файле hosts, отсюда и проблема.
Arvind K.
2

Либо используйте настоящее полное доменное имя (например dev.yourdomain.com), указывающее на него, 127.0.0.1либо попробуйте отредактировать соответствующий файл hosts (обычно / etc / hosts в средах * nix).

Oli
источник
Я разрабатываю на Windows с помощьюsystem32/drivers/etc/hosts
Xeoncross
Вы используете встроенную сборку cURL или кросс-сборку cygwin? Я говорю это, потому что не знаю, как каждый из них разрешает свой DNS. Собственный должен выбрать из файла hosts Windows, но для версии cygwin может потребоваться версия cygwin. В любом случае использование реального домена, указывающего на 127.0.0.1, будет работать независимо от настроек.
Оли
Я использую встроенную сборку Windows, включенную в PHP 5.3 для Windows (работает как php_fastcgi).
Xeoncross
2

Похоже, это не редкость.

Сначала проверьте это .

Если это не поможет, вы можете установить локальный DNS-сервер в Windows, например этот . Настройте Windows на использование localhost в качестве DNS-сервера. Этот сервер можно настроить так, чтобы он был авторитетным для любых фальшивых доменов, которые вам нужны, и для пересылки запросов на реальные DNS-серверы для всех других запросов.

Я лично считаю, что это перебор, и я не понимаю, почему файл hosts не работает. Но это должно решить вашу проблему. Убедитесь, что вы также настроили обычные DNS-серверы в качестве серверов пересылки.

Matt
источник
Не могли бы вы прочитать свой ответ и переписать его? Английский в третьей строке не имеет смысла!
OmarOthman 02
Прибрано. Ну и дела, я напечатал это слишком быстро, не прочитав как следует.
Мэтт
1

Действительно ли сервер получает запросы и правильно ли вы обрабатываете имя хоста (псевдоним)?

после добавления в мой файл .hosts

Проверьте журнал своего веб-сервера, чтобы узнать, как поступил запрос ...

curl имеет параметры для сброса отправленного запроса и полученного ответа, это называется трассировкой, которая будет сохранена в файл.

--trace

Если вам не хватает информации о хосте или заголовке - вы можете принудительно использовать эти заголовки с помощью параметра конфигурации.

Я бы получил запрос curl, работающий в командной строке, а затем попытался бы реализовать на PHP.

опция конфигурации

-K / - конфигурации

параметры, относящиеся к curl, находятся здесь

--trace Включает полный дамп трассировки всех входящих и исходящих данных, включая описательную информацию, в указанный выходной файл. Используйте «-» в качестве имени файла, чтобы вывод был отправлен на стандартный вывод.

      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 Укажите, из какого файла конфигурации читать аргументы curl. Файл конфигурации - это текстовый файл, в который могут быть записаны аргументы командной строки, которые затем будут использоваться, как если бы они были записаны в самой командной строке. Параметры и их параметры должны быть указаны в одной строке файла конфигурации, разделенные пробелом, двоеточием, знаком равенства или любой их комбинацией (однако предпочтительным разделителем является знак равенства). Если параметр должен содержать пробелы, параметр должен быть заключен в кавычки. В двойных кавычках доступны следующие escape-последовательности: \, \ ", \ t, \ n, \ r и \ v. Обратная косая черта перед любой другой буквой игнорируется. Если первый столбец в строке конфигурации - '#' символ, остальная часть строки будет рассматриваться как комментарий.

      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.
Джордж Ламберт
источник
Опять же, я использую PHP в Windows для получения страницы на виртуальном хосте в тех же окнах, где запущен nginx. В любом случае, я сделал запрос к vhost, http://domain.loc/users/getSettings.xmlи это то, что показал access.log 127.0.0.1 - - [09/Aug/2010:11:42:55 -0500] "POST /users/getSettings.xml HTTP/1.1" 499 0 "-" "-"и сообщил curl. Operation timed out after 10000 milliseconds with 0 bytes received Итак, я предполагаю, что cURL фактически обрабатывает vhost, поскольку access.log показывает запрос. С другой стороны, теперь он может попасть в правильный домен ...
Xeoncross
«499 0» в этой строке ОЧЕНЬ значимо. Процесс вернул нулевые байты - которых ждал curl. и вернул HTTP 499 - странный результат. вызовите другой скрипт, который возвращает статическую строку в ответ на сообщение, и убедитесь, что вы получаете ответ в curl. Многие не публикуют данные, как вы ожидаете ... и сценарий может ожидать ответа. также измените сценарий, чтобы записать ввод во временный файл и увидеть, что вы «получаете ожидаемое сообщение от вашего запроса curl»
Джордж Ламберт,
Добавьте, вы пробовали curl из командной строки - чтобы вы могли контролировать сообщение и видеть ответ сервера?
Джордж Ламберт,
Быстрый ответ на второй вопрос - нет. Я не знаю, как получить доступ к cURL командной строки в Windows, поскольку он встроен в PHP, а не в терминал Windows.
Xeoncross
1
вы можете скачать версию curl для Windows для командной строки отсюда curl.haxx.se/download.html
Джордж Ламберт,
1

Делая запрос

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

Результатом является -Hфайл журнала, содержащий:

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

Файл моих хостов выглядит так:

# 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
источник
1
-Hпредназначен для полного заголовка, а не только для хоста, поэтому используйте -H 'Host: project1.loc'. Кроме того, несмотря на эту проблему, этот запрос, похоже, работает на правильном хосте ( hostsпо крайней мере, правильно получен из вашего файла с помощью curl в командной строке). То, что не работает (403), похоже на проблему аутентификации / авторизации, поэтому ваш сервер, похоже, блокирует эти запросы. Я бы посоветовал исправить для этого конфигурацию сервера.
Бруно
0

Для настройки виртуальных хостов на http-серверах Apache, которые еще не подключены через DNS, мне нравится использовать:

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

Где host-name - это IP-адрес или DNS-имя машины, на которой работает веб-сервер. Это также хорошо работает для https-сайтов.

effhaa
источник
1
Этот пост был отправлен 10 лет назад и исправлен с помощью комментариев, спасибо за вклад. В таких сообщениях, пожалуйста, проверьте ответы, если есть предложение отправить голосование, иначе отправьте новый ответ, потому что вы можете пометить его как спам.
самухай