четверг, 17 августа 2017 г.

Отдаем .webp вместо jpg/png при помощи .htaccess

Формат .webp уже поддерживается основными браузерами: файрфоксом, эджем, хромом и аналогами, их совокупная доля на рынке превышает 75%, а значит есть смысл его использовать, чтобы изображения быстрее загружались.

Как это сделать? Существуют решения с <picture> или определением поддержки webp при помощи джаваскрипта, добавлением класса .webp в <html> и загрузки нужных форматов через css. Эти варианты требуют изменения разметки. Вместо этого можно обойтись всего лишь изменением конфига сервера.

Работает так:
  1. Сервер проверяет, поддерживает ли браузер пользователя webp (браузер указывает в это заголовках запроса).
  2. Если пользователь запрашивает изображение, то сервер проверяет, есть ли такая же картинка с расширением webp.
  3. Если есть, то отдает ее пользователю. Иначе отдает обычную.
Решение для .htaccess:

В диспетчере запросов будет виден только один запрос с изначальной картинкой, вместо которой будет отдан webp файл. В столбце Type будет указано "webp".

Существуют аналогичные решения: webp-detect (заодно есть конфиг для nginx и др.), WebP-images-with-htaccess.

Их особенность в том, что они не работают. В них для проверки существования файла с расширением webp используется {DOCUMENT_ROOT}, но у меня он ведет в корень сайта, а не в папку с файлом. Из-за этого сервер не может найти webp файлы. Зато вариант с {REQUEST_FILENAME} работает.

Вывести переменную из .htaccess

При отладке .htaccess хочется вывести на экран значение переменных или найденных строк. На stackoverflow есть решение:
# в переменную окружения TEST0 передаем требуемые данные
RewriteRule ^(.*) - [E=TEST0:%{DOCUMENT_ROOT}/blog/html_cache/$1.html]

# после чего показываем эту переменную в заголовке ответа TEST_FOOBAR
Header set TEST_FOOBAR "%{REDIRECT_TEST0}e"
Например, если мы хотим отладить отдачу картинок webp через .htaccess, то делаем так:
<IfModule mod_rewrite.c>
  RewriteEngine On

  RewriteCond %{HTTP_ACCEPT} image/webp
  RewriteCond %{REQUEST_FILENAME} ^(.+)\.(jpe?g|png)$
  RewriteCond %1\.webp -f
    RewriteRule ^(.+)\.(jpe?g|png)$ $1.webp [T=image/webp,E=accept:1,E=TEST0:%1\.webp]
</IfModule>

<IfModule mod_headers.c>
  Header append Vary Accept env=REDIRECT_accept
  Header set TEST_FOOBAR "%{REDIRECT_TEST0}e"
</IfModule>

AddType image/webp .webp
Затем заходим в инспектор запросов браузера, кликаем на нужный запрос, и смотрим заголовок TEST_FOOBAR:



Более подробное логирование

В апаче можно включить логирование rewrite-правил: он будет объяснять что делает и почему. Но, к сожалению, такой лог нельзя включить через .htaccess, а значит на обычных хостингах работать не будет. Впрочем, можно включить его на своем локальном апаче и отладить там.

Он включается в настройках VirtualHost апача. Нужно указать:
LogLevel alert rewrite:trace8
Перезапускаем апач и теперь в error.log будет отображаться подробная информация по правилам .htaccess.
четверг, 1 июня 2017 г.

Как правильно обновить npm под windows

Открываете cmd или powershell от имени администратора и запускаете там команды:
powershell -ExecutionPolicy unrestricted
npm install --global --production npm-windows-upgrade
npm-windows-upgrade --npm-version latest
Вот и все, npm обновлен.
воскресенье, 10 апреля 2016 г.

Syntax highlighter для blogger

