# ApiRoute

Данный узел служит для описания интерфейса конкретного эндпоинта. Интерфейс схож с [RequestStep](/master/node-types/requeststep.md) узлом. Это и не удивительно - в обоих случаях мы имеем дело с HTTP-запросами.

Основные возможности данного типа узлов:

* Возможность описания http-заголовков, query параметров, body параметров запроса и HTTP-кодов, HTTP-заголовков, body параметров ответа
* Использование типов для описания каждого из заголовков, query параметров, body параметров. Поддерживаются следующие типы: `string`, `number`, `integer`, `boolean`, `array` и `object`.
* Добавление описаний для каждой из сущностей
* Поддержка описания нескольких параметров тела запроса (в зависимости от content-type)
* Поддержка описания нескольких возможный ответов от сервера
* Создание запроса из описания
* Автодополнение урлов, HTTP-заголовков, query параметров и body параметров в [RequestStep](/master/node-types/requeststep.md) узлах.

## Обзор интерфейса

Для создание **ApiRoute** узла необходимо в контекстном меню [ApiFolder](/master/node-types/api-description/apifolder.md) узла выбрать **Add node** -> **ApiRoute.**

### **Вид узла в дереве проекта**

В дереве **ApiRoute** узел выглядит следующим образом:

![Вид ApiRoute узла в дереве проекта](/files/-LiMsjdLErhFxCQUpVzR)

В качестве иконки у данного вида узла выступает название HTTP-метода. Контекстное меню выглядит следующим образом:

![Контекстное меню ApiRoute узла](/files/-LiMslz8Y5XicOHnnV8p)

* **Rename.** Переименовать узел.
* **Duplicate.** Сделать копию узла. Новый узел будет иметь название NodeName \[Copy \[number]].
* **Remove node.** Удалить узел.
* **Show in explorer.** Открыть папку с узлом в файловом менеджере.

### Интерфейс вкладки

Вкладка **ApiRoute** узла выглядит следующим образом:

![Вкладка ApiRoute узла](/files/-LiMspLCONT78JfocOc6)

#### Области общих параметров запроса

Рассмотрим подробнее верхнюю часть данной вкладки:

![Верхняя часть таба ApiRoute узла](/files/-LiMsscrBJx53fsqf00u)

На скрине обозначены следующие области:

1. Http-метод. Данный список совпадает со списком методов из [RequestStep](/master/node-types/requeststep.md) узла
2. Url с поддержкой [механизма переменных](/master/variables/variables.md)
3. Кнопка открытия [диалога работы с переменными](/master/variables/user-variables.md)
4. Кнопка создания запроса из текущего описания API
5. Текстовое описание запроса

#### Область описания параметров запросов

В левой нижней части расположена область описания запроса. Она разделена на 3 вкладки: **Headers**, **Query parameters** и **Body** для редактирования HTTP-заголовков, query параметров и параметров тела запроса соответственно.

Рассмотрим вкладку **Headers**. Ее содержимое представлено в табличном виде. Для редактирования заголовков доступны следующие поля:

* Название заголовка
* Тип значения заголовка (список типов описан выше)
* Описание

Поддерживаются все стандартные операции.

Вкладка **Query Parameters** используется для редактирования query параметров, в остальном по функционалу идентична вкладке **Headers**.

Как уже было сказано, в **ApiRoute** узле можно описать несколько тел для одного и того же запроса. Например, по одному и тому же эндпоинту могут приниматься как данные с `Content-Type` равным `application/json`, так и с `application/xml`. Вкладка **Body** разделена как раз по `content-type` на вкладки и имеет следующий вид:

![Вид вкладки Body интерфейса описания запроса](/files/-LiMsvmecyriXA8KhPQP)

На скрине отмечены следующие области:

1. Кнопка редактирования текущего `content-type`. При нажатии на нее данное поле подменяется на текстовое поле, где можно ввести интересующий `content-type`.
2. Кнопка удаления тела запроса
3. Кнопка добавления тела запроса
4. Текущий `content-type` узла
5. Область редактирования тела запроса

