2013-02-01 57 views
5

हमारे पास एक RemObjects एसडीके HTTP सर्वर है जो कई सेवाओं और विधियों का खुलासा करता है। एसओएपी/जेएसओएन जैसे पैरामीटर को पारित करने के बजाय यूआरआई के माध्यम से एक विधि को कॉल करना संभव है।एसएमके पैरामीटर को रेमो ऑब्जेक्ट्स यूआरआई के माध्यम से पारित किया जा सकता है?

http://www.mywebservice.com/servicename/methodname?param1=xxx&param2=yyy 
+0

आपको विक्रेता से अधिक प्रत्यक्ष उत्तर मिल जाएगा, connect.remobjects.com पर, यह नहीं कि यह इस प्रश्न के लिए ठीक नहीं है। –

+0

@ वॉरेनपी-आम तौर पर, मैं सहमत हूं - RemObjects के पास बहुत अच्छे उत्पाद हैं, लेकिन उनके समर्थन का जवाब देने में लंबा समय लग सकता है। हालांकि यह यहां तेजी से पोस्ट हो सकता है :) – norgepaul

+1

@ नोर्गपॉल - अगर वे कभी जवाब देते हैं ... – RBA

उत्तर

3

अद्यतन

मैंने सर्वर वंश का एक बेहतर संस्करण लिखा है। यह एक स्वरूपित यूआरआई को एक JSON ऑब्जेक्ट में परिवर्तित करता है जो उपसेक्यू आरओ JSON संदेश हैंडलर द्वारा ntly संभाला जा सकता है।

डिफ़ॉल्ट हैंडिंग विधि यूआरआई को अनदेखा करना है।

बदलें urhJSON को URIHandlingMethod इस तरह एक URI स्वीकार करने के लिए:

http://www.mywebservice.com/json?{JSON OBJECT} 

सेट URIHandlingMethodurhParametersto को इस तरह एक URI स्वीकार करने के लिए:

unit ROJSONURIIndyHTTPServer ; 

interface 

uses 
    SysUtils, Classes, 

    uROIndyHTTPServer, 

    IdURI, IdCustomHTTPServer; 

type 
    TURIHandlingMethod = (
    urhNone, 
    urhJSON, 
    urhParameters 
); 

    TROJSONURIIndyHTTPServer = class(TROIndyHTTPServer) 
    private 
    FURIHandlingMethod: TURIHandlingMethod; 
    FJSONVersion: String; 

    function ConvertURIToJSON(const Document, Params: String): String; 
    function NextBlock(var Value: String; Delimiter: Char = '/'): String; 
    protected 
    procedure InternalServerCommandGet(AThread: TIdThreadClass; RequestInfo: TIdHTTPRequestInfo; ResponseInfo: TIdHTTPResponseInfo); override; 
    public 
    constructor Create(AOwner: TComponent); override; 
    published 
    property URIHandlingMethod: TURIHandlingMethod read FURIHandlingMethod write FURIHandlingMethod; 
    property JSONVersion: String read FJSONVersion write FJSONVersion; 
    end; 

implementation 

{ TROJSONURIIndyHTTPServer } 

constructor TROJSONURIIndyHTTPServer.Create(AOwner: TComponent); 
begin 
    inherited; 

    FJSONVersion := '1.1'; 
end; 

function TROJSONURIIndyHTTPServer.NextBlock(var Value: String; Delimiter: Char): String; 
var 
    p: Integer; 
begin 
    p := 1; 

    while (p <= length(Value)) and (Value[p] <> Delimiter) do 
    Inc(p); 

    if p = length(Value) then 
    Result := Value 
    else 
    Result := copy(Value, 1, p - 1); 

    Value := copy(Value, p + 1, MaxInt); 
end; 

function TROJSONURIIndyHTTPServer.ConvertURIToJSON(const Document, Params: String): String; 
const 
    JSONObjectTemplate = '{"method":"%s.%s"%s,"version": "%s"}'; 
    JSONParamTemplate = '"%s":"%s"'; 
    JSONParamsTemplate = ',"params":{%s}'; 
var 
    CallService, CallMessage, 
    ParsedDocument, ParsedParams, JSONParams, 
    Param, ParamName, ParamValue: String; 
    i: Integer; 
