Средняя посещаемость ресурса 40т в сутки. Drupal, кеширующий модуль boost, создающий статичные страницы которые выдает nginx.
Поиск решения в google предлагал варианты js перенаправление на стороне клиента, либо передачу данных на апач, запрос базы данных для получения нужного урла, что изначально не устраивало.
Рассмотрев доступные базы ip адресов: www.wipmania.com/ru/base/, www.maxmind.com/en/home, ipgeobase.ru/, возникла «гениальная идея», что если бы в базе были необходимые нам урлы [номер региона], то счастье было бы полным.
Исходя из этого и условий, что геотаргетинг делается только для регионов России, остановился на модуле nginx geo и базе адресов от ipgeobase, так как модуль geo может принимать текстовый файл в качестве базы адресов, ну а база от ipgeobase распространяется в текстовом формате. Осталось, собственно, привести базу адресов в нужный формат…
Итак:
Отсюда ipgeobase.ru/files/db/Main/geo_files.tar.gz скачиваем базу данных, получаем архив, распаковываем и получаем 2 файла cidr_optim.txt и cities.txt.
cidr_optim.txt имеет следующий формат записи:
<начало блока> <конец блока> <блок адресов> <страна> <идентификатор города>
<начало блока> — число, полученное из первого ip адреса блока (диапазона) ip-адресов вида a.b.c.d по формуле a*256*256*256+b*256*256+c*256+d
<конец блока> — число, полученное из второго ip адреса блока (диапазона) ip-адресов вида e.f.g.h по формуле e*256*256*256+f*256*256+g*256+h
<блок адресов> — блок (диапазон) ip-адресов вида a.b.c.d — e.f.g.h, для кторого определено положение
<страна> — двухбуквенный код страны, к которой относится блок
<идентификатор города> — идентификатор города из файла cities.txt. Если вместо идентификатора стоит прочерк, значит, либо город не удалось определить, либо страна блока не Россия и не Украина.
cities.txt имеет следующий формат записи:
<идентификатор города> <название города> <название региона> <название округа> <широта центра города> <долгота центра города>
Описание файлов находится здесь ( ipgeobase.ru/Help.html#35 )
Из всего этого, распарсив файлы в базу данных, получил 2 таблицы с данными из файлов, которые, затем, используя названия регионов привел к формату
«блок (диапазон) ip-адресов вида a.b.c.d — e.f.g.h» -> (необходимый урл) [номер региона]
Дело осталось за малым — перевести формат:
«блок (диапазон) ip-адресов вида a.b.c.d — e.f.g.h» в формат понимаемый модулем geo:
0.0.0.0/0 (начальный адрес/битовая маска).
Тут, как ни странно, началось самое веселое. Опросил все знакомых админов, все дружно сказали что проходили то как перевести диапазон в нужный мне формат, но, за ненадобностью, все давно забыли, а вспоминать некогда. Google, который всегда нам в помощь, предлагал либо инструкции по расчету диапазона по адресу и маске, либо досконально изучить принцип формирования сетей ip4.
Для решения задачи выбрал 3-й вариант. В сети нашел ip-calculator.ru/, связался с администратором домена, который любезно согласился помочь с переводом и разъяснением принципа перевода адресов в нужный формат. (еще раз спасибо).
В итоге получился файл формата «0.0.0.0/0 (необходимый урл);» c 57 тысячами строк, назовем его, скажем, geo_ru.conf.
Теперь, собственно, nginx:
в блоке http{} включаем модуль
geo $region_number { default all; include [адрес где лежит файлик]/geo_ru.conf }
т.е. после обращения, в случае нахождения адреса клиента в файле, в переменной $region будет находиться соответствующее значение, а именно [номер региона], в противном случае ‘all’. (подробнее: nginx.org/ru/docs/http/ngx_http_geo_module.html )
Далее, собственно, редирект:
в блоке server{} сайта
# установили переменную $get_redirect со значением donot_redirect set $get_redirect donot_redirect; # в случае, если клиент заходит на главную страницу присваеваем переменной значение do_redirect if ($uri = '/') { set $get_redirect do_redirect; } # если nginx не нашел адреса клиента в базе и в переменной $region_number значение 'all' , то и редиректить незачем if ($city = 'all') { set $get_redirect donot_redirect; } # если уже есть кука, т.е. клиент уже заходил к нам и мы его редиректили на его регион (должна же быть возможность смотреть главную страницу) if ($cookie_geolocate = 1) { set $get_redirect donot_redirect; } # ну и собственно сам редирект на нужную страницу if ($get_redirect = do_redirect) { rewrite ^(.*)$ http://fedpress.ru/region/$region_number redirect; }
(т.е. в итоге мы получили то что хотели — переход на region/[номер региона])
Ну и последнее — чтобы клиент мог все-таки посмотреть главную страницу, в блоке
location / {} отправляем клиенту куку:
add_header Set-Cookie "geolocate=1;Path=/;Domain=.example.com;";
Вот, собственно, и все. Надеюсь кому-нибудь поможет. Поводом для написания статьи стало то что решение, вроде бы очевидное, появилось не сразу. Буду рад комментариям, советам, уточнениям.
PS Уважаемые админы, присутствующие на хабре, напишите, пожалуйста, статью с пошаговым руководством «для чайников» о том что такое ip адреса, как расчитывать маску по диапазону и наоборот, зачем нужны <начало блока> (a*256*256*256+b*256*256+c*256+d) и <конец блока> (e*256*256*256+f*256*256+g*256+h), думаю многие были бы благодарны.
ссылка на оригинал статьи http://habrahabr.ru/post/159335/
Добавить комментарий