Xiper

Cookies — извлечение

Автор: Андрей Косяк Дата публикации:

В прошлой статье "Cookies — установка" мы «нафаршировали» наш браузер печеньками. Пришло время достать их и выбрать самые вкусные. В этой статье будем разбираться в тонкостях извлечения куков.

Гюльчатай, открой личико!

Собственно, сам процесс получения куков до безобразия прост:

var	cookieStr = document.cookie;
	alert(cookieStr);

Вот и все, спасибо за внимание… :)

Шутка, конечно же. Да, мы получили строку с куками, но загвоздка в том, что таким образом браузер отдает нам абсолютно все куки, установленные текущим ресурсом. А именно, если стояла одна кука, cookieStr будет содержать:

"cookieName=cookieValue;"

Уверен, в таком случае, у тебя проблем возникнуть не должно, потому как задача сводится к извлечению значения куки из строки, при этом, точно зная, что оно находится сразу после символа "=" (другой вопрос, когда содержимое куки содержит перечень значений, такую ситуацию рассмотрим дальше).

А вот если сайтом было установлено несколько кук, то переменная cookieStr несколько изменит свой вид:

"cookieName1=cookieValue; cookieName2=cookieValue; cookieName3=cookieValue;"

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

  • куки необходимо структурировать, отделить друг от друга;
  • найти нужную и изъять её содержимое

Если значение куки, в свою очередь, является также каким-то перечнем данных, то примерно такую же процедуру нужно проделать и с ними:

  • структурировать значения, отделить друг от друга;
  • найти нужное

А теперь детальнее

Вариант с одной кукой рассматривать нет смысла, поэтому сразу ставим задачу по изъятию конкретной куки из нескольких установленных и, соответственно, конкретного значения из нее.

Давай разберем строку с куками на запчасти. Для начала заложим исходные данные:

var	cookieVal1 = escape('первая кука'),
	cookieVal2 = escape('вторая кука'),
	cookieVal3 = escape('часть1 третьей куки; часть2 третьей куки; часть3 третьей куки'),
	cookieVal4 = escape('четвертая кука'),
	cookieVal5 = escape('пятая кука');
// устанавливаем
	document.cookie = 'cookieName1='+cookieVal1+';';
	document.cookie = 'cookieName2='+cookieVal2+';';
	document.cookie = 'cookieName3='+cookieVal3+';';
	document.cookie = 'cookieName4='+cookieVal4+';';
	document.cookie = 'cookieName5='+cookieVal5+';';

Первым этапом, разобьем строку на массив по разделителю ";", элементы которого будут строками и содержать пару ключ=значение:

// разделение куков
var    cookieStr = document.cookie,                  // получаем строку куков
       cookieArray = cookieStr.split(';'),           // вспоминаем о чудесном методе split и разбиваем строку с куками на упорядоченый массив по разделителю ";"
       i, j;
       // удалим пробельные символы (если они, вдруг, есть) в начале и в конце у каждой куки
       for (j=0; j<cookieArray.length; j++) cookieArray[j] = cookieArray[j].replace(/(s*)B(s*)/g, '');

Теперь, нужно обработать (привести к человеческому виду) каждую пару в этом массиве:

var    cookieNameArray = new Array({name: '', value: new Array()});    // результирующий упорядоченный массив
                                                                       // каждый элемент будет объектом с методами name и value
                                                                       // name - имя куки, value - упорядоченный массив значений куки
       // обрабатываем каждую куку
       for (i=0; i<cookieArray.length; i++)
       {
           var    keyValue = cookieArray[i].split('='),               // разделяем имя и значение		
                  cookieVal = unescape(keyValue[1]).split(';');       // разделяем значения, если они заданы перечнем
                  // удаляем пробельные символы  (если они, вдруг, есть) у значений в начале и в конце
                  for (j=0; j<cookieVal.length; j++) cookieVal[j] = cookieVal[j].replace(/(s*)[B*](s*)/g, '');
                  keyValue[0] = keyValue[0].replace(/(s*)[B]*(s*)/g, '');
                  // вот получился такой cookie-объект
                  cookieNameArray[i] = {
                      name: keyValue[0],
                      value: cookieVal
                  };
       };