begin 
    Result := ''; 

    ParsedDocument := Trim(Document); 

    // Remove the leading/
    if (length(Document) > 0) and 
    (Document[1] = '/') then 
    NextBlock(ParsedDocument); 

    // Remove the message type 
    NextBlock(ParsedDocument); 

    // Extract the service 
    CallService := NextBlock(ParsedDocument); 

    // Exctract the service message (method) 
    CallMessage := NextBlock(ParsedDocument); 

    JSONParams := ''; 
    ParsedParams := Params; 

    while ParsedParams <> '' do 
    begin 
    // Extract the parameter and value 
    Param := NextBlock(ParsedParams, '&'); 

    // See RFC 1866 section 8.2.1. TP 
    Param := StringReplace(Param, '+', ' ', [rfReplaceAll]); {do not localize} 

    // Extract the parameter name 
    ParamName := NextBlock(Param, '='); 

    // Extract the parameter value 
    ParamValue := Param; 

    // Add a delimiter if required 
    if JSONParams <> '' then 
     JSONParams := JSONParams + ','; 

    // Build the JSON style parameter 
    JSONParams := JSONParams + format(JSONParamTemplate, [ParamName, ParamValue]); 
    end; 

    if JSONParams <> '' then 
    JSONParams := format(JSONParamsTemplate, [JSONParams]); 

    // Make sure we have values for all the object variables, then build the JSON object 
    if (CallService <> '') and 
    (CallMessage <> '') and 
    (FJSONVersion <> '') then 
    Result := format(JSONObjectTemplate, [CallService, CallMessage, JSONParams, JSONVersion]); 
end; 

procedure TROJSONURIIndyHTTPServer.InternalServerCommandGet(
    AThread: TIdThreadClass; RequestInfo: TIdHTTPRequestInfo; 
    ResponseInfo: TIdHTTPResponseInfo); 
begin 
    if FURIHandlingMethod in [urhJSON, urhParameters] then 
    begin 
    // Parse parameters into JSON if required 
    if FURIHandlingMethod = urhParameters then 
     RequestInfo.UnparsedParams := ConvertURIToJSON(RequestInfo.Document, RequestInfo.UnparsedParams); 

    // Decode the URI e.g. converts %20 to whitespace 
    RequestInfo.UnparsedParams := TIdURI.URLDecode(RequestInfo.UnparsedParams); 

    // This works around a bug in TROIndyHTTPServer. By adding a whitespace to the 
    // end of the QueryParams it forces the http server to process the parameters 
    RequestInfo.QueryParams := TIdURI.URLDecode(RequestInfo.QueryParams) + ' '; 
    end; 

    inherited; 
end; 

end. 
:

http://www.mywebservice.com/json/service/method?param1=xxx&param2=yyy 

कोड यह


मूल उत्तर

यह एक आन्द्रे का जवाब देने के लिए अनुवर्ती है।

निम्नलिखित यूआरआई काम करना चाहिए RemObjects एसडीके के वर्तमान संस्करण के साथ

, लेकिन नहीं करता है: इससे पहले कि यह पारित हो जाता है

  • यूआरआई डीकोड नहीं है:

    http://www.mywebservice.com/JSON?{"id":"{392543cf-f110-4ba3-95471b02ce5bd693}","method":"servicename.methodname","params":{"param1":"xxx","param2":"yyy"}}: 
    

    वहाँ 2 कारणों क्यों कर रहे हैं संदेश हैंडलर को। यदि किसी भी वर्ण को एन्कोड किया गया है तो इसका परिणाम JSON त्रुटि में होता है। % 20 आदि

  • ROIndyHTTPServer कोड में एक बग प्रतीत होता है जो यूआरआई पैरामीटर को मिशनल करता है।

मैंने एक ROINDYHTTPServer वंशज बनाया है जो दोनों समस्याओं को हल करता है। यहां कोड है:

unit FixedROIndyHTTPServer; 

interface 

uses 
    SysUtils, Classes, 

    uROIndyHTTPServer, 

    IdURI, IdCustomHTTPServer; 

