Автореферат
Библиотека
Ссылки
Отчет о поиске
Роликовый спорт
Автобиография
Автореферат Библиотека Ссылки Отчет о поиске Роликовый спорт

Гошко Владислав Викторович

Донецкий национальный технический университет

Факультет: вычислительной техники и информатики

Специальность: экономическая кибернетика

Тема выпускной работы: Маркетинговый анализ средств защиты от спама

Руководитель: Костин Валерий Иванович

Гошко В.В.

Полезные свойства HTTP заголовка.


Давайте разберемся, что такое header и cookie, начнем с первого. Например, вы набрали в строке броузера адрес http://www.somesite.com при этом сервер возвращает какой-нибудь результат:

HTTP/1.0 200 OK
Date: Sat, 27 Jul 2002 14:48:29 GMT
Server: Apache 1.3.1
Expires: Sat, 27 Jul 2002 14:48:29 GMT
Content-Legnth: 132
Content-type: text/html

<html>
<head>
<title>Somesite.com</title>
</head>
<body bgcolor=#ffffff>
<h1>Somesite.com welcomes you !</h1>
</body>
</html>

В данном случае все до Content-type: text/html\n\n и включая его - это заголовок страницы (header), два пропуска строки обязательны, от этого заголовка будет зависеть как выглядит страница, но самого Content-type: text/html\n\n, мы не увидим, равносильно как и другие параметры заголовка даже если они не существуют.

Также в заголовке прописываються cookie. Синтаксис не особо сложен, давайте его разберем.

Такой формат строки должен возвращать CGI скрипт (как и выше), в header HTTP документа, который будет сохранен и использован позже:

Set-Cookie: NAME=VALUE; expires=DATE;
path=PATH; domain=DOMAIN_NAME; secure

NAME=VALUE

Эта строка представляет собой последовательность символов, исключая точку с запятой, запятую, и пробел. Если нужно поместить какие-нибудь данные в NAME или в VALUE, то рекомендуется кодирование стиля %XX (шестнадцатиричное кодирование символов), хотя кодирование не обязательно.

Это единственный обязательный аттрибут в заголовке Set-Cookie.

expires=DATE

Аттрибут параметра EXPIRES (c англ. Истекать, заканчиваться) задает дату которая обазначет “время жизни” этого cookie. Как только дата была достигнута больше невозможно будет получить значение cookie.

Формат строки даты:

Wdy, DD-Mon-YYYY HH:MM:SS GMT

