Перейти к основному содержимому

Модульный RAML с использованием включений, библиотек, наложений и расширений

· 9 мин. чтения

1. Введение

В наших первых двух статьях о RAML — языке моделирования RESTful API — мы представили некоторый базовый синтаксис, включая использование типов данных и схемы JSON, и показали, как упростить определение RAML путем извлечения общих шаблонов в типы ресурсов и признаки .

В этой статье мы покажем, как можно разбить определение RAML API на модули , используя включения , библиотеки , наложения и расширения .

2. Наш API

В этой статье мы сосредоточимся на части нашего API, включающей тип сущности под названием Foo .

Вот ресурсы, из которых состоит наш API:

  • ПОЛУЧИТЬ /api/v1/foos
  • ПОСТ /api/v1/foos
  • ПОЛУЧИТЬ /api/v1/foos/{fooId}
  • ПОСТАВЬТЕ /api/v1/foos/{fooId}
  • УДАЛИТЬ /api/v1/foos/{fooId}

3. Включает

Целью включения является модульность значения сложного свойства в определении RAML путем помещения значения свойства во внешний файл.

В нашей первой статье кратко упоминалось об использовании включений, когда мы указывали типы данных и примеры, свойства которых повторялись во всем API.

3.1. Общее использование и синтаксис

Тег !include принимает единственный аргумент: расположение внешнего файла, содержащего значение свойства. Это местоположение может быть абсолютным URL-адресом, путем относительно корневого файла RAML или путем относительно файла включения.

Расположение, начинающееся с косой черты (/), указывает путь относительно расположения корневого файла RAML, а расположение, начинающееся без косой черты, интерпретируется как относительно расположения включающего файла.

Логическим следствием последнего является то, что включаемый файл может сам содержать другие директивы !include .

Вот пример, показывающий все три варианта использования тега !include :

#%RAML 1.0
title: ForEach Foo REST Services API
...
types: !include /types/allDataTypes.raml
resourceTypes: !include allResourceTypes.raml
traits: !include http://foo.com/docs/allTraits.raml

3.2. Типизированные фрагменты

Вместо того, чтобы помещать все типы , типы ресурсов или черты в их собственные включаемые файлы, вы также можете использовать специальные типы включений , известные как типизированные фрагменты , чтобы разбить каждую из этих конструкций на несколько включаемых файлов, указав разные файлы для каждого типа , ресурса . тип или черта .

Вы также можете использовать типизированные фрагменты для определения элементов пользовательской документации , именованных примеров , аннотаций , библиотек , наложений и расширений . Мы рассмотрим использование наложений и расширений позже в этой статье.

Хотя это и не обязательно, первая строка включаемого файла, которая является типизированным фрагментом , может быть идентификатором фрагмента RAML следующего формата:

#%RAML 1.0 <fragment-type>

Например, первая строка файла типизированного фрагмента для признака будет выглядеть так:

#%RAML 1.0 Trait

Если используется идентификатор фрагмента, то содержимое файла ДОЛЖНО содержать только действительный RAML для указанного типа фрагмента.

Давайте сначала посмотрим на часть раздела характеристик нашего API :

traits:
- hasRequestItem:
body:
application/json:
type: <<typeName>>
- hasResponseItem:
responses:
200:
body:
application/json:
type: <<typeName>>
example: !include examples/<<typeName>>.json

Чтобы разделить этот раздел на модули с помощью типизированных фрагментов , мы сначала перепишем раздел свойств следующим образом:

traits:
- hasRequestItem: !include traits/hasRequestItem.raml
- hasResponseItem: !include traits/hasResponseItem.raml

Затем мы напишем типизированный файл фрагмента hasRequestItem.raml :

#%RAML 1.0 Trait
body:
application/json:
type: <<typeName>>

Типизированный файл фрагмента hasResponseItem.raml будет выглядеть так:

#%RAML 1.0 Trait
responses:
200:
body:
application/json:
type: <<typeName>>
example: !include /examples/<<typeName>>.json

4. Библиотеки

Библиотеки RAML могут использоваться для модуляции любого количества и комбинаций типов данных , схем безопасности , типов ресурсов , признаков и аннотаций .

4.1. Определение библиотеки

