Игорь Сысоев: маштабируемая конфигурация nginx
abarmotik


Тезисы:



Локейшны бывают трех видов:

  • строковые

    • location /dir/ {...} — соот-вие по префиксу (/dir/photo/123.jpg)

    • location = /dir/counter.js {...} — строгое соот-вие

    • location ^~ /dir/ {...} — соот-вие по префиксу с запретом проверки
      регэксп-локейшнов


  • регэкспы

  • именованнве



Для поиска совпадения из строковых локешнов строится дерево и ищется максимальное совпадение.
Затем проверяются регэксп-локейшны (если это не отменил строковый локейшн).

Желательно весь конфиг делать на основе строковых локейшынов!


Если это это невозможно — постараться сделать вложенные локейшны (регэксп вложить в строковый):

location /i/ {
    location ~* \.(gif|jpg|jpeg)$ { ... }
}




Отличие root и alias:

location /img/ {
    #  '/' в конце роли не играет
    root /home/x/content;
}

img/leftArrow.png → /home/x/content/img/leftArrow.png

location /img/ {
    #строковая замена! обращать внимание на '/' в конце.
    alias /home/x/content/; 
}

/img/leftArrow.png → /home/x/content/leftArrow.png
Метки:

JQuery UI datepicker — иногда мигает страница.
abarmotik
Нравится мне этот пикер в жквери-юае. Тык в простой инпут открывает симпатичный календарик. Использую его во всех проектах где хоть одну дату надо вводить.
Недавно столкнулся с интересной его особенностью — моргает страница на которой используется datapicker.
Моргает не всегда. Небольшое исследование показало — моргание происходит, когда включен выбор года через селект ($('.date').datepicker({changeYear: true});). И когда диапазон лет (yearRange) достаточно большой.

Видимо в этом случае селектор для выбора года не всегда вписывается в отведенное ему место, а при его перестроении и происходит моргание страницы.

Как фиксить — не понял. Стараюсь теперь отключать селекторный выбор года и месяца, где в этом нет необходимости (т.е. почти везде)


Кстати, оказалось, что стандартный автокомплит не всегда отключается при использовании датапикера. Отключить не сложно:

$('.data').datepicker({...}).attr('autocomplete', 'off');
Метки:

Начинающим Java программистам
abarmotik
Программирую на Java вот уже 7 лет. Но на работе часто приходится обучать новое поколение. В связи с этим и решил сделать некоторую шпаргалку, которая, надеюсь, пригодится и для хабрчан. Если кто-то может помочь дополнить чем-то информацию из этой статьи, то пишите! Итак:

Основные ресурсы для начального обучения

  • www.javable.com — сайт со статьями и tutorial'ом по Java. Все в основном на русском.
  • www.exampledepot.com — очень полезный ресурс, где собраны краткие примеры использования классов для тех или иных пакетов
  • java.sun.com — без первоисточника не обойтись. Для любого Java программиста JavaDoc должен быть истиной в последней инстанции. Так же здесь можно найти серию tutorial'ов на все возможные темы.

Основные Java пакеты


Ниже приведён список Java пакетов, в которых программист должен свободно ориентироваться. Знакомиться с ними рекомендуется как по JavaDoc'ам, так и с помощью www.exampledepot.com. Все пакеты выстроены в рекомендуемом порядке для изучения. Итак:
  1. java.lang — основа основ. Каждый класс в этом пакете нуждается в отдельном внимании.
  2. java.io — ни одна программа не может обойтись без операций с вводом-выводом.
  3. java.util — пакет в основном содержит все необходимое для работы с коллекциями: Collection, Enumeration, Set, List, Map и т. д. и т. п.
  4. java.net — содержит основные классы для работы с сетью.
  5. java.text — все необходимое для форматирования текста
  6. java.lang.reflect — Java не была бы Java'ой если бы не Reflection. Reflection стирает грань между данными и кодом.
  7. javax.sql — все необходимое по работе с базами данных
  8. javax.xml.*, org.w3c.dom.*, org.xml.sax.* — без этих пакетов работа с XML просто немыслима

Ресурсы для расширения кругозора

  • onjava.com — рано или поздно все новости мира Java попадают сюда
  • www.javaspecialists.eu — ресурс полезен как новичкам, так и продвинутым программистам, так как содержит много статей о тонкостях работы с Java.
  • www.theserverside.com — рекомендуется подписаться на RSS, так как часто проскакивают весьма интересные вещи по Java.


