Поиск по этому блогу

четверг, 16 июня 2011 г.

Создание простого CGI приложения на Delphi 2007 (POST, GET, Cookie)

Simple app, создание, получение POST, GET запросов, куков



Файл >> New >> Other >> WebBroker >> Web Server Application
Создаем действие, на которое будет реагировать наше приложение (Action)
В окне свойств Web модуля

Перед нами появляется окно, в котором необходимо добавить новое действие и определить его свойство PathInfo







В нашем случае приложение будет реагировать на запрос /echo (свойство PathInfo)
т.е. URL для запуска cgi и обработки запроса /echo должен выглядеть так:
http://10.0.0.27:8081/cgi/firstcgi.exe/echo
Сам обработчик вешаем на событие OnActions
procedure TWebModule2.WebModule2WebActionItem1Action(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
В обработчик события передается два важных объекта:
Request: TWebRequest; - это то что мы получаем
его свойства
RemoteAddr - IP клиента
Referer - URL адрес с которого пришел клиент
Данные о GET запросе
Хранятся в списке Request.QueryFields (TStrings)
К данным можно обращаться по их номеру QueryFields[номер параметра]
или по имени QueryFields.Values['Имя параметра']

Данные о POST запросе
Хранятся в списке Request.ContentFields (TStrings)
их значения можно получить аналогично ContentFields[номер параметра], ContentFields.Values[Имя параметра])

Данные о Cookie
Хранятся в списке Request.CookieFields
получение их значений также аналогично вышеперечисленным параметрам

Response: TWebResponse - то, что мы отправим серверу
Наиболее важные свойства
Response.ContentType тип ответа
Response.Content - содержимое нашего ответа серверу

Еще один важный метод - Response.SendRedirect - он позволяет перенаправить пользователя на другую страницу, входящим параметром для этого метода является URL на ту страницу, на которую необходимо перенаправить клиента.

