Consolidate functions to avoid duplication

Broke out to avoid duplication, as requested by mortenbra. Response is
now passed around internally as a record, with a flag to indicate
whether the BLOB or CLOB is relevant.
This commit is contained in:
Eric Olson 2015-04-06 16:49:18 -05:00
parent 9c8dceb985
commit ebe4c7655e
2 changed files with 111 additions and 270 deletions

View File

@ -1,5 +1,13 @@
create or replace package body ntlm_http_pkg create or replace package body ntlm_http_pkg
as as
c_blob constant number(1) := 0;
c_clob constant number(1) := 1;
type t_response_body is record (
l_blob blob,
l_clob clob,
l_blob_or_clob number(1) default 1
);
/* /*
@ -51,12 +59,55 @@ begin
end headers_contain_value; end headers_contain_value;
function get_response_blob (p_url in varchar2, procedure get_response_body (p_resp in out utl_http.resp, p_response_body in out nocopy t_response_body)
as
l_bdata raw(32767);
l_cdata string_util_pkg.t_max_pl_varchar2;
begin
/*
Purpose: get the response body as a blob
Remarks:
Who Date Description
------ ---------- --------------------------------
MBR 24.06.2011 Created
EAO 22.03.2015 Works with BLOBs
*/
if p_response_body.l_blob_or_clob = c_blob then
begin
loop
utl_http.read_raw(r => p_resp, data => l_bdata);
dbms_lob.append( p_response_body.l_blob, to_blob( l_bdata ));
end loop;
exception
when utl_http.end_of_body then
null;
end;
else
begin
loop
utl_http.read_text(r => p_resp, data => l_cdata);
p_response_body.l_clob := p_response_body.l_clob || l_cdata;
end loop;
exception
when utl_http.end_of_body then
null;
end;
end if;
end get_response_body;
procedure get_response (p_url in varchar2,
p_username in varchar2, p_username in varchar2,
p_password in varchar2, p_password in varchar2,
p_wallet_path in varchar2 := null, p_wallet_path in varchar2 := null,
p_wallet_password in varchar2 := null, p_wallet_password in varchar2 := null,
p_proxy_server in varchar2 := null) return blob p_proxy_server in varchar2 := null,
p_response_body in out nocopy t_response_body)
as as
l_req utl_http.req; l_req utl_http.req;
@ -77,61 +128,13 @@ as
l_authenticate_message varchar2(500); l_authenticate_message varchar2(500);
function get_response_body (p_resp in out utl_http.resp) return blob
as
l_data raw(32767);
l_returnvalue blob;
begin
/*
Purpose: get the response body as a blob
Remarks:
Who Date Description
------ ---------- --------------------------------
MBR 24.06.2011 Created
*/
dbms_lob.createtemporary( l_returnvalue, true );
begin
loop
utl_http.read_raw(r => p_resp, data => l_data);
dbms_lob.append( l_returnvalue, to_blob( l_data ));
end loop;
exception
when utl_http.end_of_body then
null;
end;
return l_returnvalue;
end get_response_body;
procedure debug_response (p_resp in out utl_http.resp) procedure debug_response (p_resp in out utl_http.resp)
as as
l_name varchar2(255); l_name varchar2(255);
l_value varchar2(2000); l_value varchar2(2000);
l_body blob; l_body clob;
begin begin
/*
Purpose: print debug info about the response
Remarks:
Who Date Description
------ ---------- --------------------------------
MBR 24.06.2011 Created
*/
debug_pkg.printf('Response Status Code: %1', p_resp.status_code); debug_pkg.printf('Response Status Code: %1', p_resp.status_code);
for i in 1 .. utl_http.get_header_count (p_resp) loop for i in 1 .. utl_http.get_header_count (p_resp) loop
@ -139,7 +142,7 @@ as
debug_pkg.printf('#%1 %2 : %3', i, l_name, l_value); debug_pkg.printf('#%1 %2 : %3', i, l_name, l_value);
end loop; end loop;
l_returnvalue := get_response_body (p_resp); get_response_body (p_resp, p_response_body);
debug_pkg.printf('Body length = %1', dbms_lob.getlength (l_returnvalue)); debug_pkg.printf('Body length = %1', dbms_lob.getlength (l_returnvalue));
debug_pkg.printf('Persistent connection count: %1', utl_http.get_persistent_conn_count); debug_pkg.printf('Persistent connection count: %1', utl_http.get_persistent_conn_count);
@ -148,7 +151,6 @@ as
begin begin
/* /*
Purpose: Get response clob from URL Purpose: Get response clob from URL
@ -270,7 +272,45 @@ begin
utl_http.close_persistent_conns; utl_http.close_persistent_conns;
debug_pkg.printf('Persistent connection count (should be zero): %1', utl_http.get_persistent_conn_count); debug_pkg.printf('Persistent connection count (should be zero): %1', utl_http.get_persistent_conn_count);
return l_returnvalue; end get_response;
function get_response_blob (p_url in varchar2,
p_username in varchar2,
p_password in varchar2,
p_wallet_path in varchar2 := null,
p_wallet_password in varchar2 := null,
p_proxy_server in varchar2 := null) return blob
as
l_response_body t_response_body;
begin
/*
Purpose: Get response clob from URL
Remarks: see http://davenport.sourceforge.net/ntlm.html#ntlmHttpAuthentication
Who Date Description
------ ---------- --------------------------------
FDL 11.05.2011 Created
MBR 03.06.2011 Lots of changes
EAO 22.03.2015 Most functionality moved to get_response
*/
dbms_lob.createtemporary( l_response_body.l_blob, true);
l_response_body.l_blob_or_clob := c_blob;
get_response(
p_url => get_response_blob.p_url,
p_username => get_response_blob.p_username,
p_password => get_response_blob.p_password,
p_wallet_path => get_response_blob.p_wallet_path,
p_wallet_password => get_response_blob.p_wallet_password,
p_proxy_server => get_response_blob.p_proxy_server,
p_response_body => l_response_body);
return l_response_body.l_blob;
end get_response_blob; end get_response_blob;
@ -282,218 +322,21 @@ function get_response_clob (p_url in varchar2,
p_wallet_password in varchar2 := null, p_wallet_password in varchar2 := null,
p_proxy_server in varchar2 := null) return clob p_proxy_server in varchar2 := null) return clob
as as
l_response_body t_response_body;
l_req utl_http.req;
l_resp utl_http.resp;
l_returnvalue clob;
l_authenticate_with_ntlm boolean;
l_name varchar2(500);
l_value varchar2(500);
l_ntlm_message varchar2(500);
l_negotiate_message varchar2(500);
l_server_challenge raw(4000);
l_negotiate_flags raw(4000);
l_authenticate_message varchar2(500);
function get_response_body (p_resp in out utl_http.resp) return clob
as
l_data string_util_pkg.t_max_pl_varchar2;
l_returnvalue clob;
begin begin
dbms_lob.createtemporary( l_response_body.l_clob, true);
/* l_response_body.l_blob_or_clob := c_clob;
Purpose: get the response body as a clob get_response(
p_url => get_response_clob.p_url,
Remarks: p_username => get_response_clob.p_username,
p_password => get_response_clob.p_password,
Who Date Description p_wallet_path => get_response_clob.p_wallet_path,
------ ---------- -------------------------------- p_wallet_password => get_response_clob.p_wallet_password,
MBR 24.06.2011 Created p_proxy_server => get_response_clob.p_proxy_server,
p_response_body => l_response_body);
*/
return l_response_body.l_clob;
begin
loop
utl_http.read_text(r => p_resp, data => l_data);
l_returnvalue := l_returnvalue || l_data;
end loop;
exception
when utl_http.end_of_body then
null;
end;
return l_returnvalue;
end get_response_body;
procedure debug_response (p_resp in out utl_http.resp)
as
l_name varchar2(255);
l_value varchar2(2000);
l_body clob;
begin
/*
Purpose: print debug info about the response
Remarks:
Who Date Description
------ ---------- --------------------------------
MBR 24.06.2011 Created
*/
debug_pkg.printf('Response Status Code: %1', p_resp.status_code);
for i in 1 .. utl_http.get_header_count (p_resp) loop
utl_http.get_header (p_resp, i, l_name, l_value);
debug_pkg.printf('#%1 %2 : %3', i, l_name, l_value);
end loop;
l_returnvalue := get_response_body (p_resp);
debug_pkg.printf('Body length = %1', dbms_lob.getlength (l_returnvalue));
debug_pkg.printf('Persistent connection count: %1', utl_http.get_persistent_conn_count);
end debug_response;
begin
/*
Purpose: Get response clob from URL
Remarks: see http://davenport.sourceforge.net/ntlm.html#ntlmHttpAuthentication
Who Date Description
------ ---------- --------------------------------
FDL 11.05.2011 Created
MBR 03.06.2011 Lots of changes
*/
utl_http.set_detailed_excp_support (enable => true);
utl_http.set_response_error_check (false);
utl_http.set_persistent_conn_support (true, 10);
debug_pkg.printf('Persistent connection count: %1', utl_http.get_persistent_conn_count);
-- support for HTTPS
if instr(lower(p_url),'https') = 1 then
utl_http.set_wallet (p_wallet_path, p_wallet_password);
end if;
-- support for proxy server
if p_proxy_server is not null then
utl_http.set_proxy (p_proxy_server);
end if;
------------
-- Request 1
------------
debug_pkg.printf(' ');
debug_pkg.printf(p_url);
l_req := utl_http.begin_request(p_url);
l_resp := utl_http.get_response (l_req);
debug_response (l_resp);
if l_resp.status_code = utl_http.HTTP_UNAUTHORIZED then
l_authenticate_with_ntlm := headers_contain_value (l_resp, 'WWW-Authenticate', 'NTLM');
utl_http.end_response (l_resp);
if l_authenticate_with_ntlm then
l_negotiate_message := 'NTLM ' || ntlm_util_pkg.get_negotiate_message(p_username);
-- need to send negotiation message
debug_pkg.printf('Negotiate message: %1', l_negotiate_message);
------------
-- Request 2
------------
debug_pkg.printf(' ');
debug_pkg.printf(p_url);
l_req := utl_http.begin_request(p_url);
utl_http.set_header (l_req, 'Authorization', l_negotiate_message);
l_resp := utl_http.get_response(l_req);
debug_response (l_resp);
if l_resp.status_code = utl_http.HTTP_UNAUTHORIZED then
-- received server challenge
utl_http.get_header_by_name(l_resp, 'WWW-Authenticate', l_value, 1);
utl_http.end_response(l_resp);
if substr(l_value, 1, 4) = 'NTLM' then
-- get value
l_value := substr(l_value, 6);
ntlm_util_pkg.parse_challenge_message (l_value, l_server_challenge, l_negotiate_flags);
l_authenticate_message := 'NTLM ' || ntlm_util_pkg.get_authenticate_message(p_username, p_password, l_server_challenge, l_negotiate_flags);
debug_pkg.printf('Authenticate message: "%1"', l_authenticate_message);
------------
-- Request 3
------------
-- sending NTLM message 3
debug_pkg.printf(' ');
debug_pkg.printf(p_url);
l_req := utl_http.begin_request(p_url);
utl_http.set_header (l_req, 'Connection', 'close');
utl_http.set_header (l_req, 'Authorization', l_authenticate_message);
l_resp := utl_http.get_response (l_req);
debug_response (l_resp);
-- this is already done inside debug_response
--l_returnvalue := get_response_body (l_resp);
utl_http.end_response(l_resp);
end if;
end if;
else
debug_pkg.printf('Server is not configured with NTLM security (missing "WWW-Authenticate: NTLM" header).');
end if;
end if;
utl_http.close_persistent_conns;
debug_pkg.printf('Persistent connection count (should be zero): %1', utl_http.get_persistent_conn_count);
return l_returnvalue;
end get_response_clob; end get_response_clob;
@ -697,4 +540,3 @@ end end_request;
end ntlm_http_pkg; end ntlm_http_pkg;
/ /

View File

@ -47,4 +47,3 @@ as
end ntlm_http_pkg; end ntlm_http_pkg;
/ /