Java Библитеки, которые должны знать все


Java не заканчивается знаниями лишь о возможностях JSDK. Чтобы чувствовать себя комфортно необходимо знать еще десятка два сторонних библиотек, используемых Java программистами повсеместно. Итак, начнем с основных:

  • Commons Lang — то что «забыли» включить в JDK
  • Commons Math — отличное дополнение для java.math
  • Commons Logging — логирование должно быть грамотным. За System.out.println для вывода логов начинающим программистам уже через неделю обучения следует отрубать руки.
  • Commons Net — логическое продолжение для пакета java.net. Множество классов для работы с основными сетевыми протоколами.
  • Commons VFS — отличная библиотека для абстрагирования от способа хранения файла. Позволяет достаточно обобщено иметь доступ до файлов по FTP, SFTP, WEBDAV, (G)ZIP и т. д.
  • Commons IO — работа с вводом-выводом часто получается весьма муторной, но с этой библиотекой все становится несколько веселее.
  • HttpClient — библиотека по работе с http ресурсами.
  • JUnit — любой код, должен сопровождаться тестированием. Для автоматизации тестирования и предназначена эта библиотека.

На этом пока все. Если подобные шпаргалки по Java вам интересны, то могу так же выложить свою коллекцию «простейших» задач по Java, которые ориентированы, на то, чтобы быстро освоить основные пакеты Java.

источник: http://habrahabr.ru/blogs/java/43293
автор: DbLogs

Как сделать сайт более iPhone-совместимым за 5 шагов
abarmotik
habrahabr.ru/blogs/web_design/72612Тот факт, что iPhone предлагает наиболее развитый мобильный браузер среди мобильных платформ, пожалуй, ни у кого не вызовет сомнений. Однако не все знают, что довольно небольшими усилиями можно сайт сделать еще более дружественным к тем, кто смотрят его на iPhone или iPod Touch.

Ниже предлагаются простые 5 шагов, с которых можно начать, на примере сайта WHOIS Digger.

Шаг 1. Аналог favicon.ico

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

<link rel="apple-touch-icon" href="res/iphone_icon.png" />

и добавьте соответствующую картинку res/iphone_icon.png размером 57х57 пикселов. iPhone сам добавит скругленные углы и полукруглый блик, сделав вашу иконку похожей на остальные.

Вот так выглядит исходная картинка и иконка на рабочем столе iPhone:



Шаг 2. Полноэкранный режим (почти).

Добавление вот этого тега приведет к тому, что ваш сайт, будучи запущен по иконке из SpringBoard, будет похож на отдельностоящее приложение (не будет отображаться ни строка ввода адреса / поиска, ни нижний тулбар). Останется только верхняя полоска статуса.

<meta name="apple-mobile-web-app-capable" content="yes" />

Минусы — навигация на сайте должна быть самодостаточной, ибо на кнопки Back / Forward браузера уже полагаться не получится.

Это вид веб-сайта, запущенного с иконки на рабочем столе. Как видите, ничего лишнего.



Шаг 3. Адаптируем диапазон масштабирования

Если Ваш сайт изначально отображается в iPhone не на полный экран, то вы можете подобрать начальный масштаб отображения, максимальный масштаб отображения и, при необходимости, запретить масштабирование пальцами вообще (если весь сайт при выбранном масштабе умещается на экране по горизонтали):

<meta name="viewport" content="width=device-width; initial-scale=0.85; maximum-scale=0.85; user-scalable=0;" />

Шаг 4. Добавляем CSS-стили, предназначенные только для iPhone

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

<link rel="stylesheet" href="res/iphone.css" media="only screen and (max-device-width: 480px)" />

Критически оцените вид вашего сайта на iPhone и посмотрите, какие элементы навигации и контента можно увеличить, чтобы по ним легче было попадать пальцем. Какие блоки можно на iPhone вообще скрыть или уменьшить? Можно ли привести сайт к одноколоночной верстке, для которой легче подобрать масштаб? Понятно, что разработка полноценного стиля сайта под iPhone — занятие ответственное, но какие-то моменты можно подправить достаточно быстро.

Шаг 5. Отмена автоматической коррекции масштабирования

