Roteamento
Agrupe rotas em scopes sob um prefixo de URL, cada um com seu pipeline de plugs. Path params como /posts/:id são extraídos automaticamente.
Apps web que ficam no ar
Framework web para Lx inspirado no Phoenix. Declare rotas com scopes e pipelines, responda pelos controllers, renderize views em HTML e entregue interfaces em tempo real com LiveView sobre WebSockets — tudo rodando sobre Cowboy, na BEAM, com gettext (i18n) e hot-reload em dev embutidos.
Agrupe rotas em scopes sob um prefixo de URL, cada um com seu pipeline de plugs. Path params como /posts/:id são extraídos automaticamente.
Plugs compostáveis por scope: fetch_params, fetch_session, put_secure_headers, accept_json, logger — encadeie o que precisar.
Funções simples (conn, params) -> conn. Responda com json, text, render, redirect, send_resp, defina status e headers, ou faça halt do pipeline.
Módulos render/2 com a diretiva template (layouts, partials) e component tags. Mantenha a marcação fora da sua lógica.
Componentes reativos: o servidor guarda o estado e envia patches de HTML sobre WebSockets. Bindings lx-click / lx-change / lx-submit; morphdom aplica os diffs no cliente.
lxweb_request simula requisições HTTP completas pelo seu roteador real — sem TCP. Asserte status, body e headers em testes simples.
require "lxweb_router"
require "lxweb_pipeline"
def dispatch(conn, method, path) do
pipelines = %{
browser: [
{:lxweb_pipeline, :fetch_params, []},
{:lxweb_pipeline, :put_secure_headers, []}
],
api: [{:lxweb_pipeline, :accept_json, []}]
}
routes = [
{:scope, "/api", :api, [
{:get, "/posts", :post_controller, :list},
{:post, "/posts", :post_controller, :create}
]},
{:scope, "/", :browser, [
{:get, "/", :page_controller, :index},
{:get, "/posts/:id", :post_controller, :show},
{:live, "/counter", :counter_live}
]}
]
lxweb_router:dispatch(conn, method, path, pipelines, routes)
end
require "lxweb_controller"
def show(conn, params) do
id = params[:id]
lxweb_controller:json(conn, %{id: id, title: "Hello"})
end
def create(conn, params) do
conn
|> lxweb_controller:put_status(201)
|> lxweb_controller:json(%{ok: true, title: params[:title]})
end
require "lxweb/lxweb_live"
def mount(_params, _session, socket) do
{:ok, lxweb_live:assign(socket, %{count: 0})}
end
def handle_event("inc", _params, socket) do
c = socket.assigns[:count]
{:noreply, lxweb_live:assign(socket, %{count: c + 1})}
end
def render(assigns) do
~L"""
<div data-lx-topic="lv:counter">
<h2>Contagem: #{assigns.count}</h2>
<button lx-click="inc">+1</button>
</div>
"""
end
require "lxweb_request"
require "lxweb_conn"
test "GET /posts/:id" do
conn = lxweb_conn:test(:my_router)
r = lxweb_request:get(conn, "/posts/42")
assert r.status == 200
assert lxweb_request:response_header(r, "content-type") == "application/json"
end
# project.yml
dependencies:
lxweb:
path: ../../lx_libs/lxweb
cowboy: "~> 2.0"
# depois
$ lx deps get & lx compile & lx run