Почему Request [ "host" ] == "dev.testhost.com:1234", тогда как Request.Url.Host == "localhost"
Привет всем, я, кажется, обнаружил несоответствие при локальном тестировании приложений ASP.NET на встроенном веб-сервере с Visual Studio 2008 (Cassini).
Я установил хост на локальном компьютере, связывающем dev.testhost.com с 127.0.0.1, так как у меня есть приложение, которое должно изменить его внешний вид в зависимости от заголовка хоста, используемого для его вызова.
Однако, когда я запрашиваю свое тестовое приложение с помощью http://dev.testhost.com:1234/index.aspx
, значение Request.Url.Host
всегда "localhost"
. В то время как значение Request.Headers["host"]
равно "dev.testhost.com:1234"
(как и я ожидал, что оба они будут).
Я НЕ обеспокоен тем, что второе значение включает номер порта,, но я могу смущен тем, что ИМЯ ХОЗЯЙСТВА совершенно разные! Кто-нибудь знает, является ли это известной проблемой или по дизайну? Или я идиот?!
Я бы предпочел использовать Request.Url.Host
, так как это позволяет избежать выделения номера порта при тестировании... - Удалено из-за возможной путаницы! - Сэм
Ответы
Ответ 1
Request.Headers["host"]
- это значение, полученное от приложения, которое подключается к серверу, а другое значение - тот, который получает сервер, когда он пытается получить доменное имя.
Браузер использует в запросе имя домена, введенное, поскольку оно используется в случае виртуальных доменов. Сервер сообщает о том, что задано в настройках сервера, или о первом найденном.
РЕДАКТИРОВАТЬ: Глядя на код Cassini, чтобы узнать, использует ли он какие-то определенные настройки, я заметил следующий код:
public string RootUrl {
get {
if (_port != 80) {
return "http://localhost:" + _port + _virtualPath;
}
else {
return "http://localhost" + _virtualPath;
}
}
}
//
// Socket listening
//
public void Start() {
try {
_socket = CreateSocketBindAndListen(AddressFamily.InterNetwork, IPAddress.Loopback, _port);
}
catch {
_socket = CreateSocketBindAndListen(AddressFamily.InterNetworkV6, IPAddress.IPv6Loopback, _port);
}
// …
}
Объяснение похоже, что Cassini делает явную ссылку на localhost и не пытается сделать обратный поиск DNS. Иными словами, он не будет использовать return "http://localhost" + _virtualPath;
.
Ответ 2
Request.Headers["host"]
- это хост, указанный в заголовке http из браузера. (например, это то, что вы увидите, если бы вы исследовали трафик с помощью Fiddler или HttpWatch)
Однако ASP.NET обрабатывает эту (и другую информацию запроса) в экземпляр System.Uri
, который анализирует строку запроса на ее составные части. В этом случае "Хост" означает буквально часть главной машины исходного запроса (например, с портом tcp, находящимся в порте).
Этот класс System.Uri
- очень полезный вспомогательный класс, который отнимает всю боль от разделения вашего запроса на его части, тогда как "Host:" (и, самое главное, "GET" ) из HTTP-заголовка просто необработанные данные запроса.
Хотя оба они имеют одно и то же имя, они не должны быть одинаковыми.
Ответ 3
Это вопрос о том, что спецификации w3 говорят о том, что Microsoft Uri.Host должно содержать. Именование не подразумевает попытки MS предоставить идентичную функциональность. Функция, которая включает номера портов, Uri.Authority.
С обновлением, которое вы опубликовали, вы все еще сталкиваетесь с одной и той же проблемой, просто исследуя другой аспект этого. свойство Uri.Host не является явно выраженной или подразумеваемой для выполнения той же функции, что и заголовки, определенные в спецификациях w3. В длинной форме, вот некоторые цитаты из страницы UDN.Host:
Свойство Uri.Host
Получает компонент хоста этого экземпляра.
Значение свойства
Тип: System.String
Строка, содержащая имя хоста. Обычно это имя хоста DNS или IP-адрес сервера.
Нет никакой гарантии, что это будет соответствовать тому, что находится в заголовках, просто, что оно представляет имя хоста в той или иной форме.