4 Replies Latest reply: Oct 31, 2012 5:27 PM by J-Lig RSS

    apex_web_service.make_rest_request: Passing parameters and the content type

    trent
      Not sure if I am missing something, but should this API be setting the content type (to application/x-www-url-formencoded) when there are values present for the parameters p_parm_name and p_parm_value.

      The example in the docs is to a yahoo API. I'm not sure about that particular one (see: http://docs.oracle.com/cd/E23903_01/doc/doc.41/e21676/apex_web_service.htm#BABEDJHJ), and I think it requires an appid (yahoo account), so i just went with the example here:

      http://developer.yahoo.com/yql/guide/yql-code-examples.html#yql_php

      If I run the following from a html file on my desktop it works:
      <form method="POST" action="http://query.yahooapis.com/v1/public/yql">
      
      <input type="hidden" name="q" value="select * from upcoming.events where location='San Francisco' and search_text='dance'"></input>
      <input type="hidden" name="format" value="json"></input>
      <input type="submit"></input>
      
      </form>
      That is, it returns a JSON result.

      The raw HTTP data is as follows:
      POST http://query.yahooapis.com/v1/public/yql HTTP/1.1
      Host: query.yahooapis.com
      Connection: keep-alive
      Content-Length: 110
      Cache-Control: max-age=0
      Origin: null
      User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.11 (KHTML, like Gecko) Ubuntu/12.04 Chromium/20.0.1132.47 Chrome/20.0.1132.47 Safari/536.11
      Content-Type: application/x-www-form-urlencoded
      Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
      Accept-Encoding: gzip,deflate,sdch
      Accept-Language: en-AU,en;q=0.8,en-US;q=0.6
      Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

      q=select+fromupcoming.events+where+location%3D%27San+Francisco%27+and+search_text%3D%27dance%27&format=json>

      However, running the following returns nothing: (nothing, as in nothing that depends on the parameters passed in)
      set serveroutput on
      
      declare
      
      l_c CLOB;
      
      begin
      
      
        l_c := apex_web_service.make_rest_request(
          p_url => 'http://query.yahooapis.com/v1/public/yql',
          p_http_method => 'POST',
          p_parm_name => apex_util.string_to_table('q:format'),
          p_parm_value => apex_util.string_to_table('select * from upcoming.events where location=''San Francisco'' and search_text=''dance'':json'),
          p_proxy_override => 'http://192.168.1.3:8888');
      
        dbms_output.put_line(substr(l_c, 1, 4000));
      
      end;
      Raw HTTP data:
      POST http://query.yahooapis.com/v1/public/yql HTTP/1.1
      Host: query.yahooapis.com
      Connection: Keep-Alive
      Content-Length: 106
      Connection: close

      q=select+%2A+from+upcoming%2Eevents+where+location%3D'San+Francisco'+and+search_text%3D'dance'&format=json>

      I do note a key difference is that content type isn't being set in the web service API.

      This was just to test a public service. I do note that the above has slighty different request data (percentage encoding on some chars). However, I experienced the same behaviour on a procedure I had written (I can also provide this example test case if you like), which is where I first noticed the issue.

      Using utl_http and setting the content type to application/x-www-url-formencoded, does resolve the issue. However, just thought i'd see the possibility of using the Web service API that is made available.

      Is the example in the docs valid, or am I missing something obvious?

      This is on ApEx 4.1 on the OTN Dev Days VM.

      Thoughts?
        • 1. Re: apex_web_service.make_rest_request: Passing parameters and the content type
          Prabodh
          Hi trent,

          I too have had issues with this API , so moved forward with UTL_HTTP API.
          There is something amiss.

          If you change your code to the one below it works.
          SET SERVEROUT ON
          declare
           l_c CLOB;
           l_param varchar2(1000) ; 
          begin
           l_param := 'select * from upcoming.events where location=''San Francisco'' '||
                  ' and search_text=''dance'''||'&'||'format=json'; 
           l_c := apex_web_service.make_rest_request(
              p_url => 'http://query.yahooapis.com/v1/public/yql?q='||
                  utl_url.escape(l_param)
              ,p_http_method => 'POST'
              );
           
            dbms_output.put_line(substr(l_c, 1, 4000));
           
          end;
          /
          Note the use of UTL_URL.ESCAPE. The call does not work without it.
          I do not use a proxy, so that parameter does not feature in my snippet above.

          Cheers,

          PS: However, the below does not work. So, it appears that the p_parm_name and p_parm_value do not quite work.
          SET SERVEROUT ON;
          declare
           l_c CLOB;
           l_param varchar2(1000) ; 
          begin
           l_param := 'select * from upcoming.events where location=''San Francisco'' and search_text=''dance'''; 
           l_c := apex_web_service.make_rest_request(
              p_url => 'http://query.yahooapis.com/v1/public/yql'
              ,p_http_method => 'POST'
              ,p_parm_name => apex_util.string_to_table('q:format')
              ,p_parm_value => apex_util.string_to_table(utl_url.escape(l_param)||':json')
              );
           
            dbms_output.put_line(substr(l_c, 1, 4000));
           
          end;
          / 
          Edited by: Prabodh on Oct 13, 2012 2:04 PM
          • 2. Re: apex_web_service.make_rest_request: Passing parameters and the content type
            J-Lig
            I had a similar issue:
            apex_web_service.make_rest_request wrapper missing header parms

            I endedup opening an SR for Oracle. I found out that headers (content-type) are set in global variables before making the apex_web_service.make_rest_request call.

            See http://docs.oracle.com/cd/E17556_01/doc/apirefs.40/e15519/apex_web_service.htm#autoId4 for a description of the headers and cookies.

            I endedup having to add the following to my code before apex_web_service.make_rest_request:

            apex_web_service.g_request_headers(1).name := 'Content-Type';
            apex_web_service.g_request_headers(1).value := 'application/xml';

            Once I did that, my service works. Odd. Not sure why they did it that way because their internal packages take header parameters, but the wrappers do it this way I guess.

            Hopefully this works for you!

            Jennifer
            • 3. Re: apex_web_service.make_rest_request: Passing parameters and the content type
              trent
              Oh great! had completely overlooked that section of the docs. Agree, seems odd.
              • 4. Re: apex_web_service.make_rest_request: Passing parameters and the content type
                J-Lig
                Just figured out another nice little nugget...when I got that web service call working, I happened to run a different call and spent hours trying to figure out why it didn’t work anymore. Unfortunately this is not documented very well (at least anywhere I could find). What I figured out (eventually) is that when you set those headers, ALL service calls use them. When I ran my other call, it was trying to use those headers too. In case you have the same issues, here are some helpful tasks that took me forever to figure out:

                --To check the count of records in that g_request_headers table
                l_count := apex_web_service.g_request_headers.count;
                dbms_output.put_line('Count: '||l_count);

                --To check the name of record (by index) in that g_request_headers table
                --l_name := apex_web_service.g_request_headers(1).name;
                dbms_output.put_line('Name: '||l_name);

                --To check the value of record (by index) in that g_request_headers table
                --l_value := apex_web_service.g_request_headers(1).value;
                dbms_output.put_line('Value: '||l_value);

                --To delete the records from the g_request_headers table
                apex_web_service.g_request_headers.delete;

                Hopefully this will save you some time if you intend to make other service calls that dont require the same headers

                Jennifer