Эликсир — Как мне управлять маршрутами с помощью Cowboy (и ничего другого)?

Я могу использовать Cowboy только для веб-сервера, который обрабатывает JSON REST API. Мне нужно иметь возможность использовать только Cowboy + независимо от возможностей языка для управления и обработки различных и переменных маршрутов, а также с использованием значений GET.

Я получаю путь, как описано в следующей процедуре:

def handle(req, router) do
  headers = [{"content-type", "application/json"}]
  {path, req}  = :cowboy_req.path(req)
  {:ok, resp} = :cowboy_req.reply(200, headers, router.call(path), req)
  {:ok, resp, router}
end

И в конечном итоге route.call(path) вызывает следующее:

defp serve("/call/[:thing]") do
  list = [path: "oy"]
  IO.puts :thing
  {status, result} = JSON.encode(list)
  result
end

Сам по себе serve("/call") возвращает JSON без проблем, но попытка запросить любой другой маршрут под /call на сервер заставляет его ответить ответом 404 (уже обработанным мной).

Каков наилучший подход при обработке этих динамических маршрутов? Имейте в виду, что я могу использовать только Cowboy и ничего больше.


person Kolt Penny    schedule 07.06.2020    source источник
comment
Вы говорите, что вам разрешено использовать только Cowboy, но добавление Plug в микс сделало бы это намного проще. Просто говорю'.   -  person zwippie    schedule 09.06.2020
comment
Я знаю. Я могу попытаться уговорить его использовать.   -  person Kolt Penny    schedule 09.06.2020


Ответы (2)


Ваш код не очень понятен - как вы запускали сервер? Точнее, как вы настроили свой маршрутизатор? Кажется, это проблема, я предполагаю, что вы сделали маршрут только для /call.

Вам понадобится что-то вроде этого:

dispatch_config = :cowboy_router.compile([{:_, [{"/call/[:thing]", YourHandlerModule, []}]}])
{ :ok, _ } = :cowboy.start_http(:http,
                                100,
                                [{:port, 8080}],
                                [{ :env, [{:dispatch, dispatch_config}]}]
                                )

Путь /call/[:thing] должен быть указан на маршрутизаторе, а не внутри вашего обработчика.

person Leonardo Dagnino    schedule 08.06.2020

Я нашел одно простое решение, используя только Cowboy и Elixir:

def call(conn) do
  serve(conn.req_path, conn)
end

defp serve(<< "/call/", name::binary >>, conn) do
  list = conn.req_qs
  IO.puts name
  {_, result} = JSON.encode(list)
put_resp_body(conn, result)

Если вы сделаете это так, все последующие маршруты останутся в rest. Подойдет простой раскол. conn содержит строку запроса, поэтому я могу получить оттуда значения.

person Kolt Penny    schedule 09.06.2020