Middleware для сохранения referer url

Часто для плотной работы по продвижению сайта и работе с клиентами требуется знать откуда и по каким запросам приходят на сайт посетители. В django данная задача решается довольно тривиально - с помощью middleware.

Например так:

# -*- coding: utf-8 -*-
from django.conf import settings

class RefererStoreMiddleware(object):
    """Get referring page and store it to the Cookie"""

    def process_request(self, request):
        request.LANKA_REF = None
        if "LANKA_REF" in request.COOKIES:
            request.LANKA_REF = request.COOKIES["LANKA_REF"]
            return
        referer_url = request.META.get("HTTP_REFERER", None)
        if referer_url is not None and referer_url != "" and \
                not self._is_local_domain(referer_url):
            request.LANKA_REF = referer_url

    def process_response(self, request, response):
        if hasattr(request, "LANKA_REF") and request.LANKA_REF is not None and \
                request.LANKA_REF != "":
            response.set_cookie("LANKA_REF", request.LANKA_REF, max_age=365*24*3600)
        return response

    def _is_local_domain(self, url):
        for domain in settings.LANGUAGES_BY_DOMAIN:
            if url.find(domain) > 0:
                return True
        return False

Полный URL источника сохраняется в куке пользователя и в дальнейшем может отсылаться администратору или менеджеру с сообщением о заказе. Не сложно чуть видоизменить для сохранения, например, в базу.

Все в этом хорошо, кроме одного: строку запроса хочется видеть в легко читаемом виде. Для этого надо делать декодирование параметров URL. Пока запросы содержат только английские буквы - все в порядке. Но как только появляются русские буквы возникает проблема кодировки при переводе из/в уникод. При попытке сохранить строку как есть в куку вылетала ошибка UnicodeDecodeError. Проблема решилась путем насильного кодирования в уникод при сохранении в куку и обратно при чтении из нее. Конечный вариант middleware:

# -*- coding: utf-8 -*-
import urllib

from django.conf import settings

class RefererStoreMiddleware(object):
    """Get referring page and store it to the Cookie"""

    def process_request(self, request):
        request.LANKA_REF = None
        if "LANKA_REF" in request.COOKIES:
            try:
                request.LANKA_REF = request.COOKIES["LANKA_REF"].decode("utf-8")
            except UnicodeDecodeError:
                pass
            return
        referer_url = request.META.get("HTTP_REFERER", None)
        if referer_url is not None and referer_url != "" and \
                not self._is_local_domain(referer_url):
            try:
                request.LANKA_REF = urllib.unquote_plus(referer_url).decode("utf-8")
            except UnicodeDecodeError:
                pass

    def process_response(self, request, response):
        if hasattr(request, "LANKA_REF") and request.LANKA_REF is not None and \
                request.LANKA_REF != "":
            try:
                response.set_cookie("LANKA_REF", request.LANKA_REF.encode("utf-8"),
                        max_age=365*24*3600)
            except UnicodeDecodeError:
                pass
        return response

    def _is_local_domain(self, url):
        for domain in settings.LANGUAGES_BY_DOMAIN:
            if url.find(domain) > 0:
                return True
        return False
 
comments powered by Disqus