可以通过URI传递RemObjects SDK参数吗?

nor*_*aul 5 delphi uri remobjects delphi-xe2

我们有一个RemObjects SDK HTTP服务器,它公开了许多服务和方法.是否可以通过URI调用方法,而不是将参数作为SOAP/JSON传递,例如

http://www.mywebservice.com/servicename/methodname?param1=xxx&param2=yyy
Run Code Online (Sandbox Code Playgroud)

nor*_*aul 3

更新

\n\n

我编写了服务器后代的改进版本。该函数将格式化的 URI 转换为 JSON 对象,随后由 RO JSON 消息处理程序处理。

\n\n

默认处理方法是忽略 URI。

\n\n

更改URIHandlingMethodurhJSON接受如下 URI:

\n\n
http://www.mywebservice.com/json?{JSON OBJECT}\n
Run Code Online (Sandbox Code Playgroud)\n\n

设置URIHandlingMethodurhParametersto接受这样的 URI:

\n\n
http://www.mywebservice.com/json/service/method?param1=xxx&param2=yyy\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是代码:

\n\n
unit ROJSONURIIndyHTTPServer ;\n\ninterface\n\nuses\n  SysUtils, Classes,\n\n  uROIndyHTTPServer,\n\n  IdURI, IdCustomHTTPServer;\n\ntype\n  TURIHandlingMethod = (\n    urhNone,\n    urhJSON,\n    urhParameters\n  );\n\n  TROJSONURIIndyHTTPServer = class(TROIndyHTTPServer)\n  private\n    FURIHandlingMethod: TURIHandlingMethod;\n    FJSONVersion: String;\n\n    function ConvertURIToJSON(const Document, Params: String): String;\n    function NextBlock(var Value: String; Delimiter: Char = \'/\'): String;\n  protected\n    procedure InternalServerCommandGet(AThread: TIdThreadClass; RequestInfo: TIdHTTPRequestInfo; ResponseInfo: TIdHTTPResponseInfo); override;\n  public\n    constructor Create(AOwner: TComponent); override;\n  published\n    property URIHandlingMethod: TURIHandlingMethod read FURIHandlingMethod write FURIHandlingMethod;\n    property JSONVersion: String read FJSONVersion write FJSONVersion;\n  end;\n\nimplementation\n\n{ TROJSONURIIndyHTTPServer }\n\nconstructor TROJSONURIIndyHTTPServer.Create(AOwner: TComponent);\nbegin\n  inherited;\n\n  FJSONVersion := \'1.1\';\nend;\n\nfunction TROJSONURIIndyHTTPServer.NextBlock(var Value: String; Delimiter: Char): String;\nvar\n  p: Integer;\nbegin\n  p := 1;\n\n  while (p <= length(Value)) and (Value[p] <> Delimiter) do\n    Inc(p);\n\n  if p = length(Value) then\n    Result := Value\n  else\n    Result := copy(Value, 1, p - 1);\n\n  Value := copy(Value, p + 1, MaxInt);\nend;\n\nfunction TROJSONURIIndyHTTPServer.ConvertURIToJSON(const Document, Params: String): String;\nconst\n  JSONObjectTemplate = \'{"method":"%s.%s"%s,"version": "%s"}\';\n  JSONParamTemplate = \'"%s":"%s"\';\n  JSONParamsTemplate = \',"params":{%s}\';\nvar\n  CallService, CallMessage,\n  ParsedDocument, ParsedParams, JSONParams,\n  Param, ParamName, ParamValue: String;\n  i: Integer;\nbegin\n  Result := \'\';\n\n  ParsedDocument := Trim(Document);\n\n  // Remove the leading /\n  if (length(Document) > 0) and\n     (Document[1] = \'/\') then\n    NextBlock(ParsedDocument);\n\n  // Remove the message type\n  NextBlock(ParsedDocument);\n\n  // Extract the service\n  CallService := NextBlock(ParsedDocument);\n\n  // Exctract the service message (method)\n  CallMessage := NextBlock(ParsedDocument);\n\n  JSONParams := \'\';\n  ParsedParams := Params;\n\n  while ParsedParams <> \'\' do\n  begin\n    // Extract the parameter and value\n    Param := NextBlock(ParsedParams, \'&\');\n\n    // See RFC 1866 section 8.2.1. TP\n    Param := StringReplace(Param, \'+\', \' \', [rfReplaceAll]);  {do not localize}\n\n    // Extract the parameter name\n    ParamName := NextBlock(Param, \'=\');\n\n    // Extract the parameter value\n    ParamValue := Param;\n\n    // Add a delimiter if required\n    if JSONParams <> \'\' then\n      JSONParams := JSONParams + \',\';\n\n    // Build the JSON style parameter\n    JSONParams := JSONParams + format(JSONParamTemplate, [ParamName, ParamValue]);\n  end;\n\n  if JSONParams <> \'\' then\n    JSONParams := format(JSONParamsTemplate, [JSONParams]);\n\n  // Make sure we have values for all the object variables, then build the JSON object\n  if (CallService <> \'\') and\n     (CallMessage <> \'\') and\n     (FJSONVersion <> \'\') then\n    Result := format(JSONObjectTemplate, [CallService, CallMessage, JSONParams, JSONVersion]);\nend;\n\nprocedure TROJSONURIIndyHTTPServer.InternalServerCommandGet(\n  AThread: TIdThreadClass; RequestInfo: TIdHTTPRequestInfo;\n  ResponseInfo: TIdHTTPResponseInfo);\nbegin\n  if FURIHandlingMethod in [urhJSON, urhParameters] then\n  begin\n    // Parse parameters into JSON if required\n    if FURIHandlingMethod = urhParameters then\n      RequestInfo.UnparsedParams := ConvertURIToJSON(RequestInfo.Document, RequestInfo.UnparsedParams);\n\n    // Decode the URI e.g. converts %20 to whitespace\n    RequestInfo.UnparsedParams := TIdURI.URLDecode(RequestInfo.UnparsedParams);\n\n    //  This works around a bug in TROIndyHTTPServer. By adding a whitespace to the\n    //  end of the QueryParams it forces the http server to process the parameters\n    RequestInfo.QueryParams := TIdURI.URLDecode(RequestInfo.QueryParams) + \' \';\n  end;\n\n  inherited;\nend;\n\nend.\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

原答案

\n\n

这是 Andr\xc3\xa9\ 答案的后续内容。

\n\n

对于当前版本的 RemObjects SDK,以下 URI 应该可以工作,但不能:

\n\n
http://www.mywebservice.com/JSON?{"id":"{392543cf-f110-4ba3-95471b02ce5bd693}","method":"servicename.methodname","params":{"param1":"xxx","param2":"yyy"}}:\n
Run Code Online (Sandbox Code Playgroud)\n\n

原因有两个:

\n\n
    \n
  • URI 在传递到消息处理程序之前不会被解码。如果任何字符已被编码,例如 %20 等,这将导致 JSON 错误。
  • \n
  • ROIndyHTTPServer 代码中似乎存在错误处理 URI 参数的错误。
  • \n
\n\n

我创建了一个 ROIndyHTTPServer 后代来解决这两个问题。这是代码:

\n\n
unit FixedROIndyHTTPServer;\n\ninterface\n\nuses\n  SysUtils, Classes,\n\n  uROIndyHTTPServer,\n\n  IdURI, IdCustomHTTPServer;\n\ntype\n  TFixedROIndyHTTPServer = class(TROIndyHTTPServer)\n  protected\n    procedure InternalServerCommandGet(AThread: TIdThreadClass; RequestInfo: TIdHTTPRequestInfo; ResponseInfo: TIdHTTPResponseInfo); override;\n  public\n    constructor Create(AOwner: TComponent); override;\n  end;\n\nimplementation\n\n{ TFixedROIndyHTTPServer }\n\nconstructor TFixedROIndyHTTPServer.Create(AOwner: TComponent);\nbegin\n  inherited;\nend;\n\nprocedure TFixedROIndyHTTPServer.InternalServerCommandGet(\n  AThread: TIdThreadClass; RequestInfo: TIdHTTPRequestInfo;\n  ResponseInfo: TIdHTTPResponseInfo);\nbegin\n  // This fixes 2 issues with TROIndyHTTPServer\n  //  1) It decodes the parameters e.g. converts %20 to whitespace\n  //  2) It adds a whitespace to the end of the QueryParams. This\n  //     forces the http server to process the parameters.\n\n  RequestInfo.QueryParams := TIdURI.URLDecode(RequestInfo.QueryParams) + \' \';\n  RequestInfo.UnparsedParams := TIdURI.URLDecode(RequestInfo.UnparsedParams);\n\n  inherited;\nend;\n\nend.\n
Run Code Online (Sandbox Code Playgroud)\n\n

这并没有回答我的问题,但对于任何有类似问题的人来说,这是一种解决方法。

\n\n

我仍然很想知道 RO SDK 是否支持使用自定义 URI。

\n