Заглушки для Elixir — это то же самое, что Rack для Ruby . Таким образом, они оба используют функции для управления веб-запросами. Принцип работы вилок прост, как и их реализация. В этой статье мы рассмотрим базовое использование плагинов, от «hello world» до JSON API.
Предпосылки
- Эликсир и понимание основного синтаксиса и понятий эликсира.
- Базовые знания веб-запросов и HTTP.
Проэкт
Для начала мы собираемся создать базовый проект Elixir, используя микс . Давайте назовем наш проект Spy .
$ mix new spy * creating README.md * creating .gitignore * creating mix.exs * creating config * creating config/config.exs * creating lib * creating lib/spy.ex * creating test * creating test/test_helper.exs * creating test/spy_test.exs Your Mix project was created successfully. You can use "mix" to compile it, test it, and more: cd spy mix test Run "mix help" for more commands.
Если этот вывод выглядит незнакомым, взгляните на это руководство по миксу, чтобы вы могли быть в курсе.
Теперь пришло время погрузиться: сначала мы должны добавить Plug и веб-сервер (Cowboy) в наш проект mix.exs
. Затем нам нужно добавить их в зависимости нашего приложения ( да , есть разница, и да , я знаю, что это сбивает с толку.) Вот готовый продукт:
#mix.exs defmodule Spy.Mixfile do use Mix.Project def project do [app: :spy, version: "0.1.0", elixir: "~> 1.3", build embedded: Mix.env == :prod, start permanent: Mix.env == :prod, deps: deps()] end # Configuration for the OTP application # # Type "mix help compile.app" for more information def application do [applications: [:logger, :cowboy, :plug]] end # Dependencies can be Hex packages: # # {:mydep, "~> 0.3.0"} # # Or git/path repositories: # # {:mydep, git: "https://github.com/elixir-lang/mydep.git", tag: "0.1.0"} # # Type "mix help deps" for more examples and options defp deps do [ {:cowboy, "~> 1.0.0"}, {:plug, "~> 1.0"} ] end end
Теперь мы можем установить зависимости, которые мы только что указали, с помощью mix deps.get
. Как только это будет завершено, мы можем начать строить наш проект. Мы собираемся начать с создания плагина, который отвечает на любой GET
с помощью Hello, world!
, Для этого мы собираемся построить наш модуль Spy
следующим образом:
#lib/spy.ex defmodule Spy do import Plug.Conn def init(options), do: options def call(conn, _opts) do conn |> put_resp_content_type("text/plain") # another plug |> send_resp(200, "Hello, world!") end end
После импорта модуля Plug.Conn
мы определили две функции: init/1
и call/2
. Это только две функции, необходимые для подключения модуля.
Если мы углубимся в функцию call/2
, то увидим, что она также вызывает две заглушки. В этом и заключается прелесть штекеров: поскольку они являются просто чистыми функциями, которые управляют соединением, они, следовательно, являются компонуемыми . Это означает, что любой штекер может вызывать несколько других штекеров для выполнения своей работы. Помните: вилки — это просто функции, которые принимают и возвращают соединение. Это так просто.
Давайте раскрутим сервер, чтобы проверить наш плагин.
$ iex -S mix iex> {:ok, _pid} = Plug.Adapters.Cowboy.http(Spy, []) # => {:ok, #PID<0.201.0>} $ curl http://localhost:4000/ Hello, world!
За исключением: хотя в большинстве случаев мы не хотели бы запускать наш сервер таким многословным образом, эти примеры предназначены для того, чтобы быть скорее дидактическими, чем реалистичными, поэтому этого метода будет достаточно. Этот серверный процесс будет работать до тех пор, пока у вас открыт IEx, поэтому для перезапуска после изменения кода подразумевается, что вы перезапустите сервер, либо снова запустив эту строку кода, либо напечатав recompile
, затем нажав стрелку вверх и найдя строку в твоей истории.
Итак, мы только что проверили наш штекер с curl
и он отлично работал Давайте сделаем еще один шаг и вернем немного JSON.
Шаг 1: Добавьте анализатор JSON в приложение.
Мы собираемся использовать Poison в качестве нашего JSON-кодировщика. Давайте добавим это в наше приложение:
#mix.exs defmodule Spy.Mixfile do use Mix.Project def project do [app: :spy, version: "0.1.0", elixir: "~> 1.3", build_embedded: Mix.env == :prod, start_permanent: Mix.env == :prod, deps: deps()] end def application do # Add Poison as application dependency. [applications: [:logger, :cowboy, :plug, :poison]] end defp deps do [ {:cowboy, "~> 1.0.0"}, {:plug, "~> 1.0"}, # Add Poison as Hex dependency. {:poison, "~> 2.2"} ] end end
Теперь, когда Poison добавлен, нам нужно изменить тип ответа на application/json
а затем закодировать Map в JSON. Это так же просто, как изменить 3 строки кода:
#lib/spy.ex defmodule Spy do # ... (concatenated for brevity) def call(conn, _opts) do # encode to JSON body = %{body: "Hello, world!"} |> Poison.encode! conn |> put_resp_content_type("application/json") # JSON type |> send_resp(200, body) # send it! end # ... end
Давайте проверим это снова с помощью curl
. ПРИМЕЧАНИЕ. Если вы получили сообщение об отсутствующих зависимостях и запуске mix deps.get
, вам следует запустить mix deps.get
. ДРУГОЕ ПРИМЕЧАНИЕ: Вы можете получить наш iex с помощью CTRL + C.
$ curl http://localhost:4000/ {"body": "Hello, world!"}
Это сработало! Теперь, когда у нас есть основы работы с плагинами, давайте создадим основной функционал Spy: перечисление файлов cookie. Не самая эффектная функция, но тем не менее полезная. Давайте составим план, как это реализовать:
- Получить куки из ответа
- Кодировать куки в JSON
- Установите новый файл cookie для демонстрационных целей
Теперь, когда у нас есть план, все должно быть просто пошагово. Давайте перейдем к первому шагу: получите куки от ответа . Звучит просто, но как именно мы должны это реализовать? К счастью, пакеты Elixir (в основном) прекрасно документированы, поэтому мы можем легко найти нужную функцию . При быстром поиске «cookie» появляется список параметров. Который из? Похоже, что функция / плагин fetch_cookies/2
— это именно то, что мы ищем. Итак, давайте добавим это в наше приложение, переопределив то, что передается в наш основной плагин, и выполним шаг 2 в процессе:
#line 7 of lib/spy.ex body = conn |> fetch_cookies |> Map.get(:cookies) |> Poison.encode!
Эта строка просто fetch_cookies
соединение в плагин fetch_cookies
, который затем загружает куки. Эти файлы cookie вместе с подключением Map.get/2
через Map.get/2
, а затем кодируются в JSON. Это оно! Мы только что выполнили 2/3 шагов, но у нас остался еще один: установить новый файл cookie для демонстрационных целей .
В нашем примере мы создадим простой файл cookie, который назначит текущую дату (в виде строки) для файла cookie с ключом hello
. Если мы put_resp_cookie/4
на наши документы по Plug и начнем поиск, то увидим, что put_resp_cookie/4
идеально подходит для этого. Чтобы добавить наш файл cookie, мы просто помещаем этот плагин сразу после первоначального вызова conn
в нашу функцию call/2
. Давайте посмотрим на готовый продукт:
#lib/spy.ex defmodule Spy do import Plug.Conn def init(options), do: options def call(conn, _opts) do body = conn |> fetch_cookies |> Map.get(:cookies) |> Poison.encode! conn |> put_resp_cookie("hello", DateTime.utc_now |> DateTime.to_string) |> put_resp_content_type("application/json") # another plug |> send_resp(200, body) end end
Теперь мы должны перезагрузить сервер и открыть http://localhost:4000/
, но на этот раз в браузере. При первой загрузке вы можете увидеть пустую страницу. Это хорошо! Это означает, что в вашем браузере нет файлов cookie. Теперь, если вы перезагрузите страницу, вы увидите, что наш плагин назначил новый файл cookie с текущим временем (временем, когда файл cookie был назначен).
Почему я не вижу свое печенье при первой перезагрузке? Из-за того, как настроен наш плагин, мы видим куки только после перезагрузки, потому что body
назначается до того, как куки установлены.
В заключение
То, что мы только что создали, показывает лишь незначительное количество полного потенциала плагина. Заглушки составляют основу Phoenix таким же образом, как Rack составляет основу Rails. С помощью плагинов вы можете создавать что угодно, от простых сервисов HTTP до надежных API. Объедините это с быстро растущим сообществом Elixir, чистой скоростью и отказоустойчивой природой Erlang, и вы на пути в рай для разработчиков.