В результате имеем массив объектов, каждый из которых имеет метод name и value. В name содержится имя куки, value — упорядоченный массив значений куки.

Теперь вспомним, во имя чего мы все это затеяли… Ах, да! Нам необходимо получить значение конкретной куки. Немного "причесав" код, получим вот такую окончательную функцию:

function getCookie(cName){
// разделение куков
var    cookieStr = document.cookie,                  // получаем строку куков
       cookieArray = cookieStr.split(';'),           // вспоминаем о чудесном методе split и разбиваем строку с куками на упорядоченый массив по разделителю ";"
       i, j;
       // удалим пробельные символы (если они, вдруг, есть) в начале и в конце у каждой куки
       for (j=0; j<cookieArray.length; j++) cookieArray[j] = cookieArray[j].replace(/(s*)B(s*)/g, '');
var    cookieNameArray = new Array({name: '', value: new Array()});    // результирующий упорядоченный массив
                                                                       // каждый элемент будет объектом с методами name и value
                                                                       // name - имя куки, value - упорядоченный массив значений куки
       // обрабатываем каждую куку
       for (i=0; i<cookieArray.length; i++)
       {
           var    keyValue = cookieArray[i].split('='),               // разделяем имя и значение		
                  cookieVal = unescape(keyValue[1]).split(';');       // разделяем значения, если они заданы перечнем
                  // удаляем пробельные символы  (если они, вдруг, есть) у значений в начале и в конце
                  for (j=0; j<cookieVal.length; j++) cookieVal[j] = cookieVal[j].replace(/(s*)[B*](s*)/g, '');
                  keyValue[0] = keyValue[0].replace(/(s*)[B]*(s*)/g, '');
                  // вот получился такой cookie-объект
                  cookieNameArray[i] = {
                      name: keyValue[0],
                      value: cookieVal
                  };
       };
    var cookieNALen = cookieNameArray.length;    // размер полученного массива
        // выбираем нужную куку
        if (!cName) return cookieNameArray
            else 
                for (i=0; i<cookieNALen; i++) if (cookieNameArray[i].name == cName) return cookieNameArray[i].value;			
     return false;	
};

Результатом работы функции будет значение (массив значений) заданной куки, иначе, если кука не была найдена, функция вернет false. При вызове функции без параметра cName, функция вернет массив всех куков. Пример вызова с параметром cName:

var    cValue = getCookie('cookieName3');
       alert(cValue);

Без параметра:

var    cValue = getCookie();
       alert(cValue);

Вот, собственно, и все с получением куки. Конечно, ты, возможно, подумал: «Я бы сделал не так.», — несомненно, но данный материал лишь призван наглядно продемонстрировать и разложить по полочкам специфику этого процесса, а как это реализовывать — личное дело каждого разработчика.

Жить или не жить?

Если куку можно установить, значит ее можно и удалить! Да, логика в порядке. А делается это… через установку:

var    cookieExp = new Date();                       // создаем объект Date
       cookieExp.setMonth(cookieExp.getMonth()-1);   // устанавливаем прошлый месяц
       document.cookie = 'myCookie=; expires='+cookieExp.toGMTString()+';';

с той лишь разницей, что для удаления, куке нужно выписать срок жизни «задним числом».

Вывод

Из всех операций с куками, самым трудоемким оказалось их получение, точнее разбор полученных данных, хотя глубина разбора, конечно же, зависит от поставленных задач. К примеру, если сайт ставит одну единственную куку с одним значением, то проще достать ее значение, например при помощи методов объекта String (indexOf(), substr()). Но и иметь в своем арсенале универсальную функции по разбору куков, тоже будет не лишним.

В следующей статье попробуем составить "бабушкин рецепт", чтоб повесить на холодильник и пользоваться ним. Иначе говоря, объединим все операции в один скрипт, дабы в дальнейшем, легко применять его в своих проектах.

Куда дальше