478 lines
15 KiB
Markdown
478 lines
15 KiB
Markdown
# XLIB_HTTP
|
||
|
||
## Package Specification
|
||
|
||
```sql
|
||
PACKAGE "XLIB_HTTP"
|
||
AS
|
||
/*=========================================================================
|
||
|
||
Purpose : Make http callouts
|
||
|
||
License : Copyright (c) 2010 Dietmar Aust (opal-consulting.de)
|
||
Licensed under a BSD style license (license.txt)
|
||
http://www.opal-consulting.de/pls/apex/f?p=20090928:14
|
||
|
||
Version Date Author Comment
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
19.02.2007 D. Aust initial creation
|
||
07.08.2008 D. Aust - added check_get_request
|
||
- display_url_raw: pass all request headers
|
||
to the client
|
||
05.08.2012 D. Aust suppress mime header TRANSFER-ENCODING,
|
||
causes lots of problems with XMLDB listener
|
||
and others choking.
|
||
2.3.0.0 19.05.2014 D. Aust - #294 - Fix chunked encoding problem in
|
||
xlib_http.get_report
|
||
- added version information to this package
|
||
2.3.0.0 09.05.2015 D. Aust pass JSESSIONID from backend J2EE server to client
|
||
for image rendering in html reports
|
||
2.6.1 28.09.2020 D. Aust - #40 - APEX 20.1 security bundle (PSE 30990551) rejects response header "Cache-Control: private"
|
||
2.6.2 13.10.2020 D. Aust - added function check_acl()
|
||
|
||
=========================================================================*/
|
||
|
||
c_success CONSTANT CHAR (1) := '1';
|
||
c_fail CONSTANT CHAR (1) := '0';
|
||
|
||
-- version of this package
|
||
version_c constant varchar2(20 char) := '2.6.2';
|
||
|
||
TYPE vc_arr_t IS TABLE OF VARCHAR2 (32767) INDEX BY BINARY_INTEGER;
|
||
g_empty_vc_arr vc_arr_t;
|
||
|
||
/* Function: MyFunction
|
||
*
|
||
* Parameters:
|
||
*
|
||
* x - Description of x.
|
||
* y - Description of y.
|
||
* z - Description of z.
|
||
*/
|
||
PROCEDURE display_url_raw (
|
||
p_url VARCHAR2,
|
||
p_mime_type_override IN VARCHAR2 DEFAULT NULL,
|
||
p_charset IN VARCHAR2 DEFAULT NULL,
|
||
p_header_name_arr IN vc_arr_t default g_empty_vc_arr,
|
||
p_header_value_arr IN vc_arr_t default g_empty_vc_arr
|
||
);
|
||
|
||
/* Procedure: retrieve_blob_from_url
|
||
|
||
Multiplies two integers.
|
||
|
||
Parameters:
|
||
|
||
p_url - url to be called
|
||
|
||
o_blob - output: the resulting out blob
|
||
o_mime_type - output: the resulting out mime type from the call
|
||
|
||
Returns:
|
||
|
||
The two integers multiplied together.
|
||
o_blob - the resulting out blob
|
||
|
||
See Also:
|
||
|
||
<escape_form_data>
|
||
*/
|
||
PROCEDURE retrieve_blob_from_url (
|
||
p_url VARCHAR2,
|
||
o_blob OUT BLOB,
|
||
o_mime_type OUT VARCHAR2
|
||
);
|
||
|
||
/*
|
||
Function: escape_form_data
|
||
Here is some describing text ...
|
||
|
||
--- SQL
|
||
declare
|
||
l_i number;
|
||
begin
|
||
null;
|
||
|
||
Select count(*)
|
||
into l_count
|
||
from dual;
|
||
end;
|
||
---
|
||
|
||
|
||
Parameters:
|
||
s - string to be escaped
|
||
|
||
Returns:
|
||
the escaped data
|
||
*/
|
||
FUNCTION escape_form_data (s VARCHAR2)
|
||
RETURN VARCHAR2;
|
||
|
||
/*
|
||
Function: check_get_request
|
||
|
||
Parameters:
|
||
p_url the url to be called
|
||
|
||
Returns:
|
||
Returns c_fail or c_success
|
||
|
||
*/
|
||
FUNCTION check_get_request (p_url VARCHAR2)
|
||
RETURN CHAR;
|
||
|
||
/*
|
||
Function: check_acl
|
||
|
||
Parameters:
|
||
p_url the url to be called
|
||
|
||
Returns:
|
||
Returns c_fail or c_success
|
||
*/
|
||
FUNCTION check_acl (p_url VARCHAR2)
|
||
RETURN CHAR;
|
||
END;```
|
||
|
||
## Package Body
|
||
|
||
```sql
|
||
PACKAGE BODY "XLIB_HTTP"
|
||
AS
|
||
/*=========================================================================
|
||
|
||
Purpose : Make http callouts
|
||
|
||
License : Copyright (c) 2010 Dietmar Aust (opal-consulting.de)
|
||
Licensed under a BSD style license (license.txt)
|
||
https://github.com/daust/JasperReportsIntegration
|
||
|
||
Version Date Author Comment
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
19.02.2007 D. Aust initial creation
|
||
07.08.2008 D. Aust - added check_get_request
|
||
- display_url_raw: pass all request headers
|
||
to the client
|
||
05.08.2012 D. Aust suppress mime header TRANSFER-ENCODING,
|
||
causes lots of problems with XMLDB listener
|
||
and others choking.
|
||
2.3.0.0 19.05.2014 D. Aust - #294 - Fix chunked encoding problem in
|
||
xlib_http.get_report
|
||
- added version information to this package
|
||
2.3.0.0 09.05.2015 D. Aust pass JSESSIONID from backend J2EE server to client
|
||
for image rendering in html reports
|
||
2.6.1 28.09.2020 D. Aust - #40 - APEX 20.1 security bundle (PSE 30990551) rejects response header "Cache-Control: private"
|
||
2.6.2 13.10.2020 D. Aust - added function check_acl()
|
||
|
||
=========================================================================*/
|
||
|
||
m_module VARCHAR2 (50) := 'XLIB_HTTP';
|
||
|
||
PROCEDURE display_url_raw (
|
||
p_url VARCHAR2,
|
||
p_mime_type_override IN VARCHAR2 DEFAULT NULL,
|
||
p_charset IN VARCHAR2 DEFAULT NULL,
|
||
p_header_name_arr IN vc_arr_t default g_empty_vc_arr,
|
||
p_header_value_arr IN vc_arr_t default g_empty_vc_arr
|
||
)
|
||
IS
|
||
l_http_request UTL_HTTP.req;
|
||
l_http_response UTL_HTTP.resp;
|
||
l_blob BLOB;
|
||
l_raw RAW (32767);
|
||
l_buffer_size NUMBER := 32767;
|
||
--
|
||
l_proc VARCHAR2 (100) := m_module || '.DISPLAY_URL_RAW';
|
||
--
|
||
l_mime_type VARCHAR2 (100);
|
||
l_header_name VARCHAR2 (256);
|
||
l_header_value VARCHAR2 (1024);
|
||
l_jsession VARCHAR2 (256);
|
||
l_path VARCHAR2 (1024);
|
||
--
|
||
l_header_name_arr vc_arr_t;
|
||
l_header_value_arr vc_arr_t;
|
||
--
|
||
l_msg varchar2(32767);
|
||
BEGIN
|
||
xlog (l_proc, 'show url: ' || p_url);
|
||
--htp.flush();
|
||
--htp.init();
|
||
|
||
-- Initialize the BLOB.
|
||
DBMS_LOB.createtemporary (l_blob, FALSE);
|
||
|
||
l_http_request := UTL_HTTP.begin_request (url => p_url,
|
||
method => 'GET',
|
||
http_version => utl_http.http_version_1_0);
|
||
|
||
utl_http.set_header (l_http_request, 'Connection', 'Keep-Alive');
|
||
|
||
-- pass additional headers to the target service
|
||
for i in 1..p_header_name_arr.count loop
|
||
xlog(l_proc, 'pass additional headers to target service: '|| p_header_name_arr(i) ||': '||p_header_value_arr(i));
|
||
utl_http.set_header(l_http_request, p_header_name_arr(i), p_header_value_arr(i));
|
||
end loop;
|
||
|
||
-- get response from target service
|
||
l_http_response := UTL_HTTP.get_response (l_http_request);
|
||
|
||
FOR i IN 1 .. UTL_HTTP.get_header_count (l_http_response)
|
||
LOOP
|
||
UTL_HTTP.get_header (l_http_response,
|
||
i,
|
||
l_header_name,
|
||
l_header_value
|
||
);
|
||
-- store header value in arr
|
||
l_header_name_arr (i) := l_header_name;
|
||
l_header_value_arr (i) := l_header_value;
|
||
|
||
IF LOWER (l_header_name) = 'content-type'
|
||
THEN
|
||
l_mime_type := l_header_value;
|
||
xlog(l_proc, 'content-type from server: ' || l_mime_type);
|
||
END IF;
|
||
END LOOP;
|
||
|
||
-- override mime type
|
||
IF p_mime_type_override IS NOT NULL
|
||
THEN
|
||
l_mime_type := p_mime_type_override;
|
||
END IF;
|
||
|
||
-- Copy the response into the BLOB.
|
||
BEGIN
|
||
LOOP
|
||
UTL_HTTP.read_raw (l_http_response, l_raw, l_buffer_size);
|
||
DBMS_LOB.writeappend (l_blob, UTL_RAW.LENGTH (l_raw), l_raw);
|
||
END LOOP;
|
||
EXCEPTION
|
||
WHEN UTL_HTTP.end_of_body
|
||
THEN
|
||
UTL_HTTP.end_response (l_http_response);
|
||
END;
|
||
|
||
xlog(l_proc, 'set content-type: ' || l_mime_type);
|
||
OWA_UTIL.mime_header (ccontent_type => l_mime_type,
|
||
bclose_header => FALSE,
|
||
ccharset => p_charset
|
||
);
|
||
|
||
FOR i IN 1 .. l_header_name_arr.COUNT
|
||
LOOP
|
||
IF UPPER (l_header_name_arr (i)) IN
|
||
('CONTENT-LENGTH', 'CONTENT-TYPE', 'MIME-TYPE', 'TRANSFER-ENCODING',
|
||
'STRICT-TRANSPORT-SECURITY', 'CACHE-CONTROL', 'PRAGMA', 'EXPIRES')
|
||
THEN
|
||
--xlog (l_proc, 'skip header ' || l_header_name_arr (i));
|
||
null;
|
||
ELSE
|
||
if upper(l_header_name_arr(i)) = 'SET-COOKIE' and l_header_value_arr (i) like 'JSESSIONID%' then
|
||
xlog(l_proc , 'JSESSION_ID found !!!:'||l_header_value_arr (i));
|
||
--extract path
|
||
l_jsession := regexp_substr(l_header_value_arr (i), 'JSESSIONID=(.*);[ ]*Path',1, 1,'i',1);
|
||
l_path := regexp_substr(l_header_value_arr (i), ';[ ]*Path=(.*)',1, 1,'i',1);
|
||
|
||
xlog(l_proc, 'xx:full:'||l_header_value_arr (i)|| '; xx:session:'||l_jsession || '; xx:path:'||l_path);
|
||
else
|
||
l_header_value := l_header_value_arr (i);
|
||
end if;
|
||
xlog (l_proc,
|
||
'set header:'
|
||
|| l_header_name_arr (i)
|
||
|| ': '
|
||
|| l_header_value
|
||
);
|
||
HTP.p (l_header_name_arr (i) || ': ' || l_header_value);
|
||
END IF;
|
||
END LOOP;
|
||
|
||
-- JSESSION Cookies ausgeben
|
||
-- if using tunnel, then the cookie is JRI_JSESSIONID
|
||
-- if not using tunnel, then cookie is JSESSIONID directly
|
||
--
|
||
if xlib_jasperreports.get_use_images_no_tunnel=false then
|
||
l_msg := 'Set-Cookie: ' || xlib_jasperreports.m_jri_cookie_name_c || '=' || l_jsession;
|
||
xlog (l_proc, 'set header:' || l_msg );
|
||
HTP.p (l_msg);
|
||
l_msg := 'Set-Cookie: ' || xlib_jasperreports.m_jri_path_cookie_name_c || '=' || l_path;
|
||
xlog (l_proc, 'set header:' || l_msg );
|
||
HTP.p (l_msg);
|
||
else
|
||
l_msg := 'Set-Cookie: JSESSIONID=' || l_jsession;
|
||
if xlib_jasperreports.get_cookie_path_no_tunnel is not null then
|
||
l_msg := l_msg || '; Path=' || xlib_jasperreports.get_cookie_path_no_tunnel;
|
||
end if;
|
||
xlog (l_proc, 'set header:' || l_msg );
|
||
HTP.p (l_msg);
|
||
end if;
|
||
|
||
-- set content length
|
||
HTP.p ('Content-length: ' || DBMS_LOB.getlength (l_blob));
|
||
OWA_UTIL.http_header_close;
|
||
WPG_DOCLOAD.download_file (l_blob);
|
||
-- Relase the resources associated with the temporary LOB.
|
||
DBMS_LOB.freetemporary (l_blob);
|
||
EXCEPTION
|
||
WHEN UTL_HTTP.end_of_body
|
||
THEN
|
||
UTL_HTTP.end_response (l_http_response);
|
||
DBMS_LOB.freetemporary (l_blob);
|
||
RAISE;
|
||
WHEN OTHERS
|
||
THEN
|
||
xlog (l_proc, 'Error: ' || SQLERRM, 'ERROR');
|
||
RAISE;
|
||
END;
|
||
|
||
PROCEDURE retrieve_blob_from_url (
|
||
p_url VARCHAR2,
|
||
o_blob OUT BLOB,
|
||
o_mime_type OUT VARCHAR2
|
||
)
|
||
IS
|
||
l_http_request UTL_HTTP.req;
|
||
l_http_response UTL_HTTP.resp;
|
||
l_raw RAW (32767);
|
||
--
|
||
l_proc VARCHAR2 (100)
|
||
:= m_module || '.RETRIEVE_BLOB_FROM_URL';
|
||
--
|
||
l_header_name VARCHAR2 (256);
|
||
l_header_value VARCHAR2 (1024);
|
||
BEGIN
|
||
-- Initialize the BLOB.
|
||
dbms_lob.createtemporary (o_blob, false);
|
||
l_http_request := utl_http.begin_request (url => p_url,
|
||
method => 'GET',
|
||
http_version => utl_http.http_version_1_0);
|
||
|
||
l_http_response := UTL_HTTP.get_response (l_http_request);
|
||
|
||
FOR i IN 1 .. UTL_HTTP.get_header_count (l_http_response)
|
||
LOOP
|
||
UTL_HTTP.get_header (l_http_response,
|
||
i,
|
||
l_header_name,
|
||
l_header_value
|
||
);
|
||
|
||
IF LOWER (l_header_name) = 'content-type'
|
||
THEN
|
||
o_mime_type := l_header_value;
|
||
END IF;
|
||
END LOOP;
|
||
|
||
-- Copy the response into the BLOB.
|
||
BEGIN
|
||
LOOP
|
||
UTL_HTTP.read_raw (l_http_response, l_raw, 32767);
|
||
DBMS_LOB.writeappend (o_blob, UTL_RAW.LENGTH (l_raw), l_raw);
|
||
END LOOP;
|
||
EXCEPTION
|
||
WHEN UTL_HTTP.end_of_body
|
||
THEN
|
||
UTL_HTTP.end_response (l_http_response);
|
||
END;
|
||
-- Relase the resources associated with the temporary LOB.
|
||
--DBMS_LOB.freetemporary (l_blob);
|
||
EXCEPTION
|
||
WHEN OTHERS
|
||
THEN
|
||
UTL_HTTP.end_response (l_http_response);
|
||
DBMS_LOB.freetemporary (o_blob);
|
||
xlog (l_proc, 'Error: ' || SQLERRM, 'ERROR');
|
||
RAISE;
|
||
END;
|
||
|
||
FUNCTION escape_form_data (s VARCHAR2)
|
||
RETURN VARCHAR2
|
||
IS
|
||
l_s VARCHAR2 (500 CHAR);
|
||
|
||
FUNCTION r (s VARCHAR2, c VARCHAR2)
|
||
RETURN VARCHAR2
|
||
IS
|
||
BEGIN
|
||
RETURN REPLACE (s, c, '%' || TRIM (TO_CHAR (ASCII (c), 'XX')));
|
||
END;
|
||
BEGIN
|
||
l_s := s;
|
||
l_s := REPLACE (l_s, ' ', '+');
|
||
l_s := r (l_s, chr(37)); -- %
|
||
l_s := r (l_s, chr(37)); -- /
|
||
l_s := r (l_s, chr(63)); -- ?
|
||
l_s := r (l_s, chr(38)); -- &
|
||
l_s := r (l_s, chr(228)); -- <20><><EFBFBD>
|
||
l_s := r (l_s, chr(196)); -- <20><>
|
||
l_s := r (l_s, chr(246)); -- <20><>
|
||
l_s := r (l_s, chr(214)); -- <20><>
|
||
l_s := r (l_s, chr(252)); -- <20><>
|
||
l_s := r (l_s, chr(220)); -- <20><><EFBFBD>
|
||
l_s := r (l_s, chr(223)); -- <20><><EFBFBD>
|
||
RETURN l_s;
|
||
END;
|
||
|
||
FUNCTION check_get_request (p_url VARCHAR2)
|
||
RETURN CHAR
|
||
IS
|
||
l_clob CLOB;
|
||
BEGIN
|
||
IF p_url IS NULL
|
||
THEN
|
||
RETURN c_fail;
|
||
END IF;
|
||
|
||
SELECT HTTPURITYPE (p_url).getclob ()
|
||
INTO l_clob
|
||
FROM DUAL;
|
||
|
||
/*SELECT c_success
|
||
INTO l_ret
|
||
FROM DUAL
|
||
WHERE EXISTS (SELECT HTTPURITYPE (p_url).getclob ()
|
||
FROM DUAL);
|
||
*/
|
||
RETURN c_success;
|
||
EXCEPTION
|
||
WHEN OTHERS
|
||
THEN
|
||
RETURN c_fail;
|
||
END;
|
||
|
||
FUNCTION check_acl (p_url VARCHAR2)
|
||
RETURN CHAR
|
||
IS
|
||
l_clob CLOB;
|
||
BEGIN
|
||
IF p_url IS NULL
|
||
THEN
|
||
RETURN c_fail;
|
||
END IF;
|
||
|
||
SELECT HTTPURITYPE (p_url).getclob ()
|
||
INTO l_clob
|
||
FROM DUAL;
|
||
|
||
/*SELECT c_success
|
||
INTO l_ret
|
||
FROM DUAL
|
||
WHERE EXISTS (SELECT HTTPURITYPE (p_url).getclob ()
|
||
FROM DUAL);
|
||
*/
|
||
RETURN c_success;
|
||
EXCEPTION
|
||
WHEN OTHERS
|
||
THEN
|
||
-- acl problem
|
||
if sqlcode=24247 then
|
||
RETURN c_fail;
|
||
else
|
||
-- no acl problem
|
||
return c_success;
|
||
end if;
|
||
END;
|
||
END;```
|