A while ago Robert and Pete blogged about Oracle’s UTL_HTTP package. Robert gave an example of how to use this package to request a web page from the Internet into Oracle and Pete mentioned that you could do the opposite, i.e. post data from Oracle to the Internet. Recently I had a requirement to do just that, HTTP post data from the Oracle database to another web server. So, I wrote the following generic procedure util_pkg.http_post. Here it is followed by an example of how to use it (tested on 9.2):
First, the package specification:
create or replace
package util_pkg
is
procedure http_post (
p_url_in in varchar2
,p_data_in in clob
,p_data_type in varchar2 default 'text/xml'
,p_proxy_in in varchar2 default null
,p_no_proxy_domains_in in varchar2 default null
,p_username_in in varchar2 default null
,p_password_in in varchar2 default null
);
end;
/
Now the package body:
create or replace
package body util_pkg
is
procedure http_post (
p_url_in in varchar2
,p_data_in in clob
,p_data_type in varchar2 default 'text/xml'
,p_proxy_in in varchar2 default null
,p_no_proxy_domains_in in varchar2 default null
,p_username_in in varchar2 default null
,p_password_in in varchar2 default null
) is
l_http_req utl_http.req;
l_http_resp utl_http.resp;
l_my_scheme varchar2(256);
l_my_realm varchar2(256);
l_my_proxy boolean;
begin
-- When going through a firewall, pass requests through this host.
-- Specify sites inside the firewall that don't need the proxy host.
if (p_proxy_in is not null) and
(p_no_proxy_domains_in is not null)
then
utl_http.set_proxy(p_proxy_in, p_no_proxy_domains_in);
end if;
-- Ask UTL_HTTP not to raise an exception for 4xx and 5xx status codes,
-- rather than just returning the text of the error page.
utl_http.set_response_error_check(false);
-- Begin the post request
l_http_req := utl_http.begin_request (p_url_in, 'POST');
-- Set the HTTP request headers
utl_http.set_header(l_http_req, 'User-Agent', 'Mozilla/4.0');
utl_http.set_header(l_http_req, 'content-type', p_data_type);
utl_http.set_header(l_http_req, 'content-length', length(p_data_in));
-- Specify a user ID and password for pages that require them.
if p_username_in is not null then
utl_http.set_authentication(
l_http_req, p_username_in, p_password_in);
end if;
-- Write the data to the body of the HTTP request
utl_http.write_text(l_http_req, p_data_in);
-- Process the request and get the response.
l_http_resp := utl_http.get_response (l_http_req);
dbms_output.put_line ('status code: ' || l_http_resp.status_code);
dbms_output.put_line ('reason phrase: ' || l_http_resp.reason_phrase);
-- Look for client-side error and report it.
if (l_http_resp.status_code >= 400) and
(l_http_resp.status_code <= 499)
then
-- Detect whether the page is password protected,
-- and we didn't supply the right authorization.
-- Note the use of utl_http.HTTP_UNAUTHORIZED, a predefined
-- utl_http package global variable
if (l_http_resp.status_code = utl_http.HTTP_UNAUTHORIZED) then
utl_http.get_authentication(
l_http_resp, l_my_scheme, l_my_realm, l_my_proxy);
if (l_my_proxy) then
dbms_output.put_line('Web proxy server is protected.');
dbms_output.put(
'Please supply the required ' ||
l_my_scheme ||
' authentication username/password for realm ' ||
l_my_realm ||
' for the proxy server.');
else
dbms_output.put_line(
'Web page ' || p_url_in || ' is protected.');
dbms_output.put(
'Please supplied the required ' ||
l_my_scheme ||
' authentication username/password for realm ' ||
l_my_realm ||
' for the Web page.');
end if;
else
dbms_output.put_line('Check the URL.');
end if;
utl_http.end_response(l_http_resp);
return;
-- Look for server-side error and report it.
elsif (l_http_resp.status_code >= 500) and
(l_http_resp.status_code <= 599)
then
dbms_output.put_line('Check if the Web site is up.');
utl_http.end_response(l_http_resp);
return;
end if;
utl_http.end_response (l_http_resp);
exception
when others then
dbms_output.put_line (sqlerrm);
raise;
end http_post;
end;
/
And here is an example of how to use it. Replace the URL and the query below with your stuff. Since I am posting XML, I used dbms_xmlgen.getxml to transform the result of the query to XML:
declare
l_url varchar2 (200) := 'http://www.example.com/post.cfm';
l_data clob;
l_query varchar2(32767);
begin
l_query := '
select object_name, created, status
from all_objects
where rownum <=2
';
l_data := dbms_xmlgen.getxml(l_query);
util_pkg.http_post(
p_url_in => l_url, p_data_in => l_data);
end;
/
On the receiving end (http://www.example.com/post.cfm for example) I simply read the posted data and insert it into a table. This can be accomplished fairly easily in ColdFusion (You may also use .NET, JSP or whatever server technology you have):
<cfset x = GetHttpRequestData()>
<cfquery name="q" datasource="ora92">
insert into test values ('#x.content#')
</cfquery>
And finally, here is what gets inserted into the table:
<?xml version="1.0"?>
<ROWSET>
<ROW>
<OBJECT_NAME>I_CDEF1</OBJECT_NAME>
<CREATED>05/12/2000</CREATED>
<STATUS>VALID</STATUS>
</ROW>
<ROW>
<OBJECT_NAME>IND$</OBJECT_NAME>
<CREATED>05/12/2000</CREATED>
<STATUS>VALID</STATUS>
</ROW>
</ROWSET>
Pretty neat!
Resources:
Oracle9i Supplied PL/SQL Packages
Retrieving the Contents of an HTTP URL from PL/SQL
HTTP Communication from Within the Oracle Database
Possibly related:
- ColdFusion bug or feature?
- Bye Bye 2006, Welcome 2007
- Read XML from an HTTP POST
- The Q-quote mechanism
- Oracle SQL and PL/SQL Bad Practices Document
Tagged dbms_xmlgen, http, utl_http, xml | Post a Comment


















Hi,
Do you know why I’m getting Null values for all the parameters, I’m sending as part of POST ?
My code looks like :
l_request := UTL_HTTP.begin_request(l_servlet_uri, ‘POST’,UTL_HTTP.HTTP_VERSION_1_0);
UTL_HTTP.SET_HEADER(l_request,’Content-Type’,'text/xml’);
UTL_HTTP.SET_HEADER(l_request,’content-length’,length(l_context_params));
Utl_Http.Write_Text(l_request,l_context_params);
l_context_params contains all the parameters separated by ‘&’.
In the servlet when I try to say getParameter for individual parameters, I get Null values for everything.
Please advice.
February 8th, 2006, at 2:09 pm #Meg, in your line:
UTL_HTTP.SET_HEADER(l_request,’content-length’,length(l_context_params));
I believe that l_context_params should be the parameter containing the actual data (clob maybe?) that needs to be posted.
Then again, I have no idea about the structure of your programs, so I’m just guessing here.
February 9th, 2006, at 1:00 pm #Meg,
Did you ever get this solved? I’m running into the same problem.
Thanks!
March 14th, 2006, at 11:10 am #Hi
I am using the following procdedure passing in these parameters
i_urltext := http://www.clicksms.co.uk:9090/
i_messagetext := sendsmstesttesttest message1000000000
CREATE OR REPLACE PROCEDURE POST_Test (o_replytext out VARCHAR2
,o_return_code out INTEGER
,i_messagetext in VARCHAR2
,i_urltext in VARCHAR2
,i_timeout in INTEGER DEFAULT 60)
IS
sslreq UTL_HTTP.req; /* Secure connection request /
rsp UTL_HTTP.resp; / Secure response /
replymessage VARCHAR2(32767); / reply message (local) /
replyline VARCHAR2(32767); / piece of reply message read from secure site. /
BEGIN
/ Set up wallet information for secure connection capability /
/ remove this line if you don’t have wallet installed and are not using https /
– UTL_HTTP.SET_WALLET(’file:DirectoryPath’,'put password here’);
/ Initiate request to secure site, set parameters /
sslreq := UTL_HTTP.BEGIN_REQUEST(i_urltext,’POST’,'HTTP/1.0′);
UTL_HTTP.SET_HEADER(sslreq,’Content-Type’,'text/xml’);
UTL_HTTP.SET_HEADER(sslreq,’Content-Length’,to_char(length(i_messagetext)));
UTL_HTTP.SET_TRANSFER_TIMEOUT(i_timeout);
/ Write information over secure connection /
UTL_HTTP.WRITE_TEXT(sslreq,i_messagetext);
/ Initialize Response /
rsp:=UTL_HTTP.GET_RESPONSE(sslreq);
replymessage := ”;
/ Retrieve response /
BEGIN
LOOP
UTL_HTTP.READ_LINE(rsp,replyline,TRUE);
replymessage := replymessage || replyline;
END LOOP;
UTL_HTTP.END_RESPONSE(rsp);
EXCEPTION
WHEN UTL_HTTP.END_OF_BODY THEN
UTL_HTTP.END_RESPONSE(rsp);
END;
/ Set output information */
o_replytext := replymessage;
o_return_code := 0;
EXCEPTION
WHEN OTHERS THEN
o_return_code := SQLCODE;
o_replytext := SQLERRM;
END POST_Test;
I am getting a TNS operation timed out error, please can you help
Thanks
March 24th, 2006, at 3:33 am #Rashad
Great sample! It saved me lot of time today. Can I use little changed code in my app?
October 27th, 2006, at 7:28 am #PaweÅ‚, it’s always nice to save time. I do not know what you exactly mean by Can I use little changed code in my app?, but I’ll guess yes anyway.
October 29th, 2006, at 3:50 pm #Hi this is very interesting. Do you know how a pl/sql procedure running under mod_plsql can be coded to be the RECIPIENT of a POST like this (instead of the .cfm in yoiur example)? I am struggling to understand how I could implement this as it seems that you have to send into a pl/sql a procedure name=value pairs (whether using flexible paramater passing or not).
I’d be interested to know if you’ve come across this and a a solution?
Regards
February 21st, 2007, at 6:39 am #Jeremy
Jeremy, I’m afraid I have not come across this or done this before (read an http post body from PL/SQL).
You may want to ask your question at http://forums.oracle.com/forums/
Cheers!
February 23rd, 2007, at 9:11 pm #Hi, this example was very useful to me.
March 26th, 2007, at 1:54 am #Thanks,
Peter.
We are using similar PL/SQL code to post the XML to a WebService.
Erroring Scenario (Generally this code works perfectly in production,But the below case had happened once ):
1) XML has posted succesfully
2) When reading the response ( l_http_resp := utl_http.get_response (l_http_req);) an error occured and control goes to main Exception.
and throwing a “Bad argument” error.
How do Oracle manages a case where XML has posted successfully and then fail to provide success or failure response . ?
Anybody experience a similar error?
Oracle version: DB version 9.2.04 generates the XML and posts on an Oracle Apps Server (HTTPServer).
Sample Code Summarized:
-- Begin the post request -- Set the HTTP request headers -- Write the data to the body of the HTTP request utl_http.write_text(l_http_req, p_data_in); -- Process the request and get the response. l_http_resp := utl_http.get_response (l_http_req);if the response is 200 Then Insert into a post message table which logs the content of succesful message.
if not 200 then I have a parent process which will retry posting after certain time.
Exception
WHEN OTHERS THEN
UTL_HTTP.END_RESPONSE(l_http_resp);
Log Error.
Exact Error shows below.
ORA-29273: HTTP request failed
April 10th, 2007, at 11:39 am #ORA-06512: at “SYS.UTL_HTTP”, line 1380
ORA-29261: bad argument
ORA-06512: at “Prodcode.Package_Name”, line 120 (here line 120 is the PLSQL exception)
ORA-29273: HTTP request failed
ORA-06512: at “SYS.UTL_HTTP
Thanks for the info. This article is good and it might work for me. I was wondering if at the receiving end i need to open a URL from ORACLE Forms, with the following code for hte post, how can I do that? Can I create this procedure at the database level and do the post there and then just invoke the URL from the when-button-pressed trigger using web.show_document()?
The code for hte post is something like this.
/* Code for the POST */
Click this button to view the books related to these courses.
February 20th, 2008, at 11:24 am #DB, I suggest you ask your question on the Forms OTN Forum.
February 20th, 2008, at 12:46 pm #Thanks! Worked well.
March 13th, 2008, at 5:31 am #Hi Eddie
The procedure works, as in it posts to the URL with the parameters, but it also throws an error:
SQL execution error,
ORA-29273: HTTP request failed
ORA-06512: at “SYS.UTL_HTTP”, line 1029 ORA-29261: bad argument
ORA-06512: at “HH.UTIL_PKG”, line 101
This is how im using the code (its in a trigger)
DECLARE
v_url varchar2(200);
l_data clob := ‘1′;
….
BEGIN
…
select REPLACE(REPLACE(:new.input_value,’ ‘,NULL),’-',NULL) into v_phone_num from dual;
– select REPLACE(REPLACE(1234567,’ ‘,NULL),’-',NULL) into v_phone_num from dual;
v_url := ‘http://www.******.com/test.asp?pnum=12345′ || ‘&’ || ‘phone=’ || v_phone_num;
util_pkg.http_post(p_url_in => v_url, p_data_in => l_data);
Im only passing 2 arguments, p_url and p_data_in, what is the bad argument error about?
April 10th, 2008, at 11:42 pm #Any help would be greatly appreciated.