Область редактирования тела запроса меняется в зависимости от `content-type` по следующему правилу: если `content-type` равен `application/x-www-form-urlencoded` или `multipart/form-data`, то область редактирования принимает табличный вид (аналогичный табличной области в **Headers** вкладке), в противном случае - текстовый как на скрине выше. В текстовой области в качестве формата описания используется [OpenAPI](https://swagger.io/specification/#requestBodyObject).

#### Область описания параметров запросов

В правой нижней области интерфейса вкладки **ApiRoute** узла расположена области редактирования ответов от сервера. Как уже было сказано, TestMace поддерживает описание нескольких ответов в рамках одного эндпоинта. Интерфейс данной области выглядит следующим образом:

![Интерфейс редактирования ответов сервера](/files/-LiMszNK7ApEdzbaBel_)

Данный интерфейс разделен на вкладки, отдельно для каждого ответа. В рамках вкладки каждого ответа можно редактировать код ответа, описание, а также HTTP-заголовки и тела ответа, интерфейсы которых идентичны таковым из области запроса.

## Интеграция с RequestStep узлом

TestMace имеет интеграцию с **ApiRoute** узлами в **RequestStep** узлах. На данный момент эта интеграция проявляется в автодополнении url, HTTP-заголовков, query параметров, параметров тела запросов **RequestStep** узлов. Причем, для url-ов в автодополнении участвуют всех url-ы **ApiRoute** узлов, тогда как для остальных параметров автодополнение работает по следующему алгоритму:

* Берутся метод и url данного **RequestStep** узла
* Ищутся все **ApiRoute** узлы с такими url и методом
* Осуществляется поиск по искомому параметру (например, по HTTP-заголовку) среди найденных **ApiRoute** узлов

## Файловое представление

**ApiRoute** узел представляет из себя папку с названием узла, внутри которой содержится файл index.yml, имеющий следующий формат.

```javascript
{
  "type": "object",
  "properties": {
    "type": {
      "description": "Type of ApiRoute node",
      "const": "ApiRoute",
      "type": "string"
    },
    "url": {
      "type": "string",
      "default": ""
    },
    "method": {
      "$ref": "#/definitions/RequestMethod"
    },
    "description": {
      "type": "string",
      "default": ""
    },
    "requests": {
      "$ref": "#/definitions/ApiRequests",
      "description": "List of requests"
    },
    "responses": {
      "description": "List of responses",
      "type": "array",
      "items": {
        "$ref": "#/definitions/ResponseParameters"
      },
      "default": []
    },
    "children": {
      "description": "List of children names",
      "type": "array",
      "items": {
        "type": "string"
      },
      "default": []
    },
    "variables": {
      "$ref": "#/definitions/NodeVariables",
      "description": "Node variables dictionary"
    },
    "name": {
      "description": "Node name",
      "type": "string"
    }
  },
  "required": [
    "children",
    "description",
    "method",
    "name",
    "requests",
    "responses",
    "type",
    "url",
    "variables"
  ],
  "definitions": {
    "RequestMethod": {
      "enum": [
        "DELETE",
        "GET",
        "OPTIONS",
        "PATCH",
        "POST",
        "PUT"
      ],
      "type": "string"
    },
    "ApiRequests": {
      "type": "object",
      "properties": {
        "queryParameters": {
          "description": "List of query parameters",
          "type": "array",
          "items": {
            "$ref": "#/definitions/QueryParameter"
          }
        },
        "headers": {
          "description": "List of headers",
          "type": "array",
          "items": {
            "$ref": "#/definitions/QueryParameter"
          }
        },
        "cookies": {
          "description": "List of cookies",
          "type": "array",
          "items": {
            "$ref": "#/definitions/QueryParameter"
          }
        },
        "bodies": {
          "description": "List of bodies",
          "type": "array",
          "items": {
            "$ref": "#/definitions/RequestParameters"
          },
          "default": []
        }
      },
      "required": [
        "bodies",
        "cookies",
        "headers",
        "queryParameters"
      ]
    },
    "QueryParameter": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        },
        "type": {
          "enum": [
            "array",
            "boolean",
            "integer",
            "number",
            "object",
            "string"
          ],
          "type": "string"
        },
        "description": {
          "type": "string"
        }
      },
      "required": [
        "name",
        "type"
      ]
    },
    "RequestParameters": {
      "type": "object",
      "properties": {
        "contentType": {
          "type": "string"
        },
        "schema": {
          "anyOf": [
            {
              "$ref": "#/definitions/SchemaRef"
            },
            {
              "$ref": "#/definitions/OneOf"
            },
            {
              "$ref": "#/definitions/AllOf"
            },
            {
              "$ref": "#/definitions/AnyOf"
            },
            {
              "$ref": "#/definitions/ObjectMember"
            },
            {
              "$ref": "#/definitions/ArrayMember"
            },
            {
              "$ref": "#/definitions/ScalarMember"
            }
          ]
        }
      },
      "required": [
        "contentType",
        "schema"
      ]
    },
    "SchemaRef": {
      "type": "object",
      "properties": {
        "$ref": {
          "type": "string"
        }
      },
      "required": [
        "$ref"
      ]
    },
    "OneOf": {
      "type": "object",
      "properties": {
        "oneOf": {
          "type": "array",
          "items": {
            "anyOf": [
              {
                "$ref": "#/definitions/SchemaRef"
              },
              {
                "$ref": "#/definitions/OneOf"
              },
              {
                "$ref": "#/definitions/AllOf"
              },
              {
                "$ref": "#/definitions/AnyOf"
              },
              {
                "$ref": "#/definitions/ObjectMember"
              },
              {
                "$ref": "#/definitions/ArrayMember"
              },
              {
                "$ref": "#/definitions/ScalarMember"
              }
            ]
          }
        }
      },
      "required": [
        "oneOf"
      ]
    },
    "AllOf": {
      "type": "object",
      "properties": {
        "allOf": {
          "type": "array",
          "items": {
            "anyOf": [
              {
                "$ref": "#/definitions/SchemaRef"
              },
              {
                "$ref": "#/definitions/OneOf"
              },
              {
                "$ref": "#/definitions/AllOf"
              },
              {
                "$ref": "#/definitions/AnyOf"
              },
              {
                "$ref": "#/definitions/ObjectMember"
              },
              {
                "$ref": "#/definitions/ArrayMember"
              },
              {
                "$ref": "#/definitions/ScalarMember"
              }
            ]
          }
        }
      },
      "required": [
        "allOf"
      ]
    },
    "AnyOf": {
      "type": "object",
      "properties": {
        "anyOf": {
          "type": "array",
          "items": {
            "anyOf": [
              {
                "$ref": "#/definitions/SchemaRef"
              },
              {
                "$ref": "#/definitions/OneOf"
              },
              {
                "$ref": "#/definitions/AllOf"
              },
              {
                "$ref": "#/definitions/AnyOf"
              },
              {
                "$ref": "#/definitions/ObjectMember"
              },
              {
                "$ref": "#/definitions/ArrayMember"
              },
              {
                "$ref": "#/definitions/ScalarMember"
              }
            ]
          }
        }
      },
      "required": [
        "anyOf"
      ]
    },
    "ObjectMember": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "object"
          ]
        },
        "properties": {
          "$ref": "#/definitions/SchemaMember"
        },
        "required": {
          "type": "boolean"
        },
        "additionalProperties": {
          "$ref": "#/definitions/ScalarMember"
        },
        "description": {
          "type": "string"
        }
      },
      "required": [
        "type"
      ]
    },
    "SchemaMember": {
      "type": "object",
      "additionalProperties": {
        "anyOf": [
          {
            "$ref": "#/definitions/SchemaRef"
          },
          {
            "$ref": "#/definitions/OneOf"
          },
          {
            "$ref": "#/definitions/AllOf"
          },
          {
            "$ref": "#/definitions/AnyOf"
          },
          {
            "$ref": "#/definitions/ObjectMember"
          },
          {
            "$ref": "#/definitions/ArrayMember"
          },
          {
            "$ref": "#/definitions/ScalarMember"
          }
        ]
      }
    },
    "ArrayMember": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "array"
          ]
        },
        "items": {
          "anyOf": [
            {
              "$ref": "#/definitions/SchemaRef"
            },
            {
              "$ref": "#/definitions/OneOf"
            },
            {
              "$ref": "#/definitions/AllOf"
            },
            {
              "$ref": "#/definitions/AnyOf"
            },
            {
              "$ref": "#/definitions/ObjectMember"
            },
            {
              "$ref": "#/definitions/ArrayMember"
            },
            {
              "$ref": "#/definitions/ScalarMember"
            }
          ]
        },
        "description": {
          "type": "string"
        }
      },
      "required": [
        "items",
        "type"
      ]
    },
    "ScalarMember": {
      "type": "object",
      "properties": {
        "type": {
          "$ref": "#/definitions/ScalarSchemaType"
        },
        "description": {
          "type": "string"
        }
      },
      "required": [
        "type"
      ]
    },
    "ScalarSchemaType": {
      "enum": [
        "boolean",
        "integer",
        "number",
        "string"
      ],
      "type": "string"
    },
    "ResponseParameters": {
      "type": "object",
      "properties": {
        "code": {
          "description": "Http-code (e.g. 200, 404)",
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "headers": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/QueryParameter"
          }
        },
        "content": {
          "$ref": "#/definitions/RequestParameters",
          "description": "Response body"
        }
      },
      "required": [
        "code",
        "content"
      ]
    },
    "NodeVariables": {
      "type": "object",
      "additionalProperties": {
        "type": "string"
      }
    }
  },
  "$schema": "http://json-schema.org/draft-07/schema#"
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs-ru.testmace.com/master/node-types/api-description/apiroute.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
