Как создать YAML-документацию с использованием атрибутов документации EMS

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

Я следовал руководству в вики по созданию первого ресурса EMS до развертывания на тестовом сервере EMS. Это работает нормально, без сбоев.

Однако когда я дойду до руководства документации по пользовательскому API, оно просто не Работа.

Я просмотрел сообщение Стивена Болла на SWAGGER / YAML И САМОДОКУМЕНТИРОВАНИЕ ВОССТАНОВЛЕНИЕ API. К сожалению, он использует проект RAD Studio EMS Sample, который отлично работает даже у меня. Но как только я пытаюсь применить те же атрибуты к своему собственному пакету EMS, это не срабатывает.

Когда я вызываю htt????: // localhost: 8080 / api / apidoc.yaml, сервер возвращает:

{
  "error":"Error",
  "description":"Error: No Responses defined for: get "
}

Сервер разработки EMS имеет следующие соответствующие записи журнала:

{"Request":{"Resource":"API","Endpoint":"GetAPIYAMLFormat","Method":"GET","User":"(blank)","Time":"2017/08/11 12:59:46 AM","Thread":1732}}
{"Error":{"Type":"HTTP","Code":"500","Reason":"Error","Error":"","Description":"Error: No Responses defined for: get ","Thread":1732}}

Вот фрагмент моего кода из учебника:

unit Unit1;

// EMS Resource Unit

interface

uses
  System.SysUtils, System.Classes, System.JSON,
  EMS.Services, EMS.ResourceAPI,
  EMS.ResourceTypes, APIDocumentationEndPointObjectsDefinitions;