type 
    TFixedROIndyHTTPServer = class(TROIndyHTTPServer) 
    protected 
    procedure InternalServerCommandGet(AThread: TIdThreadClass; RequestInfo: TIdHTTPRequestInfo; ResponseInfo: TIdHTTPResponseInfo); override; 
    public 
    constructor Create(AOwner: TComponent); override; 
    end; 

implementation 

{ TFixedROIndyHTTPServer } 

constructor TFixedROIndyHTTPServer.Create(AOwner: TComponent); 
begin 
    inherited; 
end; 

procedure TFixedROIndyHTTPServer.InternalServerCommandGet(
    AThread: TIdThreadClass; RequestInfo: TIdHTTPRequestInfo; 
    ResponseInfo: TIdHTTPResponseInfo); 
begin 
    // This fixes 2 issues with TROIndyHTTPServer 
    // 1) It decodes the parameters e.g. converts %20 to whitespace 
    // 2) It adds a whitespace to the end of the QueryParams. This 
    //  forces the http server to process the parameters. 

    RequestInfo.QueryParams := TIdURI.URLDecode(RequestInfo.QueryParams) + ' '; 
    RequestInfo.UnparsedParams := TIdURI.URLDecode(RequestInfo.UnparsedParams); 

    inherited; 
end; 

end. 

यह मेरे प्रश्न का उत्तर नहीं देता है, लेकिन यह किसी भी समस्या के लिए कामकाज है।

मैं अभी भी सुनना चाहता हूं कि आरओ एसडीके कस्टम यूआरआई के उपयोग का समर्थन करता है या नहीं।

+0

मुझे लगता है कि आपको अभी भी 'urh पैरामीटरस्टो' के लिए connect.remobjects.com –

+0

+1 पर पोस्ट करना चाहिए; मुझे लगता है कि इस जवाब को स्वीकार करने की टिक मिलनी चाहिए। –

+0

+ कोसमैनप्रंड - ठीक है, करेंगे। यह आपकी पोस्ट थी जिसने मुझे विचार दिया :) – norgepaul

2

जहाँ तक मुझे पता है: नहीं।

आप केवल एक JSON struct का उपयोग कर REST कॉल किसी तरह का कर सकते हैं: http://www.mywebservice.com/JSON { "id": "{392543cf-f110-4ba3-95471b02ce5bd693}", "विधि": "servicename.methodname" "पैरामीटर ": {" param1 ":" xxx "," param2 ":" yyy "}}:

