如何 5 分钟用 elli 搭建你的第一个 Erlang HTTP 服务器:新手快速开始完整教程
【免费下载链接】elliSimple, robust and performant Erlang web server项目地址: https://gitcode.com/gh_mirrors/ell/elli
想要用 Erlang 搭建一个HTTP 服务器,很多新手第一反应是去啃 Cowboy 或 MochiWeb 的源码,结果还没开始就劝退了。其实 Erlang 生态里有一个极其简单、健壮又高性能的轻量级 HTTP 服务器——elli。它专为 HTTP API 设计,核心思想只有一个:你只需要写一个回调模块,剩下的连接管理、请求解析、并发处理全部交给它。本文将带你 5 分钟快速上手,从零开始搭建并运行你的第一个 Erlang HTTP 服务器,非常适合刚接触 Erlang Web 开发的新手。
什么是 elli?为什么新手首选它?⚡
elli 是一个简单、健壮且高性能的 Erlang Web 服务器,官方定位是"用于 HTTP API 的 Erlang 服务器"。它最大的特点就是极简:
- 回调式设计:你只需实现
handle/2和handle_event/3两个函数,就能处理所有请求。 - 性能出色:默认 20 个 acceptor 并发接受连接,配合 Erlang 的进程模型,轻松支撑高并发 API。
- 依赖极少:rebar.config 里
deps为空,几乎没有第三方依赖,编译快、部署简单。 - 功能够用:支持 GET/POST 参数解析、自定义响应头、chunked 流式响应、sendfile 静态文件、SSL 加密、中间件扩展等。
对比 Cowboy 这类功能全面的框架,elli 更像一把"手术刀"——没有多余的东西,砍掉一切你不需要的,让你专注业务本身。
快速开始前的环境准备 🛠
在动手之前,请确认你的机器上已安装:
- Erlang/OTP(建议 20.0 以上版本),终端执行
erl能进入 Erlang shell 即可。 - make和gcc(用于编译 Erlang 代码)。
- git(用于拉取项目源码)。
如果你还没有 Erlang,可以通过系统包管理器或官方源码包安装,整个过程约 2 分钟。安装完成后,erl -version能看到版本号就说明环境就绪了。
一键安装:克隆并编译 elli 源码 🚀
环境就绪后,我们开始安装。先把项目克隆到本地并编译:
git clone https://gitcode.com/gh_mirrors/ell/elli cd elli make compilemake compile实际上执行的是./rebar compile,仓库自带了rebar可执行文件,所以无需额外安装构建工具。编译成功后,ebin/目录下会生成所有.beam文件,这就意味着你的Erlang HTTP 服务器核心已经就绪了。
想要验证代码质量,还可以运行自带测试:
make eunit测试用例覆盖了elli_example_callback、HTTP 解析、中间件、SSL 等多个模块(见test/目录),全部通过说明安装没有任何问题。
最快配置方法:启动你的第一个 HTTP 服务器 🌟
编译完成后,最快启动服务器的方式是利用 elli 自带的示例回调模块。在项目根目录启动 Erlang shell:
erl -pa ebin然后在 Erlang shell 中输入:
elli:start_link().就这么简单!默认情况下,elli:start_link/0会读取include/elli.hrl中定义的默认配置:监听8080 端口,回调模块为elli_example_callback。现在打开浏览器访问:
http://localhost:8080/hello/world→ 返回Hello World!http://localhost:8080/hello?name=Elli→ 返回Hello Elli
你的第一个 Erlang HTTP 服务器已经跑起来了!🎉 从安装到启动,整个过程不超过 5 分钟。
如果你需要自定义端口,只需传入配置列表:
elli:start_link([{callback, elli_example_callback}, {callback_args, []}, {port, 9000}]).elli:start_link/1的核心入口定义在src/elli.erl,它会创建监听 socket、启动 acceptor 进程池,并在启动时回调你的handle_event(elli_startup, ...),方便你初始化 ETS 表或辅助进程。
编写你的第一个 HTTP 回调模块 ✍️
默认的elli_example_callback只是示例,生产环境你需要写自己的回调。ellie 的约定非常清晰:实现elli_handler行为,提供handle/2和handle_event/3两个函数。
新建一个my_callback.erl文件:
-module(my_callback). -behaviour(elli_handler). -export([handle/2, handle_event/3]). -include("include/elli.hrl"). handle(Req, _Args) -> handle(elli_request:method(Req), elli_request:path(Req), Req). handle('GET', [<<"ping">>], _Req) -> {ok, [], <<"pong">>}; handle('GET', [<<"hello">>, Name], _Req) -> {ok, [{<<"Content-Type">>, <<"text/plain">>}], <<"Hello ", Name/binary>>}; handle(_, _, _Req) -> {404, [], <<"Not Found">>}. handle_event(_Event, _Args, _Config) -> ok.然后编译并启动:
c(my_callback). elli:start_link([{callback, my_callback}, {callback_args, []}, {port, 8080}]).访问http://localhost:8080/ping即可得到pong。这个最小示例展示了 elli 的核心模式:
elli_request:path/1会把 URL 路径按/切分成二进制列表,方便你写路由匹配子句。- 响应格式为
{状态码或ok, 响应头列表, 响应体},响应体可以是 binary 或 iolist。
常用接口开发技巧:参数、请求头与响应 📦
新手开发 API 时最常用到的能力,elli 的elli_request模块几乎都提供了:
获取 URL 查询参数
Name = elli_request:get_arg(<<"name">>, Req, <<"undefined">>), %% 需要 URL 解码时用 get_arg_decoded/3获取 POST 表单参数
Name = elli_request:post_arg(<<"name">>, Req, <<"undefined">>), City = elli_request:post_arg_decoded(<<"city">>, Req, <<"undefined">>),读取请求头
Accept = elli_request:get_header(<<"Accept">>, Req, <<"text/plain">>),返回自定义响应头与状态码
{201, [{<<"X-Custom">>, <<"foobar">>}], <<"created">>}, {304, [{<<"Etag">>, <<"abc">>}], <<>>}具体实现都可以在src/elli_request.erl中找到,每个函数的用途一目了然。需要提醒的是:返回{304, ...}时 elli 会自动忽略响应体,非常适合做缓存协商。
进阶玩法:中间件、gzip 压缩与流式响应 🔥
当你的 API 需要鉴权、日志、压缩等横切能力时,elli 提供了优雅的中间件机制。
中间件链:通过elli_middleware组合多个处理模块,比如官方示例中把压缩中间件和业务回调串起来:
Config = [{mods, [ {elli_middleware_compress, []}, {my_callback, []} ]}], elli:start_link([{callback, elli_middleware}, {callback_args, Config}, {port, 8080}]).配置好elli_middleware_compress后,超过 1024 字节的响应体会被自动 gzip 压缩,大幅降低带宽消耗,而你的业务代码完全无感知。
chunked 流式响应:如果要做实时推送(如 SSE),elli 支持分块发送。核心用法是拿到chunk_ref后异步发送数据:
Ref = elli_request:chunk_ref(Req), spawn(fun() -> elli_request:send_chunk(Ref, [<<"chunk1">>]), elli_request:send_chunk(Ref, [<<"chunk2">>]), elli_request:close_chunk(Ref) end), {chunk, [{<<"Content-Type">>, <<"text/event-stream">>}]}静态文件与 Range 支持:返回{file, "/path/to/file"}即可让 elli 用 sendfile 发送文件,配合elli_util:normalize_range/2还能直接支持 HTTP Range 断点续传,这在提供下载服务时非常实用。
单元测试你的回调逻辑 ✅
elli 内置了测试辅助模块elli_test,可以不启动服务器直接调用你的回调,极大方便了单元测试:
elli_test:call('GET', <<"/ping">>, [], <<>>, [{callback, my_callback}, {callback_args, []}]).返回的#req{}记录中包含了回调的返回值,配合 EUnit 断言即可完成测试。项目自带的test/elli_tests.erl等测试文件都是很好的参考范例。
写在最后 💡
通过本文,你应该已经掌握:用 5 分钟克隆编译 elli、通过默认配置快速启动、编写自己的回调模块、解析参数与请求头、使用中间件和流式响应,以及编写单元测试。elli 的代码量很小,src/目录下只有十几个.erl文件,当你遇到问题或想深入原理时,直接阅读源码就是最好的文档。还等什么?马上动手,搭建属于你的第一个 Erlang HTTP 服务器吧!
【免费下载链接】elliSimple, robust and performant Erlang web server项目地址: https://gitcode.com/gh_mirrors/ell/elli
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考