Здесь мы определяем наш класс контроллера, обязательно наследуя от ATH::Controller
. При желании можно использовать пользовательские классы абстрактных контроллеров, чтобы обеспечить общую вспомогательную логику для всех экземпляров контроллера. Затем мы определили метод экземпляра #create_article
, который возвращает ATH::Response
. К этому методу применена аннотация ARTA::Post
, которая указывает, что эта конечная точка является конечной точкой POST, а также путь, по которому должно обрабатываться это действие контроллера. Что касается тела метода, мы создаем экземпляр и преобразуем жестко закодированный экземпляр нашего объекта статьи в JSON, чтобы использовать его в качестве тела нашего ответа. Мы также устанавливаем заголовок типа контента ответа. Отсюда давайте подключим все и убедимся, что все работает как положено.
Возвращаясь к первоначально созданному файлу
require "json"
require "athena"
require "./controllers/*"
require "./entities/*"
module Blog
VERSION = "0.1.0"
module Controllers; end
module Entities; end
end
Здесь нам просто нужна Athena, модуль JSON Crystal, а также папки контроллера и сущностей. Мы также определили здесь пространства имен Controllers
и Entities
, чтобы в будущем к ним можно было добавлять документацию.
Далее давайте создадим еще один файл, который будет служить точкой входа в наш блог, скажем,
require "./blog"
ATH.run
Такой подход гарантирует, что сервер не запустится автоматически, если мы просто хотим запросить исходный код где-то еще, например, в нашем коде спецификации. ATH.run
по умолчанию запустит наш сервер Athena на порту 3000
.
Теперь, когда сервер запущен, если бы мы выполнили следующий запрос, используя cURL, например, curl --request POST 'http://localhost:3000/article'
, мы получили бы следующий ответ, как ожидал:
{
"title": "Title",
"body": "Body"
}
Однако, поскольку мы хотим, чтобы наш API возвращал JSON, есть более простой способ сделать это. Мы можем обновить действие нашего контроллера, чтобы напрямую возвращать экземпляр нашего объекта статьи. Афина позаботится о его преобразовании в JSON и настройке необходимых заголовков. Теперь метод выглядит так:
def create_article : Blog::Entities::Article
Blog::Entities::Article.new "Title", "Body"
end
Если вы отправите еще один запрос, вы увидите тот же ответ. Причина, по которой это работает, связана с ATH::Response
, этот ответ возвращается клиенту в том виде, в каком он есть. Если возвращается что-то еще, генерируется событие ATH::Response
.
Athena также предоставляет некоторые более специализированные подклассы ATH::Response
. Например, ATH::RedirectResponse
можно использовать для обработки перенаправлений, а ATH::StreamedResponse
можно использовать для потоковой передачи данных клиенту посредством фрагментированного кодирования в тех случаях, когда в противном случае данные ответа были бы слишком большими, чтобы поместиться в памяти. Дополнительную информацию об этих подклассах см. в документации API: https://athenaframework.org/Framework/.
Предполагая, что наш API будет обслуживать отдельную базу кода внешнего интерфейса, нам нужно будет настроить CORS, чтобы внешний интерфейс мог получить доступ к данным. Athena поставляется в комплекте с прослушивателем, который его обрабатывает, и его нужно просто включить и настроить.
Чтобы все было организованно, давайте создадим новый файл
def ATH::Config::CORS.conРисунок : ATH::Config::CORS?
new(
allow_credentials: true,
allow_origin: ["*"],
)
end
В идеале значение источника должно быть фактическим доменом вашего приложения, например https://app.myblog.com. Однако в этой главе мы просто позволим все что угодно. Athena также поддерживает концепцию параметров, которые можно использовать для настройки независимо от окружающей среды. Дополнительную информацию см. на https://athenaframework.org/Components/config/.