Хотя библиотека обычно определяется во внешнем файле, на который затем ссылаются как на include , библиотека также может быть определена встроенной. Библиотека , содержащаяся во внешнем файле, также может ссылаться на другие библиотеки .

В отличие от обычного включения или типизированного фрагмента , библиотека , содержащаяся во внешнем файле, должна объявлять имена определяемых элементов верхнего уровня.

Давайте перепишем наш раздел свойств в виде библиотечного файла:

#%RAML 1.0 Library
# This is the file /libraries/traits.raml
usage: This library defines some basic traits
traits:
hasRequestItem:
usage: Use this trait for resources whose request body is a single item
body:
application/json:
type: <<typeName>>
hasResponseItem:
usage: Use this trait for resources whose response body is a single item
responses:
200:
body:
application/json:
type: <<typeName>>
example: !include /examples/<<typeName>>.json

4.2. Применение библиотеки

Библиотеки применяются через использование свойства верхнего уровня, значением которого является один или несколько объектов, имена свойств которых являются именами библиотек , а значения свойств составляют содержимое библиотек .

После того, как мы создали библиотеки для наших схем безопасности , типов данных , типов ресурсов и трейтов , мы можем применить библиотеки к корневому RAML-файлу:

#%RAML 1.0
title: ForEach Foo REST Services API
uses:
mySecuritySchemes: !include libraries/security.raml
myDataTypes: !include libraries/dataTypes.raml
myResourceTypes: !include libraries/resourceTypes.raml
myTraits: !include libraries/traits.raml

4.3. Ссылка на библиотеку

Ссылка на библиотеку осуществляется путем объединения имени библиотеки , точки (.) и имени элемента (например, типа данных, типа ресурса, признака и т. д.), на который делается ссылка.

Вы можете вспомнить из нашей предыдущей статьи , как мы реорганизовали наши типы ресурсов, используя определенные признаки . В следующем примере показано, как переписать наш тип ресурса «предмет» в качестве библиотеки, как включить файл библиотеки признаков (показан выше) в новую библиотеку и как ссылаться на свойства , добавляя к именам свойств префикс с квалификатором имени библиотеки ( « мои черты »):

#%RAML 1.0 Library
# This is the file /libraries/resourceTypes.raml
usage: This library defines the resource types for the API
uses:
myTraits: !include traits.raml
resourceTypes:
item:
usage: Use this resourceType to represent any single item
description: A single <<typeName>>
get:
description: Get a <<typeName>> by <<resourcePathName>>
is: [ myTraits.hasResponseItem, myTraits.hasNotFound ]
put:
description: Update a <<typeName>> by <<resourcePathName>>
is: [ myTraits.hasRequestItem, myTraits.hasResponseItem, myTraits.hasNotFound ]
delete:
description: Delete a <<typeName>> by <<resourcePathName>>
is: [ myTraits.hasNotFound ]
responses:
204:

5. Наложения и расширения

Наложения и расширения — это модули, определенные во внешних файлах, которые используются для расширения API. Наложение используется для расширения неповеденческих аспектов API, таких как описания, инструкции по использованию и элементы пользовательской документации, тогда как расширение используется для расширения или переопределения поведенческих аспектов API.

В отличие от include , на которые ссылаются другие файлы RAML для применения, как если бы они были встроены в код, все файлы наложений и расширений должны содержать ссылку (через свойство masterRef верхнего уровня ) на свой мастер-файл, который может быть либо действительным Определение API RAML или другой файл наложения или расширения , к которому они должны быть применены.

5.1. Определение

Первая строка файла наложения или расширения должна быть отформатирована следующим образом:

RAML 1.0 Overlay

И первая строка файла оверлея должна быть отформатирована аналогично:

RAML 1.0 Extension

5.2. Ограничения использования

При использовании набора наложений и/или расширений все они должны ссылаться на один и тот же основной файл RAML. Кроме того, инструменты обработки RAML обычно ожидают, что корневой файл RAML и все файлы наложений и расширений будут иметь общее расширение файла (например, «.raml»).

5.3. Примеры использования наложений

Мотивация оверлеев состоит в том, чтобы предоставить механизм для отделения интерфейса от реализации, что позволяет более ориентированным на человека частям определения RAML изменяться или расширяться чаще, в то время как основные поведенческие аспекты API остаются стабильными.

