Thursday, March 31, 2016

apex_web_service.make_rest_request not working with POST

I recently encountered a web service that I was unable to use with POST and apex_web_service. I was using a statement like this:

declare
    l_clob       CLOB;
BEGIN

    l_clob := apex_web_service.make_rest_request(
        p_url => 'http://myMachine/myService',
        p_http_method => 'POST',
        p_parm_name => apex_util.string_to_table('param1:param2'),
        p_parm_value => apex_util.string_to_table('xyz:xml'));

END;

I've used this many times in the past, but this particular service would not recognize the parameters passed in p_parm_name and p_parm_value. I was able to use curl with the same transaction.

curl -X POST -d "param1=xyz&param2=xml" http://myMachine/myService

I must say, it was VERY frustrating. I finally enabled full logging on Apache using mod_dumpio. 

(Apache 2.4.x)
# uncomment
LoadModule dumpio_module modules/mod_dumpio.so


# add
    <IfModule dumpio_module>
#LogLevel debug
LogLevel dumpio:trace7   # Apache 2.4
DumpIOInput On
DumpIOOutput On
#DumpIOLogLevel debug   # does not work in 2.4
    </IfModule>

I reviewed the logs to find out if apex_web_service.make_rest_request was doing something different than curl. I say "if," but clearly something had to be different. In the logs I found this line from curl but not from apex_web_service:

mod_dumpio:  dumpio_in (data-HEAP): Content-Type: application/x-www-form-urlencoded\r\n

I was able to get things working by adding the Content-Type header as shown below.


declare
    l_clob       CLOB;
BEGIN
  apex_web_service.g_request_headers(1).name := 'Content-Type';
  apex_web_service.g_request_headers(1).value := 'application/x-www-form-urlencoded'; 

    l_clob := apex_web_service.make_rest_request(
        p_url => 'http://myMachine/myService',
        p_http_method => 'POST',
        p_parm_name => apex_util.string_to_table('param1:param2'),
        p_parm_value => apex_util.string_to_table('xyz:xml'));

END;


I hope this helps someone!

5 comments:

ruepprich said...

Thanks for sharing, Anton. The tip for using dumpio is definitely worth remembering. I'll reblog this.

Arun said...

Can we use JSON with apex_web_service?

Eric said...

Thanks for the information. It helped me to solve my problem!

Jason Straub said...

Hi Anton,

As you now know, you as a developer have complete control over what headers are set when you use APEX_WEB_SERVICE. The API doesn't automatically infer your intent and add arbitrary HTTP headers to your request. I am glad you found the solution.

Regards,

Jason

Unknown said...

Hi Jason,

Re-reading my blog entry, it does sound like I was complaining about apex_web_service. Really, though, I was frustrated with the web service I was consuming. I don't know why it required that header. I suppose the fact that curl automatically adds it give some indication that in that circumstance it is a common header.

As ruepprich pointed out, though, dumpio is the most valuable part of this blog post.

Thanks for your comment,

Anton