Btw: DataAbstract (आरओ के आधार पर) एक REST इंटरफ़ेस है, लेकिन आरओ ही नहीं ... :(

+0

जिस तरह से मैं अब कॉल कर रहा हूं, लेकिन हमारा उपभोक्ता यूआरआई में पैरामीटर चाहता है। हमारे पास DataAbstract है, लेकिन मुझे संदेह है कि डीए रेस्ट कार्यान्वयन के रूप में मदद मिलेगी, संभवतः केवल डेटा एबस्ट्रेट अनुरोधों से संबंधित है, सामान्य एसडीके नहीं। क्या मैं सही हूँ? – norgepaul

+0

क्षमा करें, मैंने आपके उत्तर को गलत तरीके से पढ़ा है। वर्तमान में हम JSON संरचना पोस्ट करते हैं, हम इसे यूआरआई में नहीं जोड़ते हैं। हालांकि, मैंने कोशिश की और यह काम नहीं किया। एक फिक्स के लिए मेरा जवाब देखें जो इसे काम करता है। – norgepaul

3

यहां norgepaul's समाधान पर एक नाटक है जो अच्छा दिखता है और JSON लौटाता है।यह TROIndyHTTPServer के वंशज का उपयोग करके HTTP अनुरोध को अवरुद्ध करने के समान विचार पर आधारित है, लेकिन इस बार मैं केवल अनुरोध के पैरामीटर को ठीक नहीं कर रहा हूं, मैं "JSON" पोस्ट बना रहा हूं जिसे क्लाइंट ने नहीं भेजा था!

यहाँ कोड है कि मैं डिफ़ॉल्ट के साथ "VCL Standalon" सर्वर कार्यान्वयन का परीक्षण करने के लिए इस्तेमाल है:

TUriROIndyHTTPServer = class(TROIndyHTTPServer) 
protected 
    procedure InternalServerCommandGet(AThread: TIdThreadClass; RequestInfo: TIdHTTPRequestInfo; ResponseInfo: TIdHTTPResponseInfo); override; 
end; 

procedure TUriROIndyHTTPServer.InternalServerCommandGet(AThread: TIdThreadClass;RequestInfo: TIdHTTPRequestInfo; ResponseInfo: TIdHTTPResponseInfo); 
var A, B: Integer; 
    NewPost: AnsiString; 
begin 
    if RequestInfo.Document = '/json/sum' then 
    begin 
     // Extract the parameters 
     A := StrToIntDef(RequestInfo.Params.Values['a'], 0); 
     B := StrToIntDef(RequestInfo.Params.Values['b'], 0); 
     NewPost := AnsiString(Format('{"version":"1.1","method":"NewService.Sum","params":{"A":"%d","B":"%d"}}', [A, B])); 

     // Prepare the (fake) post-stream 
     RequestInfo.PostStream.Free; 
     RequestInfo.PostStream := TMemoryStream.Create; 
     RequestInfo.PostStream.Write(NewPost[1], Length(NewPost)); 
     RequestInfo.PostStream.Position := 0; 
    end 
    else if RequestInfo.Document = '/json/getservertime' then 
    begin 
     // Extract the parameters 
     NewPost := '{"version":"1.1","method":"NewService.GetServerTime"}'; 

     // Prepare the (fake) post-stream 
     RequestInfo.PostStream.Free; 
     RequestInfo.PostStream := TMemoryStream.Create; 
     RequestInfo.PostStream.Write(NewPost[1], Length(NewPost)); 
     RequestInfo.PostStream.Position := 0; 
    end; 

    inherited; 
end; 
जगह में कोड की इस तरह के साथ

, मैं इस तरह अनुरोध कर सकता है:

http://localhost:8080/json/sum?a=1&b=2 

रिटर्न (ब्राउज़र में!)

{"version":"1.1","result":"3"}  

और इस:

+०१२३५१६४१०६१
http://localhost:8080/json/getservertime 

रिटर्न इस (अच्छी तरह से, इस लेखन के समय):

{"version":"1.1","result":"2013-02-01T19:24:24.827"} 
  • अपने सर्वर के मुख्य रूप pastebin link
  • अपने सर्वर के मुख्य रूप pastebin link
  • के लिए DFM के लिए पूरे कोड

परिणाम (ब्राउज़र या विदेशी एप्लिकेशन में) शुद्ध JSON है क्योंकि इसे "JSON संदेश" के रूप में बनाया गया है आरओ का कोड

+0

@ cosmin-Nice idea। यह अच्छा होगा अगर यह सामान्य था और किसी भी सेवा/पैरामीटर सूची के साथ काम किया। इसे लागू करने के लिए बहुत आसान होना चाहिए। मुझे कल जाना होगा और अगर यह काम करता है तो इसे यहां पोस्ट करें। – norgepaul

+0

@ नोर्गपॉल, मैं अभी इसे सामान्य बनाने में देख रहा हूं। मैं बहुत नया आरओ-एसडीके हूं और मैं यह पता लगाने की कोशिश कर रहा हूं कि आखिरकार सेवाओं को कैसे भेजा जाता है। जानकारी निश्चित रूप से कहीं कहीं है। मुझे यकीन है कि हम RODL पाठक का उपयोग सीधे उसी जानकारी को निकालने के लिए आरओडीएल से कर सकते हैं। एक समाधान निश्चित रूप से संभव है। –

+0

@ कॉस्मीन- इसे आसान रखने के लिए मैं बस उस विधि का पालन करता हूं जिसे आपने पहले ही शुरू किया है। यदि आपके पास यूआरआई कुछ है जैसे http: // webservice/json/service/method? Param1 = xxx & param2 = yyy बस सेवा, विधि और पैरामीटर को पार्स करें, फिर JSON ऑब्जेक्ट बनाएं। {"संस्करण": "1.1", "विधि": "service.method", "पैरा": {"param1": "xxx", "param2": "yyy"}} ... यह है!निश्चित रूप से ऐसा करने के लिए और अधिक सुरुचिपूर्ण तरीके होंगे हालांकि यदि आपके पास जांच करने का समय है :) – norgepaul

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^