Если Ваш сайт использует Ajax-запросы или Javascript для динамического изменения содержимого страницы, вы можете наблюдать неприятные побочные эффекты в виде изменения масштаба текста при изменениях DOM или сворачивании/отображении некоторых элементов. Следующий кусок CSS отключит встроенную эвристику мобильного Safari и избавит от этих эффектов:

html {
-webkit-text-size-adjust: none;
}


В итоге за 15 минут работы получилось полноценное веб-приложение для iPhone:



P.S.: теперь можно скачать исходники WHOIS Digger для установки на своем сайте.

источник: http://habrahabr.ru/blogs/web_design/72612
автор:
afan
Метки:

Evercookie — самые устойчивые куки / Web-разработка / Хабрахабр
abarmotik
Samy Mamkar разработал систему, которая позволяет хранить куки в 8 местах, автоматически восстанавливая друг друга, и даже добиться того, чтобы куки, поставленное в одном браузере, действовало и в другом.

Удалить это куки практически невозможно! (Все возможно, конечно, но слишком много мороки)

Куки хранятся в:
  • HTTP Cookies;
  • Local Shared Objects (Flash);
  • Сохранение куки в значениях RGB автосгенерированных и форсированно кэшированных PNG с использованием HTML5 canvas;
  • Сохранение куки в Web History;
  • HTML5 Session Storage;
  • HTML5 Local Storage;
  • HTML5 Global Storage;
  • HTML5 Database Storage через SQLite.

При удалении из одного из этих мест кука автоматически восстанавливается из оставшихся. Работает даже если пользователь сменит браузер (через Local Shared Objects из Flash).

Описание (на английском) и демо: http://samy.pl/evercookie/.
Попробуйте удалить куки, почистить систему и зайти назад.



Как пользоваться?

Скачать .js

<script type="text/javascript" src="evercookie.js"></script>
<script>
  var ec = new evercookie();
  ec.set("id", "12345");  // установить
  ec.get("id", function(value) { alert("Значение куки " + value) });  // прочитать
</script>

Добро пожаловать в конец анонимности.

UPDATE
Дополнение из комментариев (информация не проверенная и найти подтверждение пока не могу):
squint:
Автор заметки забыл сказать, что куки кросс-доменные, и хранить в них конфиденциальную инфу нельзя

Вот что написано в начале файла evercookie.js
*!!! SOME OF THESE ARE CROSS-DOMAIN COOKIES, THIS MEANS
* OTHER SITES WILL BE ABLE TO READ SOME OF THESE COOKIES!!!

источник: http://habrahabr.ru/blogs/webdev/104725
автор:
yoihj
Метки: ,

Визуализация данных в вебе: диаграммы Ганта / JavaScript / Хабрахабр
abarmotik


Диаграмма Ганта (англ. Gantt chart, также ленточная диаграмма, график Ганта) — это популярный тип столбчатых диаграмм, который используется для иллюстрации плана, графика работ по какому-либо проекту. Является одним из методов планирования проектов.

jsGantt

jsGantt — бесплатная библиотека, написанная на Javascript / CSS/ HTML, позволяет рисовать диаграммы Ганта.



Лицензия: BSD

Сайт: www.jsgantt.com/
Google Code: code.google.com/p/jsgantt/

SIcon Gantt Chart

SIcon Gantt Chart — еще одна Javascript библиотека для рисования диаграмм Ганта.

image

Лицензия: GPL

Сайт: www.codeproject.com/KB/scripting/SIcon_Gantt_Chart.aspx

Upd. jquery.gantt
Метки: ,

Неожиданность в работе явских регекспов — java.lang.StackOverflowError в Pattern'е
abarmotik
Делал профилировщик запросов к базе. Для их агрегации нужно было привести схожие запросы к единому виду.

Например все запросы типа select * from tuser where id in (?, ?, ?, ?, ?)
вне зависимости от кол-ва параметров привести к строке
select * from tuser where id in (?..?)

Казалось бы, при чем тут Лу, что проще — делаем replaceAll с правильным регэкспом «(\?,\s*)+» —
sql = sql.replaceAll("(?:\\?,\\s*)+", "(?..?)");

