我刚开始尝试使用RAD Server。使投资具有吸引力的特性之一是自我记录API的功能,它可以节省大量工作来支持连接到我们REST接口的外部合作伙伴,并且不需要维护单独的接口规范文档,这些文档总是落后发展。
我已经按照wiki中的教程创建了第一个EMS资源,一直到部署到测试EMS服务器。这很好,没有任何障碍。
然而,当我到达custom API documentation教程时,它只是无法正常工作。
我看过斯蒂芬·鲍尔在SWAGGER / YAML AND 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)?
答案 0 :(得分: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}}
任何负载都没有运行,可能是一个错误。
答案 1 :(得分: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;