REST service works via Postman, not using PL/SQL - oracle

I am new to programming with REST services, and I'm hitting a bit of a wall.
I need to be able to access a specific set of REST services from Oracle PL/SQL. The guy who knows about the services knows nothing about PL/SQL. Bridging the gap is proving difficult.
This, in POSTMAN, works:
(Apparently I'm too new to the site to post screen shots)
Action: POST
URL: http://dev-osb.sh.com/LDAP/LDAPVndrMgmt
Authorization: basic, username & password
Body: Raw, JSON
{
"requestType": "listAccounts",
"uid": "FTTestDlete100",
"vendorRole": "FreightTrackingLATA" }
And I get back all the results I expected in JSON format.
This PL/SQL should (as near as I can tell) do the same, but it doesn't.
DECLARE
l_clob clob;
l_json clob;
BEGIN
--create the JSON request body
apex_json.initialize_clob_output();
apex_json.open_object();
apex_json.write('requestType', 'listAccounts');
apex_json.write('uid', 'FTTestDlete100');
apex_json.write('vendorRole', 'FreightTrackingLATA');
apex_json.close_all();
l_json := apex_json.get_clob_output();
apex_json.free_output();
l_clob := apex_web_service.make_rest_request(
p_url => 'http://dev-osb.sh.com/LDAP/LDAPVndrMgt',
p_username => 'theUserName',
p_password => 'thepassword',
p_http_method => 'POST',
p_parm_name => apex_util.string_to_table('Content-Type'),
p_parm_value => apex_util.string_to_table('application/json'),
p_body => l_json
);
dbms_output.put_line(to_char(l_clob));
END;
As shown I get "{ "errorMessage" : "No acceptable request representation was found" }"
If I remove the /LDAP/LDAPVndrMgt portion from the URL, I get some HTML code saying:
**Error 404--Not Found
The server has not found anything matching the Request-URI. No indication is given of whether the condition is temporary or permanent.If the server does not wish to make this information available to the client, the status code 403 (Forbidden) can be used instead. The 410 (Gone) status code SHOULD be used if the server knows, through some internally configurable mechanism, that an old resource is permanently unavailable and has no forwarding address.**
So - something isn't working right. It's like the resource part (starting at /LDAP...) can't be concatenated onto the URL in the PL/SQL function, but without it I get a 404. I'm hoping to avoid having to go the UTL_HTTP route. Any suggestions?

Breakthrough - I found out that my PL/SQL was sending what should have been headers as parameters.
Here's the working code:
DECLARE
l_clob clob;
l_json clob;
BEGIN
apex_web_service.g_request_headers(1).NAME := 'Content-Type';
apex_web_service.g_request_headers(1).VALUE := 'application/json';
--create the JSON request body
apex_json.initialize_clob_output();
apex_json.open_object();
apex_json.write('requestType', 'listAccounts');
apex_json.write('uid', 'FTTestDlete100');
apex_json.write('vendorRole', 'FreightTrackingLATA');
apex_json.close_all();
l_json := apex_json.get_clob_output();
apex_json.free_output();
l_clob := apex_web_service.make_rest_request(
p_url => 'http://dev-osb.sh.com/LDAP/LDAPVndrMgt',
p_username => 'theUserName',
p_password => 'thepassword',
p_http_method => 'POST',
p_body => l_json
);
dbms_output.put_line(to_char(l_clob));
END;

Related

How to terminate a POST web service call - ORDS

Please excuse my ignorance as I am a total beginner.
I have created a basic RESTful Web Services Using PL/SQL, sample code below(which works perfectly fine)
ords.define_template(
p_module_name => 'restDemo',
p_pattern => 'updateClient');
ords.define_handler(
p_module_name => 'restDemo',
p_pattern => 'updateClient',
p_method => 'POST',
p_source_type => ords.source_type_plsql,
p_source => 'declare
w_clob clob := :body_text;
begin
ws.ws_interface.update_client(w_clob);
exception
when others then
package.ws_interface.g_result_rec.result_message := SQLERRM;
end;');
When ws_interface.update_client is initiated via the post request, in the initialization of ws_interface package, I am calling a routine thats determines if the client can be updated or not (based on access of the user logged in to the DB).
If the user does not have access to execute the updateClient service - I want to terminate the service call, which I have no idea on how to go about do this.
So my question is:
How do I go about terminating the current active updateClient webservice call ?
In your ws_interface package, if the client can not be updated, then you just need to return so that the PL/SQL block in the POST definition will complete. Your code can look something like this:
---Beginning of package
...
procedure update_client (some_clob clob) is
begin
--The client can not be updated so do no more processing.
if can_update_client = false then
--Some sort of error message could also be added here
return;
end if;
--Rest of processing for updating the client
end;
...
---End of package

Using UTL_HTTP to call a Webservice from PL/SQL Procedure - Error 403 Forbidden access is denied

I need your help.It's been almost 2 months that I am trying to call a webservice from a PL/SQL procedure.
I can call the webservice using Chrome Extension ARC.
But when I use the UTL_HTTP Oracle API, it is not working.
Here is my code (some lines are missing but I managed to show you the major lines)
DECLARE
http_method VARCHAR2(10) := 'POST';
CONTENT_TYPE_HEADER VARCHAR2(30) := 'Content-Type';
CONTENT_TYPE_LENGTH VARCHAR2(30) := 'Content-length';
CONTENT_TYPE_VALUE VARCHAR2(30) := 'text/plain';
v_param_length NUMBER :=12;
BEGIN
UTL_HTTP.SET_TRANSFER_TIMEOUT(request_timeout);
req := UTL_HTTP.BEGIN_REQUEST (url => UTL_URL.ESCAPE(v_url_1), method => http_method);
utl_http.set_authentication(req, 'myuser', '1234', 'Basic', FALSE);
UTL_HTTP.SET_HEADER (r => req, name => CONTENT_TYPE_HEADER, value => CONTENT_TYPE_VALUE);
UTL_HTTP.SET_HEADER (r => req, name => CONTENT_TYPE_LENGTH, value => v_param_length);
resp := UTL_HTTP.GET_RESPONSE(r => req);
UTL_HTTP.END_RESPONSE(resp);
EXCEPTION
WHEN UTL_HTTP.END_OF_BODY THEN
BEGIN
UTL_HTTP.END_RESPONSE(resp);
END;
WHEN UTL_HTTP.TOO_MANY_REQUESTS THEN
UTL_HTTP.END_RESPONSE(resp);
END;
This is the error :
<div id="header"><h1>Server Error</h1></div>
<div id="content">
<div class="content-container"><fieldset>
<h2>403 - Forbidden: Access is denied.</h2>
<h3>You do not have permission to view this directory or page using the credentials that you supplied.</h3>
</fieldset></div>
The administrator told me that this error is not caused by the proxy :
DISABLE PROXY
[myuser#myserver ~]$ export https_proxy=
[myuser#myserver ~]$ export http_proxy=
TEST CONNECTION
[myuser#myserver ~]$ wget http://my-server-ws:1234
--2017-02-28 13:14:17-- http://my-server-ws:1234/ Resolving my-server-ws (my-server-ws)... 10.10.5.70 Connecting to my-server-ws
(my-server-ws)|10.10.5.70|:1234... connected. HTTP request sent,
awaiting response... 403 Forbidden 2017-02-28 13:14:17 ERROR 403:
Forbidden.
403 response generally indicates one of two conditions:
Authentication was provided, but the authenticated user is not permitted to perform the requested operation.
->check if your user have all necessary permissions
The operation is forbidden to all users. For example, requests for a directory listing return code 403 when directory listing has been disabled.
->check the settings from your webserver.

Get data with restful webservices from Oracle PL/SQL

I want to get data from webservices from oracle database.
But I'm looking for it unfortunately I can't anything .
Please give me some hints.I want to accesses it with username and password in pl/sql code.
How can I do it?
Thank you..
I solve it like following code.I think it will be useful .
declare
t_http_req utl_http.req;
t_http_resp utl_http.resp;
t_request_body varchar2(30000);
t_respond varchar2(30000);
t_start_pos integer := 1;
t_output varchar2(2000);
begin
/*Construct the information you want to send to the webservice.
Normally this would be in a xml structure. But for a REST-
webservice this is not mandatory. The webservice i needed to
call excepts plain test.*/
t_request_body := 'the data you want to send to the webservice';
/*Telling Oracle where the webservice can be found, what kind of request is made
and the version of the HTTP*/
t_http_req:= utl_http.begin_request( 'http://urlofwebservice'
, 'GET'
, 'HTTP/1.1');
/*In my case the webservice used authentication with a username an password
that was provided to me. You can skip this line if it's a public webservice.*/
utl_http.set_authentication(t_http_req,'username','password');
/*Describe in the request-header what kind of data is send*/
utl_http.set_header(t_http_req, 'Content-Type', 'text/xml charset=UTF-8');
/*Describe in the request-header the lengt of the data*/
utl_http.set_header(t_http_req, 'Content-Length', length(t_request_body));
/*Put the data in de body of the request*/
utl_http.write_text(t_http_req, t_request_body);
/*make the actual request to the webservice en catch the responce in a
variable*/
t_http_resp:= utl_http.get_response(t_http_req);
/*Read the body of the response, so you can find out if the information was
received ok by the webservice.
Go to the documentation of the webservice for what kind of responce you
should expect. In my case it was:
<responce>
<status>ok</status>
</responce>
*/
utl_http.read_text(t_http_resp, t_respond);
dbms_output.put_line(t_respond);
/*Some closing?1 Releasing some memory, i think....*/
utl_http.end_response(t_http_resp);
end;
You might want to look into the UTL_HTTP package

Consuming SOAP web services with cookie-based authentication from Oracle stored procedure with PL/SQL

We are trying to consume a secure (https) web service with PL/SQL directly from Oracle DB stored procedures. There is a seperate web service for user actions (login/logout) and its documentation states
Upon successful login a session cookie is created. Web service client must be configured to receive cookies. After logging in subsequent calls will succeed as long as they include the session cookie which is received by login.
However we do not know how to store and use that cookie from PL/SQL. Any help will be appriciated..
NOTES:
We have successfuly created the Oracle Wallet, add the web servies' certificates to the wallet and assigned it to the request as follows:
Declare
...
v_req_context UTL_HTTP.REQUEST_CONTEXT_KEY;
...
Begin
...
v_req_context := UTL_HTTP.CREATE_REQUEST_CONTEXT(wallet_path => 'file:'||ssl_cert_wallet_path,
wallet_password => ssl_cert_wallet_password);
v_http_request := UTL_HTTP.BEGIN_REQUEST(url => 'https://<url_to_webservice_wsdl>',
method => 'POST',
http_version => 'HTTP/1.1',
request_context => v_req_context);
...
End;
We are making a request to the user service as follows:
Begin
-- SOAP Authentication request parameters
v_string_request := '<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:examples:userService">
<soapenv:Header/>
<soapenv:Body>
<urn:' || v_service_operation || ' soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:urn="' || v_service_namespace || '/">
<userId>' || p_username || '</userId>
<password>' || p_password || '</password>
<lang>' || p_lang || '</lang>
</urn:' || v_service_operation || '>
</soapenv:Body>
</soapenv:Envelope>';
UTL_HTTP.SET_TRANSFER_TIMEOUT(60);
v_http_request := UTL_HTTP.BEGIN_REQUEST(url => v_host_name || ':' || v_port || v_service_posfix,
method => 'POST',
http_version => 'HTTP/1.1',
request_context => v_req_context);
UTL_HTTP.SET_HEADER(v_http_request, 'Host', v_host_name || ':' || v_port);
UTL_HTTP.SET_HEADER(v_http_request, 'Connection', 'close');
UTL_HTTP.SET_HEADER(v_http_request, 'Content-Type', 'text/xml;charset=UTF-8');
UTL_HTTP.SET_HEADER(v_http_request, 'SOAPAction', '"' || v_service_operation || '"');
UTL_HTTP.SET_HEADER(v_http_request, 'Content-Length', length(v_string_request));
<<login_request_loop>>
for i in 0..CEIL(LENGTH(v_string_request) / v_buffer_size) - 1
loop
v_substring_msg := SUBSTR(v_string_request, i * v_buffer_size + 1, v_buffer_size);
begin
v_raw_data := UTL_RAW.CAST_TO_RAW(c => v_substring_msg);
UTL_HTTP.WRITE_RAW(r => v_http_request, data => v_raw_data);
exception
when NO_DATA_FOUND then EXIT login_request_loop;
end;
end loop login_request_loop;
-- SOAP Authentication request
v_http_response := UTL_HTTP.GET_RESPONSE(v_http_request);
...
End;
Let me drop the answer for future use:
If the web service you are trying to consume is a secure (https) web service, then do not set the Host seperately in header.
The code works like charm if you remove the line:
UTL_HTTP.SET_HEADER(v_http_request, 'Host', v_host_name || ':' || v_port);
PS: I have discovered that all by myself, so I could not refer to any sources.

Are BING geocoding & Google geocoding a web-service, or web-api?

I want to pull just the latitude and longitude (for some addresses in oracle table) from BING or Google. I want to do this from stored procedure. I tried to do this using the UTL_DBWS package, but I am not able to form a complete call as I am missing details like 'operation', 'input parameter request format' etc. I couldn't find wsdl file for both the geocoding services. So are these services actually a web-api or web-service? What is the best way to call these services from oracle stored-proc?
You can check this example which uses utl_http to get a good idea on how you can do it
Couple of things you need to take care
1)You need direct internet connection from database server
2)You need to edit your database ACL policy for this to work
3)You need to escape "&" symbol in the URL you use for searching
4)You need to validate the SSL certificate using Oracle wallet
The ACL Example
BEGIN
--You need DBA to execute this function where www.xml is the ACL Name
--SCOTT is the schemaname,my.oracle.com is the host to access the webpage
DBMS_NETWORK_ACL_ADMIN.CREATE_ACL(acl => 'www.xml',
description => 'WWW ACL',
principal => 'SCOTT',
is_grant => true,
privilege => 'connect');
DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE(acl => 'www.xml',
principal => 'SCOTT',
is_grant => true,
privilege => 'resolve');
DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL(acl => 'www.xml',
host => 'my.oracle.com');
END;
/
COMMIT;
you can add additional Host names for accessing the internet to the ACL www.xml like the below
BEGIN
DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL(acl => 'www.xml',
host => 'www.google.co.in');
END;
/
COMMIT;
here is an example of latitude and longitude search using google
declare
httpuri HttpUriType;
x clob;
address VARCHAR2(32000):='New York';
lat_long_value VARCHAR2(4000);
begin
UTL_HTTP.set_transfer_timeout(60); --set timeout to 60 seconds
httpuri := HttpUriType('http://www.google.co.in/search?q=find+latitude+and+longitude+of+' ||address||'&'||'ie=utf-'||'8&'||'oe=utf-'||'8&'||'aq=t'||'&'||'rls=org.mozilla'||':'||'en-US'||':'||'official'||'&'||'client=firefox-a');
x := httpuri.getclob();
lat_long_value := regexp_substr(x, '<div class="_Xj">(.+)</div>');
if lat_long_value is not null then
select regexp_replace(lat_long_value,
'<div class="_Xj">(.+)</div>',
'\1')
into lat_long_value
FROM dual;
end if;
dbms_output.put_line(lat_long_value);
end;
If you get the error that
Ora-29024 Certification validation failure
Kindly follow the steps required to add the google certificate to Oracle wallet here
Finally you get the output is
40.7127° N, 74.0059° W

Resources