type
  [ResourceName('Test')]
  [EndPointObjectsYAMLDefinitions(YAMLDefinitions)]
  [EndPointObjectsJSONDefinitions(JSONDefinitions)]

  {$METHODINFO ON}
  TTestResource = class
  published
    // Declare the function
    function MakeJSON(I: Integer): TJSONObject; //It takes an integer as a parameter and returns a JSON Object.
    [EndPointRequestSummary('Items', 'Get items', 'Used to retrieve all the items', 'application/json', '')]
    [EndPointRequestParameter(TAPIDocParameter.TParameterIn.Path, 'Test', 'Path Parameter item Description', false, TAPIDoc.TPrimitiveType.spString, TAPIDoc.TPrimitiveFormat.None, TAPIDoc.TPrimitiveType.spString, '', '')]
    [EndPointResponseDetails(200, 'Ok', TAPIDoc.TPrimitiveType.spObject, TAPIDoc.TPrimitiveFormat.None, '', '#/definitions/items')]
    procedure Get(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    [ResourceSuffix('{item}')]
    procedure GetItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
  end;
  {$METHODINFO OFF}

implementation
const
  TestValues: array [0 .. 2] of string = ('a', 'b', 'c'); // It creates an array of string values.

procedure TTestResource.Get(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
var
  LJSON: TJSONArray;
  I: Integer;
begin
  LJSON := TJSONArray.Create;
  for I := Low(TestValues) to High(TestValues) do
    LJSON.Add(MakeJSON(I)); //[{"index":0,"value":"a"},{"index":1,"value":"b"},{"index":2,"value":"c"}]
  AResponse.Body.SetValue(LJSON, True) // True causes AResponse to free JSON
end;

procedure TTestResource.GetItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
var
  I: Integer;
begin
  if not TryStrToInt(ARequest.Params.Values['item'], I) then //{"index":I,"value":value}
    AResponse.RaiseBadRequest('Index expected');
  if (I < 0) or (I >= Length(TestValues)) then
    AResponse.RaiseBadRequest('Index out of range');
  AResponse.Body.SetValue(MakeJSON(I), True);
  // True causes AResponse to free JSON
end;

function TTestResource.MakeJSON(I: Integer): TJSONObject;
begin
  Result := TJSONObject.Create;
  Result.AddPair('index', TJSONNumber.Create(I)); //Adds to the JSON object a pair {"index": I}, the index number.
  Result.AddPair('value', TJSONString.Create(TestValues[I])); //Adds to the the JSON object a pair {"value":String}, the string corresponding to the index number.

end;

procedure Register;
begin
  RegisterResource(TypeInfo(TTestResource));
end;

initialization
  Register;
end.

Похоже, что в образце проекта что-то отсутствует в коде, созданном мастером пакетов RAD Studio EMS.

Мне интересно, смог ли кто-нибудь использовать новые атрибуты документации EMS для создания документации YAML из своего собственного пакета EMS, а не образец проекта, поставляемый с RAD Studio?

Кто-нибудь еще испытал это? Возможно ли, что метод get не был полностью реализован. Есть ли исправление для этого (я только что обновился до RAD Studio 10.2.1)?


person Ngoni Simelane    schedule 14.09.2017    source источник


Ответы (2)


Это будет работать, если вы запустите EMSDevServer.exe без нагрузки, например:

{"ConfigLoaded":{"Filename":"C:\Users\Public\Documents\Embarcadero\EMS\emsserver.ini","Thread":924}}
{"DBConnection":{"InstanceName":"gds_db","Filename":"C:\Users\Public\Documents\Embarcadero\EMS\emsserver.ib","Thread":924}}
{"Licensing":{"Licensed":false,"DefaultMaxUsers":5,"Thread":924}}
{"RegResource":{"Resource":"Version","Endpoints":["GetVersion"],"Thread":924}}
{"RegResource":{"Resource":"API","Endpoints":["API","GetAPIYAMLFormat EndPoint","GetAPIYAMLFormat","GetAPIJSONFormat"],"Thread":924}}
{"RegResource":{"Resource":"Users","Endpoints":["GetUsers","GetUser","GetUserFields","GetUserGroups","SignupUser","LoginUser","AddUser","UpdateUser","DeleteUser"],"Thread":924}}
{"RegResource":{"Resource":"Groups","Endpoints":["GetGroups","GetGroup","GetGroupFields","AddGroup","UpdateGroup","DeleteGroup"],"Thread":924}}
{"RegResource":{"Resource":"Installations","Endpoints":["GetInstallations","GetChannels","GetInstallationFields","GetInstallation","AddInstallation","UpdateInstallation","DeleteInstallation"],"Thread":924}}
{"RegResource":{"Resource":"Push","Endpoints":["Send"],"Thread":924}}
{"RegResource":{"Resource":"Edgemodules","Endpoints":["GetModules","GetModule","GetResources","GetModuleResources","GetModulesFields","GetResourcesFields","GetModuleResource","RegisterModule","RegisterModuleResource","UpdateModule","UpdateModuleResource","UnregisterModule","UnregisterModuleResource","GetResourceEndpoint","GetResourceEndpointItem","PutResourceEndpoint","PutResourceEndpointItem","PostResourceEndpoint","PostResourceEndpointItem","PatchResourceEndpoint","PatchResourceEndpointItem","DeleteResourceEndpoint","DeleteResourceEndpointItem"],"Thread":924}}
{"Request":{"Resource":"API","Endpoint":"GetAPIJSONFormat","Method":"GET","User":"(blank)","Time":"06.11.2017 15:42:28","Thread":8672}}

Ни при каких нагрузках не запускается, видимо это ошибка.

person Torbins    schedule 06.11.2017

Вы должны включить EndPointRequestSummary и EndPointResponseDetails перед каждой процедурой конечной точки, иначе файлы apidoc.yaml и apidoc.json вернут ошибку. В вашем случае у вас есть MakeJSON, Get и GetItem.

Вот две строки из примера проекта APIDocAttributes.

[EndPointRequestSummary('Sample Tag', 'Summary Title', 'Get Method Description', 'application/json', '')]
[EndPointResponseDetails(200, 'Ok', TAPIDoc.TPrimitiveType.spObject, TAPIDoc.TPrimitiveFormat.None, '', '')]

Итак, ваш код может выглядеть примерно так:

  TTestResource = class
  published
    // Declare the function
    [EndPointRequestSummary('Sample Tag', 'Summary Title', 'Get Method Description', 'application/json', '')]
    [EndPointResponseDetails(200, 'Ok', TAPIDoc.TPrimitiveType.spObject, TAPIDoc.TPrimitiveFormat.None, '', '')]
    function MakeJSON(I: Integer): TJSONObject; //It takes an integer as a parameter and returns a JSON Object.

    [EndPointRequestSummary('Sample Tag', 'Summary Title', 'Get Method Description', 'application/json', '')]
    [EndPointResponseDetails(200, 'Ok', TAPIDoc.TPrimitiveType.spObject, TAPIDoc.TPrimitiveFormat.None, '', '')]
    procedure Get(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);

    [ResourceSuffix('{item}')]
    [EndPointRequestSummary('Sample Tag', 'Summary Title', 'Get Method Description', 'application/json', '')]
    [EndPointResponseDetails(200, 'Ok', TAPIDoc.TPrimitiveType.spObject, TAPIDoc.TPrimitiveFormat.None, '', '')]
    procedure GetItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
  end;
person FMXExpress    schedule 21.03.2019