Introduction
Почему большое количество Web разработчиков пишут сайты на скриптах, вроде PHP? Я, лично, не понимаю и использую другой способ - ISAPI Extensions for IIS.
ISAPI Extensions (расширения Web сервера) - простая DLL библиотека с парой функций, которые обрабатывают запрос пользователя к Web серверу и возвращают ответ. Точнее - одна функция, остальные служат для регистрации/разрегистрации DLL в рабочем процессе IIS.
Из этого следует, что, по сравнению с другими способами, такими, как скрипты, ISAPI Extensions выигрывают по:
- Скорость работы. DLL загружается в рабочий процесс IIS и находится в памяти всегда, а не читается с диска при каждом обращении. Не требуется интерпретатор языка - код нативный и исполняется непосредственно процессором;
- Функционал. Вы можете использовать любую другую DLL или любой вызов WinAPI. Теоретически возможно специально сформированным http запросом отформатировать диск
- Защищенность. Ваш код очень сложно проанализировать и понять, как взломать сайт - нативный код человеком плохо читается
- У вас есть нормальный отладчик во время разработки! Самый вкусный момент. Можете делать step-by-step trace, стэк и память доступны для анализа.
Есть и некоторые ограничения, как и везде, но их сложно назвать недостатками:
- Требуется IDE для разработки;
- Невозможно просто взять и поправить 2 строчки в скрипте на сервере - требуется пересобрать проект, как любое Windows приложение;
- Вероятность завалить рабочий процесс IIS с ошибкой Acceess violation at address (не бояться, он просто перезапустится);
- Различные security violations, связанные с возможностью делать, что хочешь. Хотя, это уже точно вопрос к админам, как они раздадут права на сервере.
- Ваши друзья - php кодеры вас не поймут и назовут дураком, если вы передадите им такую CMS. Еще они не смогут ее установить :D
Your first ISAPI Entension
Итак, приступим к работе. Я буду использовать Delphi 2010 и IIS 6 под Windows Server 2003 R2 EnUS.
Добрые Борландны, еще много лет назад, упростили процесс работы с ISAPI до предела. Чтобы начать выберем File -> New -> Other и выберите WebBooker -> Web Server Application. Далее кликаете ISAPI/NSAPI Dynamic Link Library и нажмите OK.
Вот и все, ваша первая ISAPI Extension готова. Пока она ничего не возвратит Web серверу конечно, но если ее откомпилировать, то она готова к работе. Компилировать нужно, нажимая не зеленую стрелочку, а Ctrl+F9.
Переключитесь на Unit1 и выберите Action Editor для объекта WebModule1. Об экшенах поговорим в другой раз, пока нужно просто создать default action, который будет обрабатывать все наши запросы.
Приведите внешний вид свойств объекта, как на картинке:
У этого экшена есть события, как вы уже догадались. А точнее - одно. Думаю, без картинки не заблудитесь и поймете, что надо сделать (если что, в конце поста есть ссылка на исходники).
Web Engine Class
Создадим новый класс - TWebEngine в файле WebEngineClass.pas. Он будет у нас отвечать за все манипуляции с данными. Окружение - классы TOptions и TTempVariables. TOptions будет хранить данные о базе (с которой мы будем соединяться в следующий раз), а временные вариаблы - информацию о расположении DLL библиотеки на диске и ее имени.
Сервер Microsoft IIS передает нашей библиотеке множество параметров и хочет, чтобы мы ему что-то вернули после работы. Эти объекты представляются как Request: TWebRequest и Response: TWebResponse, которые прописаны как property класса TWebEngine. Просто передадим их в класс в коде экшена:
try
try
WebEngine.Request:= Request;
WebEngine.Response:= Response;
WebEngine.Process;
finally
WebEngine.Free;
end;
except
on E: Exception do
Response.Content:= 'Internal e
end;
Логика кода, надеюсь, ясна - создать класс, передать параметры, запустить обработку (process) и удалить (free) класс. Если что - выдать ошибку.
Разъясняя код метода (да да, именно метода. Функции и процедуры одним словом называются метод) Process хочу в первую очередь указать на то, как разбирается для нас строка параметров http запроса вида
http://nowhere.com/?pagename=main&langu
все параметры попадают в Request и могут быть оттуда легко получены вот так:
LocalOptions.Language:= Request.QueryFields.Values[ 'language' ];
LocalOptions.TypeOfPage:= Request.QueryFields.Values[ 'pagename' ];
То есть никаких шаманств не требуется, хотя возможны при желании!
Код метода Process устанавливает страницей по умолчанию страницу main с языком EnUS (код 1033) и запускает дальнейшую обработку:
// language
// default language is EnUS
LocalOptions.Language:= 1033; // E
// other languagues
if AnsiSameText( Request.QueryFields.V
LocalOptions.Language:= 1033; // EnU
if AnsiSameText( Request.QueryFields.V
LocalOptions.Language:= 1049; // RuR
// type of page
// dafault is help page
if Length( Request.QueryFields.Values[
LocalOptions.TypeOfPage:= 'help'
else
LocalOptions.TypeOfPage:= Request.Qu
try
try
if LocalOptions.TypeOfPage = 'i
Begin
PageInfoShow;
Exit;
End;
if LocalOptions.TypeOfPage = 'm
Begin
PageMainShow;
Exit;
End;
// common page
PageCommonShow;
except
on E: Exception do
Begin
PageResponse.Clear;
PageResponse.Text:= 'Inter
End;
end;
finally
Send( PageResponse.Text );
end;
Код, в силу красоты языка Delphi, не требует комментариев вообще, если вы конечно знаете хоть немного этот самый EnUS.
Страница info - чудесная страница отладки, если на нее зайти можно посмотреть все переменные, что бзаузер посылает серверу.
Страница help - просто какае-то страница на сервере. Обрабатывается PageCommonShow (остальные страницы привилегированные, у них у каждой свой собственный метод).
Non-ANSI Encoding Problem
Ах, да. Что такое PageResponse? Это не объект сервера IIS, это собственный объект класса ВебДвигателя. Тут я создал лишнюю работу, потому что, вы не поверите, но TWebResponse не умеет возвращать странички в UTF-8 или любой кодировке, кроме ANSI. По этому, пока идет обработка, весь код странички копится в объекте PageResponse типа TStringList (в кодировке UCS2LE) и перекодируется во время вызова Send( PageResponse.Text ). Это - самый главный секрет написания ISAPI Extension на Delphi, теперь и вы его знаете.
Давайте посмотрим код метода Send поближе:
// encoding the string USC2LE -> UT
BufferUTF8String:= UTF8Encode( s )
// setting BOM
BOM[ 0 ]:= 239;
BOM[ 1 ]:= 187;
BOM[ 2 ]:= 191;
try
Stream:= TMemoryStream.Create;
except
on E: Exception do
Begin
LocalOptions.Response.Content:=
Exit;
End;
end;
try
try
// writing BOM
Stream.Write( BOM, SizeOf( BOM ));
// writing content
Stream.Write( BufferUTF8String[ 1
Stream.Position:= 0;
// setting content type
LocalOptions.Response.ContentType:
LocalOptions.response.ContentEncod
// sending
LocalOptions.Response.ContentStrea
LocalOptions.Response.SendResp
finally
// DO NOT Stream.Free here!
end;
except
on E: Exception do
Begin
LocalOptions.Response.Content:=
Exit;
End;
end;
Здесь происходит очень простая вещь - текст перекодируется, записывается в поток и отсылается, как массив байт. Пользователь видит страничку в UTF-8. Магия.
Page Producer
Еще, о чем можно поговорить это TPageProducer. Это замечательный класс, который преобразует тэги вида <#IAmTag> в шаблонах страницы на любой текст. Происходит это в PageProducerOnHTMLTag - вызывается каждый раз при нахождении такого тэга. Для примера я создал тэг #HeaderCopyright, код которого располагается в файле, и тэг #CopyrightYearsRange, который генерируется в самом ISAPI Extension. Посмотрите исходник, не буду останавливаться на этом моменте, он того не стоит.
How To Debug?
Все, с кодом закончили. Самые важные аспекты я осветил, теперь как же запустить это все на отладку? Не как обычное приложение, зеленая кнопка тут бессильна (сперва). Для DLL нужен хост-процесс.
Сперва остановите все службы IIS: net stop IISAdmin в command prompt и Y что вы останавливаете дочерние службы. 
Запустите IISAdmin, без дочерних служб: net start IISAdmin.
В Delphi, в свойствах проекта поставьте папку бинарников - папкой публикации IIS узла, включите debug symbols и вообще сделайте, как на картинках:

В самом IIS, если еще не сделали - страница по умолчанию index.dll, ISAPI Extension разрешить в Web Server Extensions и свойствах конкретного узла.
Теперь, по нажатию зеленой кнопки в Delphi запуститься хост-процесс IIS и заработает отладка. Вот, например, нет файла: 
А вот что видет пользователь: 
Самое вкусное - отладка работает, как в обычном Windows приложении! Всем php разработчикам - завидовать. 
Удачи вам, это все, на первый раз. Далее поговорим о соединении с базой данных из ISAPI Extensions.
Код проекта (Delphi 2010): ISAPI DEMO v1
© SV Foster, 2011. SV@novicorp.com
January 21 2011, 12:19:17 UTC 1 year ago
January 21 2011, 12:24:12 UTC 1 year ago
January 21 2011, 12:24:10 UTC 1 year ago
January 21 2011, 12:50:47 UTC 1 year ago
ЗЫ Но всё же, бесплатный LAMP - это хороший двигатель веб-прогресса :)
January 21 2011, 12:54:53 UTC 1 year ago
Скачайте пример, но полный и поможет лучше понять механизм работы.
Apache тоже поддерживает ISAPI. Только вам придется RTFM что понять, как заставить его это делать.
January 21 2011, 13:13:47 UTC 1 year ago
January 21 2011, 13:25:58 UTC 1 year ago
А так - спасибо за статью.
January 21 2011, 14:16:40 UTC 1 year ago
January 21 2011, 14:46:04 UTC 1 year ago
January 21 2011, 15:39:31 UTC 1 year ago
January 21 2011, 18:24:44 UTC 1 year ago
January 24 2011, 03:47:04 UTC 1 year ago
у способа, правда, главный недостаток в том, что дедикейтед нужен, виртуальный хотя бы. с другой стороны, цены на них щас такие, что там можно даже хомяка держать.
January 24 2011, 10:07:06 UTC 1 year ago
Colocation сейчас начинается от 800 рублей, думаю дешевле купить его. VPS неоправданно дороже.
March 31 2011, 15:08:49 UTC 1 year ago
March 31 2011, 15:24:34 UTC 1 year ago
Anonymous
December 12 2011, 16:01:41 UTC 5 months ago
Can I share it on Facebook?
I want to share it on my Facebok wallYou can find me there as Bark Pacober
February 7 2012, 18:57:11 UTC 3 months ago
February 19 2012, 18:17:09 UTC 3 months ago