3

我刚刚开始尝试使用 RAD 服务器。使投资具有吸引力的功能之一是自记录 API 的功能,这将在支持外部合作伙伴连接到我们的 REST 接口方面节省大量工作,并且无需维护单独的接口规范文档,这总是会落后的发展。

我已按照 wiki 中的教程创建自己的第一个 EMS 资源,一直到部署到测试 EMS 服务器。这工作正常,没有任何障碍。

但是,当我到达自定义 API 文档教程时,它根本不起作用。

我看过 Stephen Ball 在SWAGGER / YAML 和 SELF DOCUMENTING RESTFUL API'S上的帖子。不幸的是,他使用了 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 文档属性从他们自己的 EMS 包创建 YAML 文档——而不是 RAD Studio 提供的示例项目?

有没有其他人经历过这个?是否可能 get 方法尚未完全实现。有解决办法吗(我刚刚更新到 RAD Studio 10.2.1)?

4

2 回答 2

0

如果您在没有任何负载的情况下运行 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}}

任何负载它都不会运行,可能是一个错误。

于 2017-11-06T14:54:32.717 回答
0

您必须在每个端点过程上方包含 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;
于 2019-03-21T13:01:57.743 回答