Теперь собственно listing
procedure TWebModule2.WebModule2WebActionItem1Action(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
 RespStr: TStringList;
 i: integer;
begin

 RespStr := TStringList.Create;
 // формируем нашу страничку
 RespStr.Add('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//RU">');
 RespStr.Add('');
 RespStr.Add('<html>');
 RespStr.Add('<head>');
 RespStr.Add('<title>Тестовый пример кодировка windows-1251</title>');
 RespStr.Add('<meta http-equiv="content-type" content="text/html; charset=windows-1251">');
 RespStr.Add('<meta name="resourse-type" content="document">');
 RespStr.Add('</head>');
 RespStr.Add('<body>');
 RespStr.Add('Тестовое приложение');

 RespStr.Add('<br>');
 RespStr.Add('Ваш IP ' + Request.RemoteAddr);

 RespStr.Add('<br>');
 RespStr.Add('Вы пришли отсюда ' + Request.Referer);

 RespStr.Add('<br>');
 RespStr.Add('Accept ' + Request.Accept);

 // данные о Get
 RespStr.Add('<br>');
 RespStr.Add('Get запрос  (QueryFields)');
 if Request.QueryFields.Count <> 0 then
 begin
   for I := 0 to Request.QueryFields.Count - 1 do
    RespStr.Add('<br>' + inttostr(i) + ' ' +
    Request.QueryFields[i]);
 end else RespStr.Add(' пусто ');

 RespStr.Add('<br>');
 RespStr.Add('POST запрос (ContentFields)');
 RespStr.Add('<br>' + ' ContentEncoding: ' + Request.ContentEncoding);
 RespStr.Add('<br>' + ' ContentType: ' + Request.ContentType);
 RespStr.Add('<br>' + ' ContentLength: ' + inttostr(Request.ContentLength));
// POST
 if Request.ContentFields.Count <> 0 then
 begin
   for I := 0 to Request.ContentFields.Count - 1 do
    RespStr.Add('<br>' + inttostr(i) + ' ' +
    Request.ContentFields[i]);

    // получить значение поля по его имени
    if (Request.ContentFields.Values['data']) <> '' then
      RespStr.Add('<br>' + 'Это данные поля "data" ' +
     Request.ContentFields.Values['data'])
     else
     RespStr.Add('<br>' + 'Sorry, такого поля нет');

 end;
// Куки
 RespStr.Add('<br>');
 RespStr.Add('Куки (CookieFields)'); 
 if Request.CookieFields.Count <> 0 then
 begin
   for I := 0 to Request.CookieFields.Count - 1 do
    RespStr.Add('<br>' + inttostr(i) + ' ' +
    Request.CookieFields[i]);
 end;
 try
 // закрываем теги
 RespStr.Add('</body>');
 RespStr.Add('</html>');
 Response.ContentType := 'text/html; charset=windows-1251';
 Response.Content := RespStr.Text;
 // а так мы можем перенаправить клиента на другую страницу
 if Request.ContentFields.Values['nextpage'] <> '' then
   Response.SendRedirect(Request.ContentFields.Values['nextpage']);
 // ставим куку
 CookieExample('cook2=test', Response);
 Handled := true;
 finally
   RespStr.Free;
 end;
end;

Небольшие пояснения к коду.
В первой части мы просто формируем нашу страничку
Далее последовательно получаем информацию о клиенте (IP адрес), с какого URL'а он к нам пришел...
Разбираем GET запрос, POST запрос, выводим данные о куках
Если на форме запроса было заполнено поле 'nextpage', то перенаправляем клиента на эту страничку
Ставим куку  CookieExample('cook2=test', Response);
В заключении отправляем наш ответ клиенту  Handled := true;

О куках.
Для того, чтобы поставить куку достаточно выполнить метод SetCookieField. Каждая кука, все  тот же список параметр=значение. Метод принимает пять параметров:
1. Список куков в виде параметр=значение (TStrings)
2. ADomain - домен, на котором выставляем cookie
3. APath - какому URL выставляем куку
4. AExpires типа TDateTime - срок годности куки, можно указать -1, это означает, что кука будет сброшена только после перезапуска браузера
5. ASecure - если это свойство определить в true, то кука будет выставляться только в том случае, когда доступно безопасное соединение.

Саму процедуру выставления кук я вынесла в отдельную процедуру:
// ставим куку
procedure TWebModule2.CookieExample(cookstr: string; Response: TWebResponse);
var
 cook_slist: TStringList;
begin
 cook_slist := TStringList.Create;
 try
   cook_slist.Append('Cookie1=Первая'); // просто добавляем в список произвольную куку.
   cook_slist.Append(cookstr); // еще одна
 Response.SetCookieField(
 cook_slist,  // список куков параметр=значение
 '',          // domain we are setting the cookie for
 '',      // parameter is the path если его не указывать - будет использовн текущий путь
 -1,      // AExpires: TDateTime - срок годности куки, если указать -1, то неограничено        
 False);  // если true, то устанавливается только тогда когда доступно безопасное соединение
 finally
  cook_slist.Free;
 end;
end;
ее использование
 CookieExample('cook2=test', Response);
Для тестирования этого примера необходимо создать inputwin.html страницу с кодом:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//RU">
<html>
 <head>
  <title>Русская кодировка</title>
  <meta http-equiv="content-type" content="text/html; charset=windows-1251"> 
  <meta name="resourse-type" content="document">
 </head>
<body>
 <FORM ACTION="http://10.0.0.27:8081/cgi/firstcgi.exe/echo"
 METHOD="POST">
<DIV>Введите данные:<BR>
<INPUT NAME="data" SIZE="60" MAXLENGTH="80"><BR>
<INPUT NAME="nextpage" SIZE="60" MAXLENGTH="80"><BR>
<INPUT TYPE="SUBMIT" VALUE="Send"></DIV>
</FORM>
</body>
</html>

Скомпилировать CGI приложения и поместить его в директорию cgi
\\10.0.0.27\www\cgi\firstcgi.exe
саму страничку поместить в корень
\\10.0.0.27\www\inputwin.html

в поле nextpage мы можем набрать URL, при этом firstcgi приложение перенаправит нас по тому адресу, который мы указали

Чтобы посмотреть информацию о куках надо, не выходя из браузера, пару раз запустить
http://10.0.0.27:8081/inputwin.html страничку. В первый раз приложение выставит куку, при повторном запуске - прочитает ее.