14.7.5 Reusing Common REST API Handler Code
Reuse common REST handler code to send JSON responses, errors, and optional debug details.
Every PL/SQL handler performs the following set of steps:
- If necessary:
- processes incoming request by referencing bind variables
- prepares response to return to the client
- Then always:
- Sets the MIME Type of the response, and any other response headers
- Sets the status code if the default 200 status is not appropriate
- Closes the header
- Writes the response to the output buffer using
HTP.PorHTP.PRN
To simplify handler implementation, consider using a package like
APP_COMMON_REST below that provides procedures for:
commit_and_send_response– committing the transaction and writing out the responsehandle_error– rolling back the transaction, signalling an error, and returning error detailsset_debug– to enable including additional debug info useful to developers.
package app_common_rest as
--------------------------------------------------------------
-- Set debug mode for error reporting
--------------------------------------------------------------
procedure set_debug(
p_value in varchar2);
--------------------------------------------------------------
-- Commit and write out JSON response
--------------------------------------------------------------
procedure commit_and_send_response(
p_json json_element_t default null);
--------------------------------------------------------------
-- Handle error by sending HTTP error with $error payload
--------------------------------------------------------------
procedure handle_error(
p_error_message in varchar2,
p_http_error_code in number default 400);
end app_common_rest;The package body follows for you to study. Notice it uses:
owa_util.mime_header– to set standardContent-TypeMIME type headerowa_util.status_line– to set a non-default HTTP response status codehtp.p– to write out the response body as serialized JSON text.
If the g_debug_mode flag is enable by a call to set_debug, then notice also that the handle_error adds an additional debug$error property whose value is a JSON array containing the lines of the PL/SQL call stack info from format_error_stack and format_error_backtrace in the dbms_utility package.
create or replace package body app_common_rest as
g_debug_mode boolean := false;
------------------------------------
procedure set_debug(
p_value in varchar2)
is
begin
if upper(p_value) = 'TRUE' then
g_debug_mode := true;
end if;
end set_debug;
------------------------------------
procedure commit_and_send_response(
p_json in json_element_t default null)
is
l_has_json boolean := p_json is not null;
begin
commit;
owa_util.mime_header('application/json', l_has_json);
if p_json is not null then
htp.p(p_json.stringify);
else
owa_util.status_line(204, 'No content', true);
end if;
end;
--------------------------------------------------------------
-- Handle error by sending HTTP 400 with $error payload
--------------------------------------------------------------
procedure handle_error(
p_error_message in varchar2,
p_http_error_code in number default 400)
is
l_json_err json_object_t := json_object_t();
l_json_arr json_array_t;
begin
owa_util.mime_header('application/json', p_error_message is null);
owa_util.status_line(p_http_error_code, 'Error', true);
if p_error_message is not null then
l_json_err.put('$error',
regexp_replace(p_error_message,'^ORA-[0-9]+:\s'));
if g_debug_mode then
l_json_arr := json_array_t();
for j in (select rownum, column_value
from table(apex_string.split(
dbms_utility.format_error_stack()
|| chr(10)
|| dbms_utility.format_error_backtrace())))
loop
if j.column_value is not null then
l_json_arr.append(j.column_value);
end if;
end loop;
l_json_err.put('debug$error', l_json_arr);
end if;
htp.p(l_json_err.stringify);
end if;
rollback;
end;
end app_common_rest;Parent topic: Controlling REST API Behavior Completely