уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

с библиотекой Synapse я знаком достаточно давно и, вроде бы, никаких особых серьезных претензий к Synapse нет. Но, тем не менее, чего-то да не хватает. Например, не хватает автоматического редиректа при получении 301 или 302 кода, хотелось бы получить более удобную (для меня) работу с заголовками и т.д. и т.п. Снизить, так сказать, затраты времени на написание программ, использующих Synapse. Я решил для этих целей использовать свой class helper.

Во-первых, поработаем немного с заголовками. В Synapse все заголовки хранятся в виде списка TStringList. Вполне удобно, если бы не одно «НО». Но иногда часто необходимо знать:
1. Какие заголовки (названия заголовков) вообще пришли нам
2. Определить какое значение содержит тот или иной заголовок, например, HTTP-заголовок «Location».
Поэтому, начнем именно с этого — работа с заголовками.
Запускаем Delphi 2010 или Delphi XE, создаем приложение (с помощью него будем тестить хэлпер) — я буду использовать приложение для работы с Google Docs. В uses подключаем модуль httpsend.pas.
Объявляем class helper:

type
 THTTPSend_ = class helper for THTTPSend
 public
   function HeaderNameByIndex(index:integer):string;
   function HeaderByName(const HeaderName:string):string;
 end;

Метод HeaderNameByIndex будет возвращать название заголовка по его индексу, а второй (HeaderByName) — значение заголовка по его имени.

function THTTPSend_.HeaderNameByIndex(index: integer): string;
begin
  if (index>(Headers.Count-1))or(index<0) then Exit;
  Result:=copy(Headers[index],0, pos(':',Headers[index])-1)
end;
 
function THTTPSend_.HeaderByName(const HeaderName: string): string;
var i:integer;
begin
  for i:=0 to Headers.Count-1 do
    begin
      if LowerCase(HeaderNameByIndex(i))=lowercase(HeaderName) then
        begin
          Result:=copy(Headers[i],pos(':',
                       LowerCase(Headers[i]))+2,
                       Length(Headers[i])-length(HeaderName));
          break;
        end;
    end;
end;

Теперь, когда мы можем определить значения заголовков, можно написать новый HTTPMethod, который будет, в случае получения 301 или 302 кода, делать автоматический редирект на необходимый URL:

function THTTPSend_.HTTPMethod(const Method, URL: string): Boolean;
var Heads: TStringList;
    Cooks: TStringList;
    Redirect: string;
    Doc:TMemoryStream;
begin
  try
    Heads:=TStringList.Create;
    Cooks:=TStringList.Create;
    Doc:=TMemoryStream.Create;
    Doc.LoadFromStream(Document);
    Cooks.Assign(Cookies);
    Heads.Assign(Headers);
    Result:=inherited HTTPMethod(Method,URL);
    if (ResultCode=301)or(ResultCode=302) then
      begin
        Redirect:=HeaderByName('location');
        Headers.Assign(Heads);
        Document.Clear;
        Document.LoadFromStream(Doc);
        Cookies.Assign(Cooks);
        Result:=inherited HTTPMethod(Method,Redirect);
       end;
  finally
    FreeAndNil(Heads);
    FreeAndNil(Cooks);
    FreeAndNil(Doc)
  end;
end;

Здесь мы вначале перед отправкой данных на сервер сохраняем значения Cookies, Headers и Document для того, чтобы в случае наличия редиректа не потерять эти данные (они автоматически заменяться на заголовки, куки и html-код перенаправления соответственно). Затем отправляем данные с использованием «родного» HTTPMethod и анализируем результат. Если получили код перенаправления, то определяем значение заголовка location и снова отправляем запрос.
Для бОльшей универсальности необходимо было бы сделать подсчёт редиректов и перенаправлять до тех пор пока не получим код отличный от 3хх, но мне такая универсальность не нужна, а Вы сможете дописать метод в любой момент.

var HTTP: THTTPSend;
begin
try
  HTTP:=THTTPSend.Create;
    if HTTP.HTTPMethod('GET','AnyURL') then
    begin
      Memo1.Lines.Add('-----------------------------');
      Memo1.Lines.Add(HTTP.Headers.Text);
      Memo1.Lines.Add('-----------------------------');
    end

Теперь можете протестировать class helper для Synapse и отправить какой-либо запрос, который 100% возвращает редирект на другую страницу. Я тестировал class helper на работе с Google Docs, а именно на скачивании документа с сервера — httpsend автоматически сделал 1 редирект и загрузил документ. Ну о загрузке гуглодоков и их конвертации в различные форматы мы поговорим позже, а пока можете скачать class helper для Synapse и протестировать его работу в своей программе:

Книжная полка

Описание: Рассмотрены практические вопросы по разработке клиент-серверных приложений в среде Delphi 7 и Delphi 2005 с использованием СУБД MS SQL Server 2000, InterBase и Firebird. Приведена информация о теории построения реляционных баз данных и языке SQL. Освещены вопросы эксплуатации и администрирования СУБД.
купить книгу delphi на ЛитРес
Описание: Рассмотрены малоосвещенные вопросы программирования в Delphi. Описаны методы интеграции VCL и API. Показаны внутренние механизмы VCL и приведены примеры вмешательства в эти механизмы. Рассмотрено использование сокетов в Delphi: различные режимы их работы, особенности для протоколов TCP и UDP и др.
купить книгу delphi на ЛитРес
0 0 голоса
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
2 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии
Sergey
Sergey
04/10/2010 14:45

Посмотрите мою реализацию
http://narod.ru/disk/25641124000/IngHTTPSend.7z.html
Метод GetParamValue по-моему проще, чем ваш HeaderByName, единственное — надо учитывать регистр.

SOAP
SOAP
16/02/2015 03:07

Взамен хелперу необходимо сделать так:

constructor THTTPSend.Create;
begin
inherited;
FHeaders.NameValueSeparator := ':'; // <-- вместо хелпера
end;

А потом читать на здоровье:

Headers.Values['location']