Авторские статьи Простой веб-сервер на Дельфи

Discussion in 'Статьи' started by begin_end, 26 Mar 2007.

  1. begin_end

    begin_end Green member

    Joined:
    4 Jan 2007
    Messages:
    265
    Likes Received:
    638
    Reputations:
    476
    Простой веб-сервер на Дельфи или компонент idHTTPServer, описание и применение.

    Целью данной статьи было описание возможностей и указание примеров использования INDY-компонента idHTTPServer в Дельфи. К статье прилагается прокомментированный исходный код и демонстрационное приложение. Скачать можно здесь.

    Статья рассчитана на читателей, знакомых с технологией Web и освоивших среду разработки приложений Дельфи на начальном уровне. Некоторые термины:
    INDY – Internet Dyrect, набор компонентов для Дельфи, ориентированный преимущественно на работу с сетевыми функциями.
    idHTTPServer – INDY компонент, предназначенный для построения HTTP-сервера.


    Поставленная для разбора задача – ПО «Sample HTTPServer» (или SHTTPS) должно предоставлять следующие возможности: передавать запрошенные страницы, как полноценный веб-сервер; запрашивать пароль на доступ при необходимости; иметь страницу управления.

    Создание основы приложения: формы и её элементов.
    Для выполнения задачи потребуется всего одна форма. И следующие поля ввода на ней: для задания порта, имя пользователя, пароль пользователя, путь к папке проекта и его индексу, название страницы управления, имя администратора, пароль администратора. Также нужны два чекбокса для: вклбчения/выключения авторизации и страницы управления. Для вызова диалога обзора и открытия файлов поставим кнопку. И ещё две: для запуска сервера и для завершения работы приложения. Подписи к элементам управления (Label’ы) ставим по усмотрению.

    Затем положим на форму компонент idHTTPServer, находящийся на вкладке компонентов INDY Servers. Другие, требующиеся нам не визуальные компоненты, это Timer и OpenDialog.

    Программирование приложения.
    Фактически, вся работа будет связана с событием IdHTTPServer1CommandGet ( AThread: TIdPeerThread; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo ). Где нужные нам параметры – ARequestInfo и AResponseInfo.

    Состав структуры ARequestInfo:
    Code:
    TIdHTTPRequestInfo = class(TIdRequestHeaderInfo)
      protected
        FAuthExists: Boolean;
        FCookies: TIdServerCookies;
        FParams: TStrings;
        FPostStream: TStream;
        FRawHTTPCommand: string;
        FRemoteIP: string;
        FSession: TIdHTTPSession;
        FDocument: string;
        FCommand: string;
        FVersion: string;
        FAuthUsername: string;
        FAuthPassword: string;
        FUnparsedParams: string;
        FQueryParams: string;
        FFormParams: string;
        procedure DecodeAndSetParams(const AValue: String);
      public
        constructor Create; override;
        destructor Destroy; override;
        property Session: TIdHTTPSession read FSession;
        property AuthExists: Boolean read FAuthExists;
        property AuthPassword: string read FAuthPassword;
        property AuthUsername: string read FAuthUsername;
        property Command: string read FCommand;
        property Cookies: TIdServerCookies read FCookies;
        property Document: string read FDocument write FDocument    property Params: TStrings read FParams;
        property PostStream: TStream read FPostStream write FPostStream;
        property RawHTTPCommand: string read FRawHTTPCommand;
        property RemoteIP: String read FRemoteIP;
        property UnparsedParams: string read FUnparsedParams write FUnparsedParams; 
        property FormParams: string read FFormParams write FFormParams;    property QueryParams: string read FQueryParams write FQueryParams;    property Version: string read FVersion;
      end;
    Состав структуры AResponseInfo:
    Code:
     TIdHTTPResponseInfo = class(TIdResponseHeaderInfo)
      protected
        FAuthRealm: string;
        FContentType: string;
        FConnection: TIdTCPServerConnection;
        FResponseNo: Integer;
        FCookies: TIdServerCookies;
        FContentStream: TStream;
        FContentText: string;
        FCloseConnection: Boolean;
        FFreeContentStream: Boolean;
        FHeaderHasBeenWritten: Boolean;
        FResponseText: string;
        FSession: TIdHTTPSession;
        FServerSoftware: string;
        procedure ReleaseContentStream;
        procedure SetCookies(const AValue: TIdServerCookies);
        procedure SetHeaders; override;
        procedure SetResponseNo(const AValue: Integer);
        procedure SetCloseConnection(const Value: Boolean);
      public
        procedure CloseSession;
        constructor Create(AConnection: TIdTCPServerConnection); reintroduce;
        destructor Destroy; override;
        procedure Redirect(const AURL: string);
        procedure WriteHeader;
        procedure WriteContent;
        property AuthRealm: string read FAuthRealm write FAuthRealm;
        property CloseConnection: Boolean read FCloseConnection write SetCloseConnection;
        property ContentStream: TStream read FContentStream write FContentStream;
        property ContentText: string read FContentText write FContentText;
        property Cookies: TIdServerCookies read FCookies write SetCookies;
        property FreeContentStream: Boolean read FFreeContentStream write FFreeContentStream;
        property HeaderHasBeenWritten: Boolean read FHeaderHasBeenWritten write FHeaderHasBeenWritten;
        property ResponseNo: Integer read FResponseNo write SetResponseNo;
        property ResponseText: String read FResponseText write FResponseText;
        property ServerSoftware: string read FServerSoftware write FServerSoftware;
        property Session: TIdHTTPSession read FSession;
      end;
    Для того чтобы был запрос ввода пароля, когда нам это нужно, на событие onCommandGet, сразу после описания процедуры (т.е. перед begin) ставим следующее:

    Code:
    procedure AuthFailed;
      begin
        AResponseInfo.AuthRealm :='Авторизация на SHTTPS:';
      end;
    Смотрим: в структуре AResponseInfo AuthRealm предназначен для запроса авторизации с текстом, ему присвоенным.
    Сразу после begin ставим AResponseInfo.Server : = 'версия сервера' ; AResponseInfo . CacheControl : = 'no-cache' ; Это задаст версию сервера и укажет браузеру не кэшировать документы с сервера. Потом проверяем состояние чекбокса для авторизации (нужна/нет). Если нужна, то проверка: (ARequestInfo.AuthUsername <> ‘имя_пользователя’) or (ARequestInfo.AuthPassword <> ‘пароль’). В случае непрохождения её вызов AuthFailed.

    После просто обрабатываем введённый адрес, находящийся в ARequestInfo.Document (см. структуру ARequestInfo). При запросе “/” показываем индексный файл. А при запросе вида “/1/file.htm” отдаём файл 1/file.htm.

    Для передачи файла используем AResponseInfo.ContentStream := TFileStream.Create (‘filename’,fmOpenRead).

    При запросе страницы управления в нашем случае отдаём не файл с диска, а html-код, непосредственно генерирующийся здесь. Потому что нужно получить и показать в полях ввода страницы управления их текущие значения. Страница управления будет похожа видом на форму сервера. Часть её исходного кода шаблонна и будет задана фрагментами в Resourcestring, откуда эти фрагменты будут вставляться в ContentText (AResponseInfo) вперемежку с иными вставками.

    Получается, что в html-странице управления будет форма и поля ввода. При отправке, их значения методом POST будут направлены серверу. Считывать их на сервере можно из структуры ARequestInfo, в которой они есть Params.values. Полностью обращаться: ARequestInfo.Params.Values['имя_элемента'].

    Запуск сервера производится так: idHTTPServer1.DefaultPort := #порта; idHTTPServer1.Active:=true; (Порт указываем именно перед запуском). Для остановки сервера через страницу управления нужен таймер, по которому выполнится Application.Terminate. Напрямую вызвать в ходе IdHTTPServer1CommandGet завершение приложения нельзя, следует делать активным таймер.

    Заключение.
    Для разработки ПО Sample HTTPServer использовалась среда Дельфи 7.0, упаковщик исполняемых файлов UPX 1.95. Весь код данного ПО, кроме автокода модулей Дельфи и структур ARequestInfo, AResponseInfo, взятых из исходного кода SvrHTTPIndy.pas был написан автором.

    Сама статья и ПО были созданы в учебных целях, а также, как основа будующей статьи, посвящённой созданию программы-сервера удалённого администрирования на основе idHTTPServer, без отдельного клиента (управление по http). ПО предложено только для сопровождения статьи и его использование в качестве сервера неактуально, но возможно. Статью (как и исходный код) можно дополнять, переопубликовывать, ссылаясь на первоисточник, при этом критика ожидаема и желательна.

    __________________________
    Думаю важное и нужное дополнение: полезные ссылки по тематике INDY HTTP.

    1. Веб-сервер своими руками
    2. SeverMain.pas
    3. Веб-сервер своими руками (2)
    4. idHttp Server
    5. INDY - Internet Direct (komponenty otwarte)

    Замечу, что в структурах ARequestInfo и AResponseInfo много прочих полезных параметров и создание полноценного веб-сервера на Delphi, применяя INDY действительно возможно и быстро.
     
    _________________________
    #1 begin_end, 26 Mar 2007
    Last edited: 4 Jun 2007
    11 people like this.
  2. 4xks

    4xks Banned

    Joined:
    2 Mar 2007
    Messages:
    9
    Likes Received:
    0
    Reputations:
    -3
    Тоже писал веб серверы на компонентах - нужная вещь - Indy
     
  3. M-K

    M-K New Member

    Joined:
    16 Aug 2007
    Messages:
    3
    Likes Received:
    1
    Reputations:
    1
    Статья шикарная. Но прошу объяснить новичку, для чего может понадобиться создавать руками такой сервер? Примеры хотелось бы... потому что есть ведь Денвер, или Апач. А вот такой самодельный сервер - это наверное более гибко. Но какие варианты применения?
     
  4. Spyder

    Spyder Elder - Старейшина

    Joined:
    9 Oct 2006
    Messages:
    1,388
    Likes Received:
    1,209
    Reputations:
    475
    или mysql...

    мб это круто, сервак на делфи, но чё то я толку не вижу) Ну за старания плюс =\
     
    1 person likes this.
  5. YURBAN

    YURBAN New Member

    Joined:
    31 Oct 2010
    Messages:
    0
    Likes Received:
    0
    Reputations:
    0
    Так говорят те кто вообще ничего не шарит в технологиях!

    Плюсы очевидны: безопасность - всё в одном, можно закодить как тебе удобно а не так как кто-то до тебя сделал!
    Минусы: Apache+PHP+MySQL - скорость, память, безопасность + настройка!
     
  6. Chrome~

    Chrome~ Elder - Старейшина

    Joined:
    13 Dec 2008
    Messages:
    936
    Likes Received:
    162
    Reputations:
    27
    Вообще то чувак правильно написал.
    Но старую ты темку поднял. За 2007 год.
     
  7. dshelyuzhak

    dshelyuzhak Member

    Joined:
    25 Oct 2012
    Messages:
    139
    Likes Received:
    7
    Reputations:
    1
    даже слишком старую статью ты поднял.