Ура! Все работает как надо.
Локально.
На сервере, ловим:
Exception in thread "prepareSql" java.lang.StackOverflowError
at java.util.regex.Pattern$Ques.match(Unknown Source)
at java.util.regex.Pattern$Slice.match(Unknown Source)
at java.util.regex.Pattern$GroupHead.match(Unknown Source)
at java.util.regex.Pattern$Loop.match(Unknown Source)
at java.util.regex.Pattern$GroupTail.match(Unknown Source)
at java.util.regex.Pattern$Ques.match(Unknown Source)
at java.util.regex.Pattern$Slice.match(Unknown Source)
at java.util.regex.Pattern$GroupHead.match(Unknown Source)
.... (и т.д.)


Оказалось, такой регэксп «(\?,\s*)+» обрабатывается рекурсивно и на длинных строках стэк превышает допустимую глубину.

Вылечил, заменив «\s*» на простой «\s».

Вроде ерунда, но как-то непривычно было словить StackOverflow на такой простой задаче.
Метки: , ,

Сити-квест: новые идеи
abarmotik
(начало где-то в предыдущих топиках)

Сайт сити-квеста нада сделать в виде онлайн игры. Это решает практически все вопросы и разногласия по организации.

С каждым участником ассоциирован персонаж. Выполняя задания персонаж перемещается по карте города и увеличивает свой уровень.

Все задания ассоциированы с определенной точкой на карте (Третьяковка, Воробьевы горы, Малый театр, Поклонка, ВВЦ и т.п.) Получив набор новых заданий, юзер открывает на карте связные с ними «точки» и смотрит кто еще собирается выполнять там свои задания в ближайшие дни. И есессно может скооперироваться с кем-либо. Это придаст сити-квесту черты соц-сети и сайта знакомств.

Кроме раздачи заданий и общения юзеров можно внести элементы традиционных онлайн-игр и соц-сетей. Фотки, «стена» юзера, блоги, френды, отчеты о заданиях (это от соц-сетей). Какие-нить флэш-игрухи, перемещение по карте, медали-амулеты-одежда и др барахло за выполнение задания (это от игр). К примеру выдавать медаль «ученик Чемпиона» за выполнение трех заданий связанных с разными видами спорта (ролики, картинг и пайнтбол, например).

