【问题标题】:How to invoke a REST web service, with POST method sending the parameters as json in a query string in plsql?如何调用 REST Web 服务,使用 POST 方法在 plsql 的查询字符串中将参数作为 json 发送?
【发布时间】:2019-11-11 13:29:27
【问题描述】:

我正在尝试从 plsql 调用 REST Web 服务,使用 POST 方法,并尝试将参数作为查询字符串中的 json 发送。不幸的是,我失败可能是因为我没有正确使用 utl_http(这里是 plsql 新手)。

恐怕我没有正确发送请求并且我没有在查询字符串中提交 json。

实际上,Web 服务的提供者期望这样的东西:BASE URL/postPayment/jsonstring,而我恐怕并没有这样做。

实际上我收到一个 HTTP 405 错误:“指定的 HTTP 方法不允许用于请求的资源 ()。”

我试图四处搜索,发送 json 的最佳方式是什么(最初我尝试使用 APEX_WEB_SERVICE.MAKE_REST_REQUEST 但返回的结果为空)但似乎我找不到关于我的情况的进一步指导。

有人可以通过在我的案例中指出正确的 uttl_http 使用形式,或者通过在下面指出我的错误来指导我应该如何进行?

create or replace procedure another_way

( 
customerNo        IN   VARCHAR2,  
invoiceNo        IN   VARCHAR2,
agreementNo        IN   VARCHAR2,
instance        IN   VARCHAR2,
paymentRefId        IN   VARCHAR2,
paymentDate        IN   VARCHAR2,
principalAmt        IN   VARCHAR2,
interest        IN   VARCHAR2,
totalAmt        IN   VARCHAR2,
passCode        IN   VARCHAR2,
invoiceType        IN   VARCHAR2,
phoneNo        IN   VARCHAR2

) is

req utl_http.req;
res utl_http.resp;
url varchar2(4000) := 'http://baseurl:7474/mpower/rest/postPayment/';
name varchar2(4000);
buffer varchar2(4000); 
content varchar2(4000) := '{"customerNo":"'||customerNo||'","invoiceNo":"'||invoiceNo||'","agreementNo":"","instance":"'||instance||'","paymentRefId":"'||paymentRefId||'","paymentDate":"'||paymentDate||'","principalAmt":'||principalAmt||',"interest":'||interest||',"totalAmt":'||totalAmt||',"passCode":"'||passCode||'","invoiceType":"'||invoiceType||'","phoneNo":"'||phoneNo||'"}';

begin

   /* just to indicate it started */
    dbms_output.put_line('START'); 

    /* to check if your JSON content is okay and has correct values */
    dbms_output.put_line(content); 

dbms_output.put_line(url||content);


req := utl_http.begin_request(url||content, 'POST',' HTTP/1.1');
utl_http.set_authentication( req, 'abi','oshee', 'Basic' );
--utl_http.set_header(req, 'user-agent', 'mozilla/4.0'); 
--utl_http.set_header(req, 'content-type', 'application/json'); 
--utl_http.set_header(req, 'Content-Length', length(content));




/* not sure if this will work but try to print the utl_http */


res := utl_http.get_response(req);

    begin
    loop
    utl_http.read_line(res, buffer);
    dbms_output.put_line(buffer);

    end loop;
    utl_http.end_response(res);
    exception
    when utl_http.end_of_body then
    utl_http.end_response(res);
    end;

 /* just to indicate it ended */
    dbms_output.put_line('END');
exception
    when utl_http.end_of_body 
    then
        utl_http.end_response(res);

        /* just to indicate it went to exception part */
    DBMS_OUTPUT.put_line (SQLERRM); 
    dbms_output.put_line('EXCEPTION');
    end;

--end another_way;

【问题讨论】:

  • 您应该返回使用 APEX_WEB_SERVICE.MAKE_REST_REQUEST(它也可以进行基本身份验证)。你说你没有得到响应,但你至少得到了 HTTP 状态码吗?如果是这样,它是什么?接下来,为什么要在查询字符串中发送数据?使用 REST 发布时,通常使用 HTTP 请求的主体来发送数据。最后,如果你让它在 Postman 中工作,请执行以下操作:点击右侧的 Code 链接,选择 cURL,然后点击 Copy to Clipboard乙>。删除所有敏感信息并向我们展示其中的内容。
  • 实际上提供商已经建立了规则:因此我们有义务将 json 作为查询字符串发送。据我所知,REST 并没有强制要求在正文中发送参数。然而,你是对的。我回到使用 APEX_WEB_SERVICE.MAKE_REST_REQUEST 但通过使用 uttl_url.escape 引入了 url 编码的缺失部分!!!!现在我可以得到回应了!!!! :) :) :) 再次感谢您。

标签: json plsql query-string oracle-apex invoke-webrequest


【解决方案1】:

我之前没有在 PLSQL 中尝试过,但我可以为您提供以下内容:

(1) 首先,测试您使用的 URL 是否真的可以捕获您的 POST 请求和请求正文。 为此,您可以使用 POSTMAN(它是我用来测试 API 的应用程序 - 在您的情况下,此网址为“http://10.211.47.98:7474/rest/postPayment/”)。免费。您也可以在不登录的情况下按原样使用它。

在 POSTMAN 中,您只需在 url 左侧的下拉列表中使用“POST”,然后在 url 字段中提供您的 url,然后在正文中提供您的 JSON 内容。 (如果端点需要,还有授权标头)

以下是邮递员的网址和网站截图示例: https://www.getpostman.com/downloads/

(2) 在您的代码中,您还可以添加额外的 DBMS_OUT.put_line() 代码,以便在运行时验证触发代码时发生的情况。

SAMPLE(我刚刚在您的代码中添加了一些 DBMS_OUT 行和 cmets):

/*<"create or replace", name and other variables used by your code here>*/
req utl_http.req;
res utl_http.resp;
url varchar2(4000) := 'http://10.211.47.98:7474/rest/postPayment/';
name varchar2(4000);
buffer varchar2(4000); 
content varchar2(4000) := '{"customerNo":"' || customerNo || '","invoiceNo":"' || invoiceNo || '","agreementNo":"","instance":"' || instance || '","paymentRefId":"' ||paymentRefId || '","paymentDate":"' || paymentDate || '","principalAmt":' || principalAmt || ',"interest":' || interest|| ',"totalAmt":' || totalAmt || ',"passCode":"' || passCode || '","invoiceType":"' || invoiceType || '","phoneNo":"' || phoneNo || '"}';

begin
    /* just to indicate it started */
    dbms_output.put_line("START"); 

    /* to check if your JSON content is okay and has correct values */
    dbms_output.put_line(content); 

    req := utl_http.begin_request(url, 'POST',' HTTP/1.1');
    utl_http.set_header(req, 'user-agent', 'mozilla/4.0'); 
    utl_http.set_header(req, 'content-type', 'application/json'); 
    utl_http.set_header(req, 'Content-Length', length(content));

    utl_http.write_text(req, content);

    /* not sure if this will work but try to print the utl_http */
    dbms_output.put_line(utl_http);

    res := utl_http.get_response(req);

    begin
    loop
        utl_http.read_line(res, buffer);
        dbms_output.put_line(buffer);
    end loop;

    utl_http.end_response(res);

    /* just to indicate it ended */
    dbms_output.put_line("END");
exception
    when utl_http.end_of_body 
    then
        utl_http.end_response(res);

        /* just to indicate it went to exception part */
    dbms_output.put_line("EXCEPTION");
    end;
end /*<name of package/procedure>*/;

(3) 您也可以参考本文档了解有关 oracle 的 utl_http 的更多技术细节。 https://docs.oracle.com/database/121/ARPLS/u_http.htm#ARPLS70957

希望这会有所帮助。

如果您遇到任何其他问题,请在此处告知我们,以便我们分享更多详细信息。

【讨论】:

  • 您好,感谢您的回复。实际上,我已经用 POSTMAN 进行了测试,查询字符串中的 url + json 由我的代码生成,它工作正常,我可以从提供者那里得到响应。我收到 HTTP 405 错误消息:“指定的 HTTP 方法不允许用于请求的资源 ()。”是因为我没有引入认证。我修好了。我在我的问题中编辑了代码,所以我的整个代码都在那里。不幸的是,dbms_output 不能与 uttl_http 或 req 一起使用。但是我现在得到的响应如下:
  • START 10.211.47.98:7474/rest/postPayment /{"customerNo":"TR3V160273630450","invoiceNo":"290407083","agreementNo":"","instance":"TIRANA3","paymentRefId":" 001CHDP192820003","paymentDate":"08-11-201912:10:00","principalAmt":340.00,"interest":82.32,"totalAmt":422.32,"passCode":"ABI","invoiceType":" F","phoneNo":""} END
  • 我似乎仍然无法获取响应。
  • 也许您可以尝试在 read_line 代码上添加 值? utl_http.read_line(res, buffer, TRUE);参考:docs.oracle.com/cd/B28359_01/appdev.111/b28419/…docs.oracle.com/cd/B10501_01/appdev.920/a96612/u_http.htm
【解决方案2】:

基本上,使用 POST 方法调用 REST Web 服务,通过 plsql 在查询字符串中传递一个 json 参数,可以通过 APEX_WEB_SERVICE.MAKE_REST_REQUEST 成功执行,但是应该记住 url 编码,因为 json 是用保留的人物。可以使用 UTL_URL.ESCAPE 包/函数。以下是我的案例示例:

L_BASE_URL VARCHAR2 (4000) :='@987654321@' ; PAR := '{"customerNo":"'||customerNo||'","invoiceNo":"'||invoiceNo||'","agreementNo":"","instance":"'||instanceNo||'","paymentRefId":"'||paymentRefId||'","paymentDate":"'||paymentDate||'","principalAmt":'||principalAmt||',"interest":'||interest||',"totalAmt":'||totalAmt||',"passCode":"'||passCode||'","invoiceType":"'||invoiceType||'","phoneNo":"'||phoneNo||'"}'; l_base_url := l_base_url ||URL_ENCODE(PAR,'ASCII'); l_result := APEX_WEB_SERVICE.make_rest_request( p_url => l_base_url, p_http_method => 'POST', p_username => 'username', p_password => 'password' ); 其中URL_ENCODE函数如下:

create or replace FUNCTION url_encode ( data IN VARCHAR2, charset IN VARCHAR2) RETURN VARCHAR2 AS BEGIN RETURN utl_url.escape(data, TRUE, charset); -- note use of TRUE END;

【讨论】:

    猜你喜欢
    • 2011-09-26
    • 1970-01-01
    • 1970-01-01
    • 2016-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-06
    • 2019-04-09
    相关资源
    最近更新 更多