Распространенным вариантом использования наложений является предоставление пользовательской документации и других описательных элементов на нескольких языках. Давайте перепишем название нашего API и добавим некоторые элементы пользовательской документации:

#%RAML 1.0
title: API for REST Services used in the RAML tutorials on ForEach.com
documentation:
- title: Overview
- content: |
This document defines the interface for the REST services
used in the popular RAML Tutorial series at ForEach.com.
- title: Copyright
- content: Copyright 2016 by ForEach.com. All rights reserved.

Вот как мы бы определили наложение на испанском языке для этого раздела:

#%RAML 1.0 Overlay
# File located at (archivo situado en):
# /overlays/es_ES/documentationItems.raml
masterRef: /api.raml
usage: |
To provide user documentation and other descriptive text in Spanish
(Para proporcionar la documentación del usuario y otro texto descriptivo
en español)
title: |
API para servicios REST utilizados en los tutoriales RAML
en ForEach.com
documentation:
- title: Descripción general
- content: |
Este documento define la interfaz para los servicios REST
utilizados en la popular serie de RAML Tutorial en ForEach.com.
- title: Derechos de autor
- content: |
Derechos de autor 2016 por ForEach.com.
Todos los derechos reservados.

Другим распространенным вариантом использования наложений является экстернализация метаданных аннотаций , которые, по сути, представляют собой способ добавления нестандартных конструкций в API, чтобы предоставить крючки для процессоров RAML, такие как инструменты тестирования и мониторинга.

5.4. Примеры использования расширений

Как вы можете догадаться из названия, расширения используются для расширения API путем добавления новых вариантов поведения и/или изменения существующих вариантов поведения API. Аналогией из мира объектно-ориентированного программирования может быть подкласс, расширяющий суперкласс, где подкласс может добавлять новые методы и/или переопределять существующие методы. Расширение также может расширять нефункциональные аспекты API.

Расширение можно использовать, например, для определения дополнительных ресурсов, доступных только избранному набору пользователей, например, администраторам или пользователям, которым назначена определенная роль . Расширение также можно использовать для добавления функций для более новой версии API .

Ниже приведено расширение , которое переопределяет версию нашего API и добавляет ресурсы, недоступные в предыдущей версии:

#%RAML 1.0 Extension
# File located at:
# /extensions/en_US/additionalResources.raml
masterRef: /api.raml
usage: This extension defines additional resources for version 2 of the API.
version: v2
/foos:
/bar/{barId}:
get:
description: |
Get the foo that is related to the bar having barId = {barId}
typeName: Foo
queryParameters:
barId?: integer
typeName: Foo
is: [ hasResponseItem ]

А вот оверлей на испанском языке для этого расширения :

#%RAML 1.0 Overlay
# Archivo situado en:
# /overlays/es_ES/additionalResources.raml
masterRef: /api.raml
usage: |
Se trata de un español demasiado que describe los recursos adicionales
para la versión 2 del API.
version: v2
/foos:
/bar/{barId}:
get:
description: |
Obtener el foo que se relaciona con el bar tomando barId = {barId}

Здесь стоит отметить, что, хотя в этом примере мы использовали оверлей для переопределений на испанском языке, поскольку он не изменяет поведение API, мы могли бы с таким же успехом определить этот модуль как расширение . И его может быть более уместно определить как расширение , учитывая, что его целью является переопределение свойств, найденных в англоязычном расширении над ним.

6. Заключение

В этом руководстве мы представили несколько методов, позволяющих сделать определение API RAML более модульным путем разделения общих конструкций во внешние файлы.

Во-первых, мы показали, как функцию включения в RAML можно использовать для рефакторинга отдельных сложных значений свойств в многократно используемые внешние файловые модули, известные как типизированные фрагменты . Затем мы продемонстрировали способ использования функции включения для преобразования определенных наборов элементов в повторно используемые библиотеки . Наконец, мы расширили некоторые поведенческие и неповеденческие аспекты API за счет использования оверлеев и расширений .

Чтобы узнать больше о методах модульности RAML, посетите спецификацию RAML 1.0 .

Вы можете просмотреть полную реализацию определения API, используемого для этого руководства, в проекте github .