Еще было б здорово придумать мета-цели. Т.е. цели для выполнения которых нужно собрать набор из каки-нить «амулетов». Достижение цели награждается каким-либо интересным способом. О! Есть «магазин необычных подарков» (вот например http://www.smile-smile.ru). Там можно купить «прыжок с парашютом», «тайский массаж», «катание на лошадях». Ну или банальные билеты в кино и т.п.

До новых встреч!
Метки: ,

Nginx, post_action. Как раздавать файлы по уникальному URL и отмечать окончание скачивания.
abarmotik

Условия


Задача возникла при работе над файл-шарой.
Для противодействия недобросовестным пользователям нужно организовать:

  1. уникальную ссылку на файл (что бы ей мог воспользоваться только получивший ее юзер)

  2. учет полного скачивания файла (т.е. отмечать скачивание по его завершению, а не по началу)



Файлы раздает nginx, а шифрует-дешифрует ссылки и учитывает раздачу бэк-енд сервер.

Схема работы:



  • сервер генерит ссылку, шифруя в ней ИД файла и IP юзера

  • по ссылке запрос пользователя попадает в лапы nginx'у

  • nginx перенаправляет запрос на бэк-енд сервер

  • бэк-енд расшифровывает ссылку и возвращает нгинксу путь к файлу

  • нгинкс раздает файл и по завершению отправляет отчет на бэк-енд.



Подробнее:


Создание ссылки пропускаю — тут все просто.

Что бы отдать файл, нгинкс должен знать его настоящий путь. Для этого передаем запрос бэк-енду с помощью директивы proxy_pass:

    proxy_pass http://127.0.0.1:8888/nginxds/linkDecoder?domain=$host&path=$request_uri;
    proxy_set_header  X-Real-IP  $remote_addr;



Бэк-енд получив шифрованную ссылку и ИП юзера, получает из нее ИД файла, узнает путь к нему и возвращает в виде хттп-хедера X-Accel-Redirect:

    String link = httpRequest.getParameter("path");
    File file = decryptLink(link);
    httpResponse.addHeader("X-Accel-Redirect", file.getPath());



Получив такой хедер, нгинкс переходит к соотв. location'у, который и отдает файл.

В этом же локейшыне нужно прописать директиву post_action @postDownload. Она выполнится по окончанию отдачи файла. В локейшыне @postDownload передаем запрос бэк-енду (с помощью proxy_pass).

Внимание, особенность!!! Если proxy_pass содержит переменные запроса ($uri, $host и т.п.) и отдача файла занимает некоторое время, то proxy_pass не срабатывает! Видимо запрос в нгинксе столько не живет. Т.е. обращения к бэк-енду не происходит. Лечится это «запоминанием» нужных данных запроса в переменные (в предыдущем локейшыне).

Не правильно. При передаче больших файлов proxy_pass не сработает.

    # В этот локейшн переходим по хедеру X-Accel-Redirect от бэк-енда.
    # (предполагается, что все раздаваемые файлы лежат в папке /storage)
    location /storage {
        post_action @postDownload;
        root /;
        internal;
    }
    
    # с такими параметрами proxy_pass на больших файлах не сработает
    location @postDownload {
        proxy_pass http://127.0.0.1:8888/nginxds/postDownload?domain=$host&uri=$uri;
        proxy_set_header  X-Real-IP  $remote_addr;
        proxy_set_header  BytesSent  $body_bytes_sent;
    }



Правильно. Сохраним нужные данные запроса в переменные.

    # В этот локейшн переходим по хедеру X-Accel-Redirect от бэк-енда.
    # (предполагается, что все раздаваемые файлы лежат в папке /storage)
    location /storage {
        set $postURI $uri;
        set $postIP $remote_addr;
        set $postHOST $host;
        
        post_action @postDownload;

        root /;
        internal;
    }

    location @postDownload {
        proxy_pass http://127.0.0.1:8888/nginxds/postDownload?domain=$postHOST&uri=$postURI;
        proxy_set_header  X-Real-IP  $postIP;
        proxy_set_header  BytesSent  $body_bytes_sent;
    }



Пост-запрос выполняется даже в случае досрочного завершения скачивания. По этому нужно передать бэк-енду сколько байт было реально отдано (proxy_set_header BytesSent $body_bytes_sent;)
На бэк-енде, учитывая хедеры BytesSent, range и реальный размер файла можно определить окончание скачивания.

Конфиг нгинкса



limit_zone lim  $binary_remote_addr 10m;

server {
    listen 80;
    server_name www.example.com;
    

    # Здесь обрабатывается запрос на скачивание файла.
    # урл имеет вид http://example.com/download/-encrypted-file-id-
    location /download {
        set $limit_rate 10k;
        limit_conn lim  1;

	# передаем запрос бэк-енду на расшифровку. В ответе ожидаем хедер X-Accel-Redirect 
        proxy_pass http://127.0.0.1:8888/nginxds/linkDecoder?domain=$host&path=$request_uri;
        proxy_set_header  X-Real-IP  $remote_addr;
        
        add_header Content-Length $content_length;
        add_header Content-Disposition attachment;
    }

    # В этот локейшн переходим по хедеру X-Accel-Redirect от бэк-енда (см. предыдущий локейшн)
    # Предполагается, что все раздаваемые файлы лежат в папке /storage
    location /storage {
        set $postURI $uri;
        set $postIP $remote_addr;
        set $postHOST $host;
        
        post_action @postDownload;

        root /;
        internal;
    }

    # по завершению скачивания файла передаем на бэк-енд переменные установленные
    # в предыдущем локейшыне и отданный объем (в байтах)
    location @postDownload {
        proxy_pass http://127.0.0.1:8888/nginxds/postDownload?domain=$postHOST&uri=$postURI;
        proxy_set_header  X-Real-IP  $postIP;
        proxy_set_header  BytesSent  $body_bytes_sent;
    }
}

Метки: ,

Волейбол с вертолетом на радиоуправлении..
abarmotik
Меня посетила очередная бредовая идея.
Что бы не засорять голову, публикую дамп сознания:


Берем вертолетик на радиоуправлении и два одинаковых пульта к нему (что б оба подходили)
встаем на таком расстоянии, что б зоны действия пультов соприкасались (или чуть-чуть пересекались)
и играем в волейбол — вертолетом!

Цель игры — расхерачить вертолет на поле противника.
Метки:

?

Log in

No account? Create an account