Он основан на RFC 822, RFC 850, RFC 1036, RFC 1123, с изменениями на то, что должна быть использована только легальная GMT (Greenwich Mean Time) зона с раздилителями элементов даты в качестве тире. (Все RFC здесь - http://ds.internic.net/rfc/rfc822.txt, и так далее)

EXPIRES это необязательный параметр. Если он не указан, то cookie хранится ТОЛЬКО в заголовке страницы, и поэтому «исчезает» после того как пользователь закрыл страницу. (как говорят создать cookie на одну сессию)

domain=DOMAIN_NAME

Когда ищется cookie, идет сопаставленние аттрибута domain из cookie с domain хоста с которого будет извлечена ссылка. Если хвост совпадает тогда cookie идет через весь path, чтобы знать, куда отправлять. Совпадение хвоста значит, что все адреса вышего уровня будут совпадать: domain=vasya.com, то все остальные тоже будут совпадать, например domain=another.vasya.com

Ставить cookie могут только домены, которые имеют как минимум две или три точки, чтобы предотвратить домены таких форм как: “.com”, “.edu”, “va.us”.

По умолчанию значение domain это имя хоста, который сгенерировал cookie.

path=PATH

Аттрибут path используется для более точного определения, т.е. для какого документа было поставлено cookie. Например если domain=vasya.com и path=/docs то cookie применимо для всех файлов директории docs на сайте vasya.com

Если path не указан тогда аттрибутом будет документ в заголовке, которого был описан cookie.

secure

Если cookie отмечен как secure, то он будет передан только по безопасному соединению, т. е HTTPS (Secure Socket Layer), а если же нет, то он будет передан по любым каналам.

Также в заголовке документа я советую использовать ниже приведенные параметры:

use CGI;
$query = new CGI;
print $query->header(-EXPIRES => “+0s”,
-PRAGMA => “no-cache”,
-CACHE_CONTROL => “no-cache”);

Таким образом, документ не будет кешироваться у клиента. Также можно ставить cookie:

$cookie = $query->cookie(-NAME => “Test”,
-VALUE => “Successful”,
-EXPIRES => “+2h”);

Значение EXPIRES может быть такое:

+15s, +30m, +2h, +4d, +1m, +1y, -40m (!)

s – seconds, m – minutes, h – hours, d – days, m – months, y – years, чтобы сделать cookie на одну сессию не следует указывать параметр EXPIRES в $query->cookie().

print $query->header(-EXPIRES => “+0s”,
-PRAGMA => “no-cache”,
-CACHE_CONTROL => “no-cache”,
-COOKIE => $cookie);

Если несколько cookie, тогда так –COOKIE => [$cookie1, $cookie2]. Только не путайте EXPIRES документа и EXPIRES cookie – для каждого это может иметь свое значение.

Конечно, как я говорил выше можно написать по-другому:

print “Content-type: text/html\n”;
print “Pragma: no-cache\n”; #для HTTP/1.0 клиентов
print “Cache-control: no-cache”; #для HTTP/1.1
print “Expires: Sat, 27 Jul 2002 14:48:29 GMT ”; # для других

И т.д.

Удаляем cookie просто установив «минусовую» дату (!), или же можно обнулить значение.

Cookie также можно создавать на JavaScript’e, но только они могут поддерживаться если разрешен JavaScript на вашем браузере Вот все эти скрипты:

function getCookieVal (offset) {
var endstr = document.cookie.indexOf (";", offset);
if (endstr == -1)
endstr = document.cookie.length;
return unescape(document.cookie.substring(offset, endstr));
}

function GetCookie (name) {
var arg = name + "=";
var alen = arg.length;
var clen = document.cookie.length;
var i = 0;
while (i < clen) {
var j = i + alen;
if (document.cookie.substring(i, j) == arg)
return getCookieVal (j);
i = document.cookie.indexOf(" ", i) + 1;
if (i == 0)
break;
}
return null;
}

function SetCookie (name, value) {
var argv = SetCookie.arguments;
var argc = SetCookie.arguments.length;
var expires = (argc > 2) ? argv[2] : null;
var path = (argc > 3) ? argv[3] : null;
var domain = (argc > 4) ? argv[4] : null;
var secure = (argc > 5) ? argv[5] : false;
document.cookie = name + "=" + escape (value) +
((expires == null) ? "" : ("; expires=" + expires.toGMTString())) +
((path == null) ? "" : ("; path=" + path)) +
((domain == null) ? "" : ("; domain=" + domain)) +
((secure == true) ? "; secure" : "");
}

Cтавиться cookie так:

var pathname = location.pathname;
var myDomain = pathname.substring(0,pathname.lastIndexOf('/')) +'/';
var largeExpDate = new Date ();
largeExpDate.setTime(largeExpDate.getTime() + (365 * 24 * 3600 * 1000));
SetCookie('nick','r3d_Dr4g0n',largeExpDate,myDomain);

Получаем значение этого cookie так:

var nick = GetCookie('nick');

Удаляем cookie так:

function deleteCookie(name, path, domain){ if (getCookie(name)){ document.cookie = name + "=" + ((path) ? "; path=" + path : "") + ((domain) ? "; domain=" + domain : "") + "; expires=Thu, 01-Jan-70 00:00:01 GMT" } }

Также в заголовке можно задавать статус документа, перемещен он или нет и т.д. Сейчас рамотрим все статусы, которые были извлечены из status.pm, я думаю, что на английском языке они будут смотреться коректнее:

ОписаниеСтатус
Continue100
Switching Protocols101
OK200
Created201
Accepted202
Non-Authoritative Information203
No Content204
Reset Content205
Partial Content206
Multiple Choices300
Moved Permanently301
Found302
See Other303
Not Modified304
Use Proxy305
Temporary Redirect307
Bad Request400
Unauthorized401
Payment Required402
Forbidden403
Not Found404
Method Not Allowed405
Not Acceptable406
Proxy Authentication Required407
Request Timeout408
Conflict409
Gone410
Length Required411
Precondition Failed412
Request Entity Too Large413
Request-URI Too Large414
Unsupported Media Type415
Request Range Not Satisfiable416
Expectation Failed417
Internal Server Error500
Not Implemented501
Bad Gateway502
Service Unavailable503
Gateway Timeout504
HTTP Version Not Supported505

Т.е документ можно переместить не хитрым параметром:

print "Status: 302\n";
# Или 301. Разница в том, что по стандарту 301 значит "перемещён навсегда", а 302 - "перемещён временно"
print "Location: http://127.0.0.1\n"; # URL абсолютный
print "URI: http://127.0.0.1\n\n"; # Для http/1.0

Но зачем изобретать колесо.…Есть такой замечательный метод в CGI.pm как:

$query->redirect(“http://127.0.0.1”);

Который делает все сам…

И вот несколько программ для «выгребания» header’ов, content’а и status’a:

#!/usr/bin/perl

use IO::Socket;

## get_header.pl by r3d_Dr4g0n v1.0 Alpha
###### gets HTTP header, content and status
## usage : get_content/get_header/get_status
## example#1 : print get_header("http://127.0.0.1/cgi-bin/main.pl?page=articlez"); #- gets header
## example#2 : print get_content("http://127.0.0.1"); #- gets index file
## example#3 : print get_status("http://127.0.0.1"); #- gets status

sub check_ip{
my $address = shift;
$address =~ s/http\:\/\///ig;
my $die = 0;
my(@adr,@spl,$ip,$doc);
@adr = split(/\//,$address,2);
@spl = split(/\./,$adr[0]);
if($adr[0] =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/){
for($i=0;$i<=$#spl;$i++){
if(!(($spl[$i] <= 255) and ($spl[$i] >= 0))){
$die = 1;
}
}
}elsif($adr[0] !~ /^[A-Za-z0-9-.]+$/i){
$die = 1;
}
die "Error : address isn't correct !" if $die;
$ip = $adr[0];
$doc = $adr[1];
return $ip,$doc;
}

sub get_{
my($type,$addr) = @_;
($addr,$doc) = check_ip($addr);
my $crlf = "\x0D\x0A";
my($socket,$url,$str,$st);$st=0;
$socket = IO::Socket::INET->new(PeerAddr => $addr,
PeerPort => "80",
Type => SOCK_STREAM,
Proto => "tcp") or die "Connect failed : $@";
#$url = "$type /$doc $crlf HTTP/1.0$crlf$crlf";
#for Small HTTP Server :-)
if($type eq "STATUS"){
$type = "HEAD";$st=1;
}
$url = "$type /$doc HTTP/1.0\n".$crlf;
print $socket "$url";
while(<$socket>){
$str .= $_;
}
close($socket);
@data = split(/$crlf$crlf/,$str,2);
#--- status
@head = split(/$crlf/,$data[0]);
@stat = split(/ /,$head[0],2);
if($st){
return $stat[1];
}elsif($type eq "GET"){
return $data[1];
}
return $data[0];
}

sub get_content{
my $addr = shift;
return get_("GET",$addr);
}

sub get_header{
my $addr = shift;
return get_("HEAD",$addr);
}

sub get_status{
my $addr = shift;
return get_("STATUS",$addr);
}

1;

Еще этот файл можно использовать так:

#!/usr/bin/perl

require "get_header.pl";

print get_header("http://127.0.0.1/cgi-bin/somescript.pl");

Как вы поняли get_header() – выбирает заголовок старницы, get_content() – содержание, а get_status() – статус, как все просто, не правда ли?

Также процедуру get_status можно использовать как определение «жива» ли ссылка, таким образом:

@links = (“http://www.vasya.com”, “http://www.vasya.ru”);

for($i=0;$i<=$#links;$i++){
if(get_status($links[$i]) =~ /200/){
print “Link $links[$i] – is alive\n”;
}else{
print “Link $links[$i] – isn’t alive\n”;
}
}

Конечно, можно использовать модуль LWP, но если вы не уверены, что он стоит на сервере, или просто не хотите его подключать, то конечно лучше, чтоб все было в одном файле...