HTTP сервер можно запускать различными способам, но здесь я рассмотрю, на мой взгляд, наиболее гибкий. Нам понадобится следующая структура:
log/ www/ index.html test.config httpd.conf scripts.erl start
В каталог log/ будут записываться лог файлы. В каталоге www/ хранятся статические файлы, в данном случае index.html:
<h1>Hello, World!</h1>
test.config - это основной файл конфигурации для приложения Inets, через который мы будем запускать HTTP сервер:
[ {inets, [ {services, [ {httpd, [{proplist_file, httpd.conf}]}]} ]} ].
Здесь httpd добавлен как сервис inets с конфигурацией в файле httpd.conf:
[ {modules, [ mod_alias, mod_auth, mod_esi, mod_actions, mod_cgi, mod_get, mod_head, mod_dir, mod_log, mod_disk_log ]}, {port, 8080}, {bind_address, any}, {server_name, "Test server"}, {server_root, "log/"}, {document_root, "www/"}, {directory_index, ["index.html"]}, {erl_script_alias, {"/scripts", [scripts]}}, {error_log, "error.log"}, {security_log, "security.log"}, {transfer_log, "transfer.log"}, {mime_types, [ {"html", "text/html"}, {"css", "text/css"}, {"js", "application/x-javascript"} ]}, {mime_type, "application/octet-stream"} ].
Рассмотрим кратко опции:
- modules - это список подключаемых модулей. В данном случае подключены все модули, но по желанию список можно сократить. Внимание: порядок модулей важен, т.к. они вызываются по порядку пока запрос не будет обработан.
- port и bind_address описывают порт и адрес на которых сервер будет принимать соединения. В качестве адреса указан атом any, но может быть указан и конкретный адрес в виде строки.
- server_name указывает имя сервера.
- server_root и document_root - соотв. корневые директории сервера и документов.
- directory_index - список индексных файлов для директорий.
- erl_script_alias описывает путь и список динамических модулей которые будут доступны через Web.
- Параметры *_log описывают имена различных лог-файлов.
- mime_types и mime_type - краткий список типов MIME и тип для неизвестных файлов. По документации mime_types можно указать в виде файла в стандартном формате, но пока у меня с этим есть сложности.
Файл конфигурации может быть также и в формате похожем на конфигурацию Apache, но мне больше нравится формат Erlang. Дополнительные опции конфигурации можно посмотреть в документации httpd.
В опции erl_script_alias в качестве доступных модулей был указан только модуль scripts. Исходный файл scripts.erl:
-module(scripts). -export([test/3]). test(SessionID, Env, _Input) -> mod_esi:deliver(SessionID, ["Content-Type: text/html\r\n\r\n" | format(Env)]). format([]) -> ""; format([{Key, Value} | Env]) -> [io_lib:format("<b>~p:</b> ~p<br />\~n", [Key, Value]) | format(Env)].
Функция test/3 описывает нашу тестовую точку входа:
- SessionID - это идентификатор запроса, который используется в последующих вызовах mod_esi:deliver/2. Рекомендуется не делать никаких предположений о типе идентификатора, но, по секрету, в текущей реализации - это pid процесса.
- Env - список переменных среды в виде [{Ключ, Значение}].
- Input - данные POST запроса. В данном случае мы их не используем.
Функция mod_esi:deliver/2 служит для посылки данных клиенту. Первым параметром должен передаваться полученный на входе идентификатор запроса и затем список строк для передачи. Функция может вызываться несколько раз, но если нужно передать заголовки, то они должны быть возвращены в первом вызове deliver, как в нашем примере.
В примере так же используется вспомогательная функция format/1 для форматирования переменных среды.
Перед запуском нам нужно откомпилировать наш модуль:
$ erlc -Wall scripts.erl
И затем мы можем запустить файл start со следующим содержимым:
#! /bin/sh erl -noshell -config test -s inets
Здесь мы запускаем приложение inets с файлом конфигурации test.config. После запуска по адресу http://127.0.0.1:8080 можно увидеть вывод странички index.html и по адресу http://127.0.0.1:8080/scripts/scripts/test/ вывод получаемый при вызове функции test в модуле scripts.
Остановить тестовый сервер можно стандартным Ctrl+C и a.
Comments All comments
Comment by Andrey Popp on 00:53, 2009 6 24
А почему не по OTP-шному?
Comment by Dmitry Vasiliev on 08:56, 2009 6 24
По OTP-шному, если ты посмотришь что такое inets:start/0
Comment by Andrey Popp on 18:08, 2009 6 24
Не нравится мне inets, это как django в python - магия сплошная. Другое дело MochiWeb - всё просто и понятно ;)
Comment by Dmitry Vasiliev on 18:12, 2009 6 24
:-))) Где магия? Это все стандартные возможности Erlang. А вот MochiWeb как-раз использует недокументированные возможности. ;-)
Comment by zabivator on 18:12, 2010 1 11
Можно узнать, какие именно недокументированные возможности использует Erlang?
А то мы его используем, вот и хочется знать какой "подземный стук" может вылезти.
P.S. уведомление об ответе мне придёт на e-mail, или самому проверять эту страницу периодически?
Comment by Dmitry Vasiliev on 18:51, 2010 1 11
Сам Erlang не может использовать недокументированных возможности, точнее - все, что внутри, все его. :-)
Приложения написанные на Erlang могут использовать недокументированные возможности Erlang и основная проблема с этим, что теоретически эти возможности могут убрать, или поменять до неузнаваемости. Поэтому я лично стараюсь избегать их использовать.
Видимо самая известная из недокументированных возможностей (которая и упомянута выше) - parameterized modules (ftp://ftp.sunet.se/pub/lang/erlang/workshop/2003/paper/p29-carlsson.pdf). Как минимум MochiWeb и Riak их используют.
Еще можно упомянуть packages (http://erlang.org/doc/man/packages.html), которые документированы, но не рекомендуются к использованию.
Из мелочей не стоит использовать, например, устаревшую форму вызова через кортеж: {string, to_lower}("TEST").
В целом, конечно, ничего страшного, тем более, если вы сами пишете эти приложения. Обычно сложнее (и менее приятно) разбираться с чужими приложениями, которые уже не поддерживаются и вдруг перестали работать.
P.S. Нужно проверять, или подписаться на RSS/Atom с комментариями.
Add comment