Почему этот веб-сервер возвращает код 404 для Indy, но код 200 для каждого браузера?

У меня есть один URL, который прекрасно работает во всех браузерах (5 протестировано на 2 компьютерах), но если я пытаюсь получить содержимое страницы с помощью Get() клиента Indy Http, он возвращает код ошибки 404, страница не найдена. Это с последней сборкой Indy SVN (4985).

Почему этот веб-сервер возвращает код 404 для Indy, но код 200 для каждого браузера?

Я подозреваю, что это может быть ошибка в Indy из-за символа "#" в URL (Indy обрезает все после #). Если так, есть ли способ обойти это. Может заменить символ # на escape-код?

Вот мой пример кода. Все, что для этого нужно, - это Delphi с компонентами Indy, а также форма с кнопкой и памяткой.

procedure TForm1.Button1Click(Sender: TObject);
var HTTPCLIENT1: TIdHTTP;
begin
  try
   try
     HTTPCLIENT1 := TIdHTTP.Create(nil);
     Memo1.Clear;
     with HTTPCLIENT1 do
     begin
          HandleRedirects := True;
          Request.UserAgent   := 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31';
          Memo1.Text := Get('http://www.visionofhumanity.org/gpi-data/#/2011/scor/');
          Caption := ResponseText;
     end;
   except
     On e: Exception do
     begin
          Memo1.Lines.Add('Exception: '+e.Message);
     end;
   end;
  finally
     HTTPCLIENT1.Free;
  end;
end;

2 ответа

Решение

# является зарезервированным символом в URL. Если вы хотите использовать зарезервированные символы внутри URL-адреса, вам необходимо их кодировать по URL. TIdHTTP не делает это для вас. Он требует, чтобы вы передали закодированный URL, но вместо этого вы передаете незашифрованный URL. поскольку # не закодирован, обрабатывается как якорь и удаляется, поэтому вы на самом деле запрашиваете http://www.visionofhumanity.org/gpi-data/ Хенсе 404 ответ.

# URL-кодируется как %23 так что используйте это:

Memo1.Text := Get('http://www.visionofhumanity.org/gpi-data/%23/2011/scor/');

Или это:

Memo1.Text := Get(TIdURI.URLEncode('http://www.visionofhumanity.org/gpi-data/#/2011/scor/'));

Обновление: я разыскал проблему. Это другое TIdURI ошибка разбора, на этот раз связанная с наличием / персонаж после # персонаж. TIdURI проверяет / символов, прежде чем он проверяет на # символ, поэтому якорная часть URL заканчивалась в TIdURI.Path собственность (ранее это заканчивалось в TIdURI.Params собственности) и, таким образом, представлены на сервер. Я проверил новое исправление (SVN rev 4987).

Ваше подозрение верно. Вы включили # раздел адреса в вашем запросе. Браузеры не делают этого, потому что этот раздел зарезервирован для навигации внутри страницы. Сервер не знает об этом, поэтому он пытается извлечь ресурс, который соответствует полному URL, который вы ему дали, включая # и все после. Ничто не соответствует, так что это терпит неудачу со статусом 404.

Либо сделайте так, как это делают браузеры, и удалите этот раздел из URL-адреса перед отправкой запроса на сервер, либо обновите Indy до версии 4987, чтобы это произошло автоматически. Простое спасение персонажа продолжит давать статус 404.

Другие вопросы по тегам