Блог Конфуция
nginx.js 30.11.2008

UPD 2011-04-08: Внимание! Всё это старье, и лежит здесь только для истории.

На работе мы используем по большому счету только javascript и nginx (еще немножко ruby, но об этом в следующий раз). И мне всегда хотелось посмотреть, как они устроены внутри. Но достойной задачи не находилось, и пришлось ее придумывать. Что может быть лучше в данном случае, чем написать модуль для нжинкса по встраиванию яваскрипта? И правда, оказалось очень интересно. Сразу скажу, что практического применения связке nginx+js найти пока не удалось.

nginx

Стабильной версией нжинкса на данный момент является 0.6.34. В качестве мануала был выбран другой модуль: ngx_http_perl_module. Встроить перл у меня однажды получилось — правда, с трудом — и этот модуль показался самым лучшим примером. Никакое другое руководство мне бы не помогло так, как помог исходник перлового модуля. Вот она сила опенсорса! Чуть позже встретилось «Руководство Эмиллера по разработке модулей для Nginx». Это руководство мне очень понравилось. Оно дает общее представление о нжинксе и его механизмах. Я даже перевел половину на русский.

javascript

В качестве представителя яваскрипта был выбран SpiderMonkey. Потому, что мне нравится файрфокс, и у них еще на рино сил хватает. Сначала почитал как его компилить, потом как его встраивать, а затем погрузился в апи. Механизмы в этих текстах изложены вполне доступно, так что страх перед неизведанным быстро пропал. Встраивался именно SpiderMonkey 1.7.0. Мозила готовит ему на смену TraceMonkey и обещает, что сохранит обратную совместимость. Верю им: Firefox 3.1 уже вовсю использует TraceMonkey, значит и нжинкс сможет. А это уже JIT.

nginx+javascript

Так как SpiderMonkey не несет с собой библиотеки модулей (как перл, руби или питон), все придется писать с нуля. Это тоже очень интересно. Так же есть возможность прикрутить поделки немногочисленных отважных джедаев. В случае нашего модуля научить яваскрипт удалось немногому: выводить сообщения в лог и отвечать на простые GET запросы. Никаких инструментов для парсинга простых POST-запросов или, тем более, мультипартов на яваскрипте мной не написано. Даже файл открыть нельзя. Не удивляйтесь, это концепт, и нужен он пока только мне одному.

nginx.js

Итак, что мы умеем. Вот пример функции, которая отвечает на HTTP-запрос:


function processRequest (r)
{
    r.sendHttpHeader('text/html; charset=utf-8')
    r.printString("Привет, Девелопер!\n")
    r.printString("Ты вызвал страницу " + r.uri
        + ', методом ' + r.method + ', с IP ' + r.remoteAddr)
    return Nginx.HTTP_OK
}
Небольшое пояснение:
r — это объект запроса, созданный внутри нжинкса;
r.sendHttpHeader(ctype) — это метод отправляет заголовки клиенту, попутно устанавливая Content-type в значение ctype;
r.printString(str) — метод копирует значение строки str в очередь на отправку;
r.uri, r.method и r.remoteAddr — геттеры для соответствующих полей запроса;
Nginx.NGX_HTTP_OK — константа равная 200.

А вот отрывок файла конфигурации, который загружает nginx.js и устанавливает хендлер processRequest():


http
{
    js_require 'nginx.js';
    # ...
    server
    {
        # ...
        location /test
        {
            js processRequest;
        }
    }
}
В общем, все скопировано с ngx_http_perl_module.

Итог

Скоро должна накопиться критическая масса желающих использовать javascript как язык общего назначения. Они принесут с собой новые полезные модули, портируют уже существующие модули для похожих языков (например, модули для руби). И все станет еще интереснее. Но уже сейчас легкий и быстрый скриптовый язык внутри нашего любимого нжинкса выглядит интересно. Посмотрим что еще из этого получится.

Смотрите в следующих сериях

В ближайшем будущем постараюсь оформить этот модуль как настоящий модуль, а не как патч ко всему дереву исходников. Затем опишу наиболее интересные места спайки конструкций NGX_* и JavaScript.*. Возможно, научу-таки яваскрипт открывать файлы (научил, а потом разучил).

Теги:
  • сервер
  • javascript
  • nginx
  • ngx_http_javascript_module
  • ngx_http_js_module
  • serverside javascript
  • spidermonkey
Очень жду ваших комментариев на почту или на гитхаб.