Improve PL/SQL HTTP Verb Support

The PL/SQL, mod_plsql web stack offers HEAD, GET, and POST out of the box. But let's face it, these three verbs aren't enough to work with. Is it possible to perform standard CRUD ops and write a rich web application with just GET and POST? Yes, but doing so does not capitalize on the tools available to you through standard HTTP, nor is it particularly amenable to application end-point organization.

Without needing to re-configure mod_plsql you can game the system. Consider the following PL/SQL package:

CREATE OR REPLACE PACKAGE PLSQL_DEMO AS
	PROCEDURE print_verb (verb in varchar2 default 'POST');
END PLSQL_DEMO;
/

CREATE OR REPLACE PACKAGE BODY PLSQL_DEMO AS
	PROCEDURE print_verb (verb in varchar2 default 'POST') IS
		v_request_verb varchar2(10) := owa_util.get_cgi_env('REQUEST_METHOD');
	BEGIN
		if (v_request_verb = 'POST') then
			v_request_verb := upper(verb);
		end if;

		htp.p(v_request_verb);
	END print_verb;
END PLSQL_DEMO;
/

Let's gather the instructive features of this example:

Interacting with this functionality is simple. We could implement a simple HTML form with a hidden input declaring verb as PUT (or whatever else).

<form action="plsql_demo.print_verb" method="POST">;
   <input type="hidden" name="verb" value="PUT" />;
</form>

Great, but how do you programmatically interact with this functionality without having to mess about with pre-existing coded HTML? That's mostly up to you, but I'll share how I'd handle a PUT form.

###Interacting with the Request Handler

Adding the aforementioned hidden inputs blurs the separation of layers that is prudent in web application development. If your web stack were to ever change and you needed to reuse your markup templates, you might be stuck with redundant and sloppy idioms. So, we'll slightly modify the example HTML form to make it more semantic and offload dealing with gateway shortcomings to the script layer.

<form action="plsql_demo.print_verb" method="PUT">
	<!-- Insert form fields here. -->
</form>

You can then include the following script to intercept native form submissions and inject the appropriate parameters:

$(document).ready(function() {
	$(document).on('submit', 'form', function(e) {
		var method, $verb, $this = $(this);

		// Grab the form's method.
		method = $this.attr('method');

		// Is the method a GET or a POST?
		// If so, don't bother taking any action.
		if (!/^(GET|POST)$/i.test(method)) {
			// Grab the input named "verb" from the form.
			$verb = $this.find('input[name="verb"]')

			// If the input doesn't already exist then insert it.
			if ($verb.length === 0) {
				$this.append('&lt;input type="hidden" name="verb" /&gt;');
			}

			// Set the value of the verb input.
			$verb.val(method);
			// Set the form submission action to POST.
			// This will help with old browser compatibility issues.
			$this.attr('method', 'POST');
		}
	});
});

Note that the entire code snippet is included in a $(document).ready() method call. This is standard practice as it creates a scope for the page specific code and ensures that the DOM is initialized before any script code is executed. If you already have a $(document).ready(), you can add the .on() call inside of it if you'd prefer.

If there's a mission-critical input already named "verb" in any form, the name of this input should be changed in the PL/SQL and JavaScript code. This would prevent your actual "verb" input from being subtly replaced by our programmatic "verb" value. Any valid PL/SQL variable name works fine.

This example doesn't cover AJAX verb adjustment, but the same principles apply. The request should be modified with a spoofed verb parameter and then sent to the server just like any other AJAX request. The additional verb can either be appended to the query string in the post URL or included in the jQuery data object argument.