В моей конторе реализовано несколько интеграционных решений с двумя web-сервисами. Вызов осуществляется через utl_http. Процедура вызова сервисов:
1.
2.
3.
4.
5.
6.
7.
begin
pmn_mdm_utils.load_goods_group; -- группа Ассор
pmn_mdm_utils.load_goods_class; -- классы Ассор
pmn_mdm_utils.load_goods_by_date(TRUNC(SYSDATE)-2); -- Ассортимент
pmn_mdm_utils.parse_bank; -- Банки
-- pmn_sap_utils.OrgAndPeople; -- Струк+Перс
end;
Проблема в том что для pmn_sap_utils.OrgAndPeople требуется другая авторизация. Параметры авторизации передаются в явном виде в процедуру вызова:
1.
2.
3.
4.
5.
6.
7.
8.
FUNCTION get_web_data(
p_web_url VARCHAR2,
p_web_login VARCHAR2,
p_web_pass VARCHAR2,
p_req IN CLOB,
p_content_type VARCHAR2 := 'text/xml',
p_http_header VARCHAR2 DEFAULT NULL
) RETURN CLOB
Но по логам видно при выполнении pmn_sap_utils.OrgAndPeople параметры авторизации толи кэшируются, то ли из library cache беруться, хз. Но авторизовываться продолжает под пользователем из первых авторизаций и запрос не проходит.
Если выполнить alter system flush shared pool и попытаться отдельно выполнить pmn_sap_utils.OrgAndPeople то все проходит нормально.
Добавил логирование параметров запроса в процедуру get_web_data
pmn_sap_utils.add_log('Выполнение запроса данных','URL:'||p_web_url||chr(10)||chr(13)||' Авторизация:'||p_web_login);
Данные передаются корректные. Но используются при этом другие. Откуда их Оракл берет хз.
Прошу идей как победить проблему.
Процедура самого запроса к сервисам:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
FUNCTION get_web_data(
p_web_url VARCHAR2,
p_web_login VARCHAR2,
p_web_pass VARCHAR2,
p_req IN CLOB,
p_content_type VARCHAR2 := 'text/xml',
p_http_header VARCHAR2 DEFAULT NULL
) RETURN CLOB
IS
v_http_req utl_http.req;
v_http_resp utl_http.resp;
v_resp_text VARCHAR2(32767);
v_resp CLOB;
v_cnt NUMBER;
v_len NUMBER;
BEGIN
pmn_sap_utils.add_log('Выполнение запроса данных','URL:'||p_web_url||chr(10)||chr(13)||' Авторизация:'||p_web_login);
dbms_lob.createtemporary(v_resp, FALSE);
utl_http.set_transfer_timeout(1800);
v_last_req := p_req;
v_last_http_status := NULL;
v_http_req := utl_http.begin_request(p_web_url, 'POST');
utl_http.set_body_charset(v_http_req, 'utf8');
-- формируем заголовок
utl_http.set_header(v_http_req, 'Content-Type', p_content_type||'; charset=UTF-8');
utl_http.set_header(v_http_req, 'Accept', 'application/soap+xml, application/json, application/dime, multipart/related, text/*');
utl_http.set_header(v_http_req, 'user-agent', 'Axis/1.4');
utl_http.set_header(v_http_req, 'Pragma', 'no-cache');
utl_http.set_header(v_http_req, 'Cache-Control', 'no-cache');
IF p_http_header IS NULL THEN
utl_http.set_header(v_http_req, 'SOAPAction', '');
ELSE
set_http_header(v_http_req, p_http_header);
END IF;
-- считаем длину в байтах в кодировке utf8
v_cnt := 1;
v_len := 0;
WHILE lengthb(substr(p_req, v_cnt, 20000)) <> 0
LOOP
v_len := v_len + lengthb(convert(to_char(substr(p_req, v_cnt, 20000)), 'utf8'));
v_cnt := v_cnt + 20000;
END LOOP;
utl_http.set_header(v_http_req, 'Content-Length', v_len);
-- аутентификация
utl_http.set_authentication(r => v_http_req,
username => p_web_login,
password => p_web_pass,
scheme => 'Basic',
for_proxy => FALSE);
-- передача запроса
v_cnt := 1;
WHILE (lengthb(substr(p_req, v_cnt, 32767)) <> 0)
LOOP
utl_http.write_text(v_http_req, substr(p_req, v_cnt, 32767));
v_cnt := v_cnt + 32767;
END LOOP;
-- получение ответа
v_http_resp := utl_http.get_response(v_http_req);
utl_http.set_body_charset(v_http_resp, 'utf8');
BEGIN
LOOP
utl_http.read_text(v_http_resp, v_resp_text, 32767);
dbms_lob.writeappend(v_resp, length(v_resp_text), v_resp_text);
END LOOP;
EXCEPTION
WHEN utl_http.end_of_body THEN NULL;
END;
IF v_resp IS NOT NULL THEN
BEGIN
v_resp := XMLTYPE(v_resp).Extract('/*').GetClobVal();
EXCEPTION WHEN OTHERS THEN NULL;
END;
END IF;
v_last_http_status.code := v_http_resp.status_code;
v_last_http_status.text := v_http_resp.reason_phrase;
-- вывод отладочной информации
IF v_web_output = 1 THEN
output_long_str('== params ==');
output_long_str('p_web_url = '||p_web_url);
output_long_str('p_web_login = '||p_web_login);
output_long_str('p_web_pass = '||p_web_pass);
output_long_str('== req ==');
output_long_str(substr(p_req, 1, 32000));
output_long_str('== http resp ==');
output_long_str('status_code = '||v_http_resp.status_code);
output_long_str('reason_phrase = '||v_http_resp.reason_phrase);
output_long_str('== resp, len '||length(v_resp)||' ==');
output_long_str(substr(v_resp, 1, 32000));
END IF;
v_last_resp := v_resp;
utl_http.end_response(v_http_resp);
utl_http.end_request(v_http_req);
RETURN v_resp;
EXCEPTION WHEN OTHERS THEN
v_resp_text := SQLERRM||CHR(13)||CHR(10)||dbms_utility.format_error_backtrace;
-- неизвестно где свалилось, поэтому гасим и запрос, и ответ
BEGIN utl_http.end_response(v_http_resp); EXCEPTION WHEN OTHERS THEN NULL; END;
BEGIN utl_http.end_request(v_http_req); EXCEPTION WHEN OTHERS THEN NULL; END;
sys_utils.raise_exception(v_resp_text, 0);
END get_web_data;
Oracle 19.3, платформа Solaris 11 (SPARC)