1. Открываете в блогспоте вкладку "Дизайн". Снизу в footer добавляете гаджет "HTML/Javascript" с содержимым:
<!-- syntax hightlight -->
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.3.0/styles/vs.min.css" />
<style>
pre>code {padding: 1em; border: 1px solid #aaa; display: block; overflow-x: auto;}
</style>
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.3.0/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
Сохраняете.

2. Во время редактирования поста переходите на вкладку HTML и там пишите:
<pre><code> тут код, который нужно раскрасить </code></pre>
Скрипт сам постарается определить язык программирования. Если хотите, то можете указать его явно. Для этого укажите класс в теге <code class="javascript">. Названия поддерживаемых языков находятся в документации.

Если хотите отключить раскрашивание, то указываете класс "nohighlight".

Если хотите раскрасить html, то в блоггере на вкладке "Создать" вставляете html код, нажав ctrl+shift+v. Затем переходите на вкладку HTML и там обрамляете получившийся код (со всеми этими &lt; и &gt;) тегами <pre><code class="html"> ... </code></pre>.

Для всего этого используется библиотека highlightjs.org. Заходите в ее демку, чтобы узнать какие языки поддерживаются и выбрать подходящий стиль раскраски.

3. Если пишите посты в блоггере через вкладку "Создать", то когда вы будете отделять пустыми строками блоки с кодом, то блоггер будет добавлять лишние пустые строки. Чтобы этого избежать, нужно убрать пустые строки над и под блоками с кодом. Можно так же во вкладке HTML удалить лишние <br> вокруг блоков с кодом. В редакторе блоггера пост будет выглядеть примерно так:


Cron в meteor.js при помощи Heroku Scheduler

Идея простая:
  1. В Meteor.methods добавляем нашу задачу (назовем ее task)
  2. Создаем route '/task/:param'
  3. А затем вызываем его через curl.
Код:
# /lib/router.coffee

Router.route '/task/:param', {where: 'server'}
  .post ->
    Meteor.call 'task', @params.param # запускаем метод 'task', ждем выполнения
    this.response.end('done') # возвращаем 'done' когда 'task' выполнится

# /lib/task.coffee (or /server/task.coffee ?)

Meteor.methods
  task: (param) ->
    return if (Meteor.isClient)
    # your code here
Добавляем в хероку аддон Heroku Scheduler. В нем добавляем задачу:
curl -X POST https://our-app.herokuapp.com/task/param-value
Теперь хероку будет по расписанию это запускать, передавая param-value в метод task и возвращать строку 'done' (будет видна через heroku logs).
воскресенье, 18 января 2015 г.

Как заставить работать PEAR в XAMPP

1. В C:\xampp\php\pear.bat нужно добавить строку (там в начале файла есть несколько аналогичных - после них и добавляйте) источник
IF "%PHP_PEAR_SYSCONF_DIR%"=="" SET "PHP_PEAR_SYSCONF_DIR=C:\xampp\php"
2. Открываете консоль в папке C:\xampp\php\ и вводите команды: источник
pear config-set doc_dir C:\xampp\php\pear\docs
pear config-set cfg_dir C:\xampp\php\pear\cfg
pear config-set data_dir C:\xampp\php\pear\data
pear config-set cache_dir C:\xampp\php\pear\cache
pear config-set download_dir C:\xampp\php\pear\download
pear config-set temp_dir C:\xampp\php\pear\temp
pear config-set test_dir C:\xampp\php\pear\tests
pear config-set www_dir C:\xampp\php\pear\www
Все, после этого PEAR должен заработать.
суббота, 20 октября 2012 г.

Что такое NCrunch

NCrunch — это расширение для Visual Studio, которое автоматически запускает тесты. Причем для этого даже не обязательно сохранять файл. Все запускается на лету. Прошел тест или нет — это отображается сразу в редакторе. Так же отображается покрытие кода и узкие места по производительности.

Материалы по теме:
Альтернативы:
четверг, 27 сентября 2012 г.

System.Web.Razor для SimpleBrowser

Во время компиляции SimpleBrowser понадобится библиотека System.Web.Razor. Чтобы ее получить, достаточно установить ASP.NET MVC 3. Весит где-то 20 мегабайт. После установки сразу должно все скомпилироваться (может быть нужно будет перезагрузить студию).

Побеждаем NCrunch: "Невозможно загрузить файл или сборку"

Иногда бывает так, что проект компилируется, запускается, тесты через visual studio работают, а вот NCrunch не хочет работать и выдает ошибку:
"C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\TeamTest\Microsoft.TeamTest.targets (14): Невозможно загрузить файл или сборку "Project2, Version=0.5.0.0, Culture=neutral, PublicKeyToken=null" или один из зависимых от них компонентов. Не удается найти указанный файл."
Т.е. он не может найти какой-то там файл и из-за этого не удается скомпилировать проект. В этом случае:
  1. Меню NCrunch → Configuration → All solutions. И меняем настройки
    Log to output window = True (по-умолчанию False),
    Logging verbosity = Detailed (по-умолчанию Summary).
  2. Меню View → Output. Там выбираем "Show output from" = NCrunch Output.
  3. Если надо, то в окне NCrunch Tests жмем правой кнопкой по проблемному проекту → Rebuild...
  4. Теперь выделяем весь лог, копируем и вставляем в какой-нибудь текстовый редактор.
Там может быть что-то типа такого: 
Could not resolve this reference. Could not locate the assembly "SimpleBrowser, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
 И далее будут указаны места, в которых он искал этот файл. Тогда:
  1. Идем в NCrunch → Configuration. Выбираем тот проект, про который он писал в самой первой ошибке "невозможно загрузить файл или сборку..." (у меня это Project2). 
  2. Additional files to include → Жмем кнопку "..." и добавляем недостающие файлы. Обычно они уже есть в папке bin\Debug.
После этого все должно нормально работать.
воскресенье, 11 марта 2012 г.

Serialize CookieContainer to string

Как сериализовать CookieContainer в строку, а затем получить его обратно.
private static string SerializeCookiesToString(CookieContainer cookieContainer)
{
    using (var stream = new MemoryStream())
    {
        try
        {
            new BinaryFormatter().Serialize(stream, cookieContainer);
            return Convert.ToBase64String(stream.ToArray());
        }
        catch (Exception)
        {
            return string.Empty;
        }
    }
}

private static CookieContainer DeSerializeCookiesFromString(string cookies)
{
    try
    {
        using (var stream = new MemoryStream(Convert.FromBase64String(cookies)))
        {
            return (CookieContainer)new BinaryFormatter().Deserialize(stream);
        }
    }
    catch (Exception)
    {
        return new CookieContainer();
    }
}
понедельник, 19 сентября 2011 г.

Как в javascript переименовать функцию

Переименовать уже существующую функцию не так-то просто. Но возможно:
// при помощи этой функции будем переименовывать
Object.defineProperty(
    Object.prototype, 
    'renameProperty',
    {
        writable : false, // Cannot alter this property
        enumerable : false, // Will not show up in a for-in loop.
        configurable : false, // Cannot be deleted via the delete operator
        value : function (oldName, newName) {
            // Check for the old property name to 
            // avoid a ReferenceError in strict mode.
            if (this.hasOwnProperty(oldName)) {
                this[newName] = this[oldName];
                delete this[oldName];
            }
            return this;
        }
    }
);

// сам пример. переименовываем функцию NIRV.repaintMain в NIRV.repaintMain2
NIRV.renameProperty("repaintMain", "repaintMain2");
NIRV.repaintMain = function() {
  NIRV.repaintMain2();
  $("li.task.completed").each(AddReaddButton);
};
Этот вариант может не везде работать. Я его взял здесь. Там есть и другая функция для переименования.
среда, 31 августа 2011 г.

Как в javascript обернуть функцию

Однажды мне для юзерскрипта потребовалось обернуть функцию. Вот есть функция repaintMain. Мне нужно обернуть ее, т.е. чтобы когда она вызывается, то сперва бы вызывался ее оригинальный код, а потом мой.

Оказывается, в джаваскрипте это делается довольно просто:
repaintMain2 = repaintMain;
repaintMain = function() {
  repaintMain2.apply(this, arguments);;
  $("li.task.completed").each(AddReaddButton);
};
Узнал об этом способе здесь.

Еще есть способ оборачивания через переименование функции.

Кроме того, есть довольно продвинутые способы оборачивания функции. Которыми можно пользоваться вот так:
var beforeExecute = function() { ... }
var afterExecute = function() { ... }

myFunc = wrap(myFunc, beforeExecute, afterExecute);
воскресенье, 14 августа 2011 г.

Работа с git-репозиторием GitEnterprise

В качестве приватного git-репозитория для личных проектов я выбрал (см. апдейт в конце поста) http://www.gitenterprise.com/. Смотрите pricing бесплатного акка: сколько угодно репозиториев, 1 гб места, до 10 пользователей.

Это скорее памятка для самого себя. Обычная ситуация: уже начал что-то делать и стало ясно, что надо бы репозиторий создать, причем хорошо бы удаленный, для бэкапа.

1. https://gitent-scm.com/gitent/ - создаем новый репозиторий.
2. На вкладке Main перем ссылку на репозиторий (https).
3. SmartGit - Remote -> Manage Remotes -> Add. Указываем ссылку, любое название (например gitent-scm.com). Вроде бы предложит ввести пароль (от акка на gitent-scm.com).
4. Жмем Push. Если будет спрашивать, то жмем кнопку Configure.
5. Все должно быть в порядке.
6. Если появилось сообщение "you cannot push changes not committed by you", то смотрим здесь и, возможно, здесь.

Другой вариант, через создание нового репозитория (думаю, это какой-то левый вариант):

Шаги 1 и 2 такие же как в первом варианте.
3. SmartGit - выбираем Clone, указываем ссылку, жмем далее. Он предложит всякие пароли ввести.
4. Git working tree. Нужно указать пустую папку. Например: I:\work\MyProject.
5. И все. Если у нас уже есть проект, то копируем туда файлы и делаем первый коммит.

Update. Я сейчас перелез на bitbucket.org - он бесплатный, есть гит, а так же вики и issue-трекер (как на гитхабе).
вторник, 2 августа 2011 г.

Чеклист по безопасности ПО

Коммент из поста на хабре "Аудит. «Черный ящик»".

Для разработчиков (я имею в виду именно тех, кто пишет новые системы, а не прикручивает взятые из интернета готовые решения), вся защита сводится к очень короткому списку:

  • Валидируйте все входящие и исходящие данные по структуре и типам;
  • Не клейте SQL конкатенацией строк никогда, кроме случаев фреймворков (но во фреймворках можно и код более качественно писать, сделав дополнительную валидацию всех склеиваемых фрагментов);
  • Как можно чаще делайте кеширование чтобы избежать повторяющихся запросов и лишних нагрузок (кеш на диске, в памяти в специальных хеш-СУБД и т.д.);
  • Разделяйте систему для разработки (закрытую от внешнего мира) и продакшен систему (из которой нужно удалить половину, а оставшееся минифицировать и «утоптать» по максимуму);
  • Всегда предусматривайте блокировку запросов по IP, если с них идет странная активность (пользователь не сгенерирует 100 запросов в минуту и не будет долбить сервер 24 часа напролет, пользователи — люди, они едят и спят) (с разумными лимитами)
  • Определяйте попытки SQL-инъекций и XSS-инъекций, не просто их фильтруйте, а блокируйте IP
воскресенье, 24 июля 2011 г.

Как в Resharper'е перейти от префикса "_" к "this"

На хабре вышел интересный опрос (набравший аж +9) "Используете ли вы префиксы в именах членов классов?" В репашпере настройки по-умолчанию таковы, что используется префикс "_". Но в комментах было много хорошего сказано про "this." Например, этот коммент.

В общем, решил отказаться от префиксов и перейти на "this".

В решарпере для этого нужно:
1. Resharper -> Options -> Languages -> C# -> Other -> Force "this"
2. Там же где-то в настройках нужно изменить Naming Style, убрав префикс "_".

пятница, 1 июля 2011 г.

Как убрать Client Profile в новых проектах

По-умолчанию, в новых проектах Visual Studio выбирается .NET Framework 4 Client Profile. Было интересно узнать, как сделать так, чтобы в новых проектах был просто 4-й фреймворк, без client profile.

Как разместить Label по центру окна?

Все просто. Меняем свойства у Label:
  • Dock = Fill
  • AutoSize = False
  • TextAlign = MiddleCenter
воскресенье, 12 июня 2011 г.

Горизонтальная линия на c#

Как добавить на форму горизонтальную линию (как тег hr)? Есть разные способы. Один из них - создать для этого user control.