VALIDATE me baby
There are many times that I have been writing sites with the desire for the client side to call the server in a safe and idempotent way with a request body for sending more data than a GET
can, or data that can't be recorded via referral logs.
Even when or if the new Form HTTP extensions specification gets approval and adoption for the basic HTTP methods, we still lack a clear way to send over requests with server side impact.
Proposal
This proposal is for browsers and servers to support a new HTTP verb VALIDATE
and adding a new HTML form parameter methodfor
so that browsers can safely send validation requests to the server.
The problem
All HTTP requests besides GET
and HEAD
are specified to have side effects on the server. Which means that behind the scenes of my client side applications, I can only safely send over GET
requests to request for updates on the validation of messages.
So for example if I wanted to server side validate a credit card form I would have to send over:
https://mysite.com/checkout/pay?creditcard=4111111111111111&fname=jonathan…
Although technically, this will be a secure request at the network layer, it could be cached and/or logged at the web server.
Advantages
The VALIDATE
verb has two clear advantages: clear semantic reasoning and automatic validation with safe client side methods.
Semantic reasoning
It gives the client and server the ability to know when a request is just a validation, and enables both sides to provide a better overall experience to the user.
User agents can indicate to the user when the form will be just a validation and will be technologically safe for them to send, potentially by giving a different appearance or accent to buttons. By doing so, users will have more confidence in trying out changes, for example payment buttons in a checkout flow.
Example:
A dynamic page could easily serve up the following form:
<form method="VALIDATE" methodfor="POST" > <fieldset> <legend>Purchase item</legend> <div class="form-row"> <label for="my-item">Item</label> <input name="item-sku" placeholder="Input SKU code" id="my-item" /> </div> <button>Submit</button> </fieldset> </form>
Once the user submits the form, the dynamic page could then come back with validation issues:
<form method="VALIDATE" methodfor="POST" > <fieldset> <legend>Purchase item</legend> <div class="form-row"> <label for="my-item">Item</label> <input name="item-sku" value="thing" placeholder="Input SKU code" id="my-item" /> <div class="inline-error">Sorry our SKU codes are numeric, you might find these in our catalog EG: SKU #121212;</div> </div> <button>Submit</button> </fieldset> </form>
Once validation issues are resolved then the following would display:
<form method="POST" > <fieldset> <legend>Confirm purchase of item 1212</legend> <div class="form-row"> <label for="my-item">Item</label> <input name="item-sku" value="1212" id="my-item" readonly /> </div> <!-- This goes out to all you "law abiding citizens" out there --> <button>Order with obligation to pay</button> </fieldset> </form>
Automatic validation
With VALIDATE
forms the JavaScript could automatically send over requests for updates and new error validations via AJAX and safely know that the user will not be impacted by side effects.
Having the ability for the JavaScript to safely make requests to the server means this feature could be turned on globally; even if the client library doesn't understand the response, the error code could be used to indicate to the user of when the form is valid or not.
Example:
Client sends:
VALIDATE /checkout/pay HTTP/1.0 Method-For: POST Content-Type: application/javascript; charset=UTF-8 Content-Length: 32 {creditcard: '4111111111111111', fname: 'jonathan'…}
Server response:
HTTP/1.0 412 Precondition Failed Date: Fri, 31 Jun 2014 23:59:59 GMT Content-Type: text/json Content-Length: 121212 {status: 'additional-information', form: [{type: 'string', name: 'creditcard'}, {status: 'new-additional', type: 'string', name: 'cv2'}, {type: 'string', name: 'fname'}...]}
When precondition failed returns, it would be able to return validation issues per field, errors for the whole form and additional fields that are required.
Wait though, what is wrong with POST? Natively the server doesn’t expose an interface for sending body data over in a request, which means that swapping from one system to another could have side effects on the users data.
So for example lets take a site with different validate systems:
- Your payment gateway implements the parameter:
?test=1
- Your order process uses http headers:
X-Validate-Request: 1
- Your blogging platform uses the parameter:
?verify-request='yes'
Client side applications can’t quickly share the same code without further adapters to each message; POSTing the data raw couldn’t be used safely as it might actually run the request that you are trying to check without the intention of the user to do so.
However, if both the payment gateway and order process implemented VALIDATE as a verb, the JavaScript and/or browser could automatically verify forms as and when it sees fit. Additionally, the blog could have the VALIDATE functionality turned off, and the server would be used in the traditional round trip manner, passing back more field when it knows the client needs them. This has the added bonus of working even with VALIDATE not being supported, so in the rare case of it being fired it would be completely safe to do so.
Methodfor reasoning
If you have read this far, it is likely you are as pedantic as I am, and you are likely to be asking ‘Ok, but how does the server know the corresponding verb’ as different verbs will require different validation.
Well I propose two things, a new HTML attribute to cater for the following verb and also a new HTTP header for the same purpose.
<form method="VALIDATE" methodfor="DELETE" action="/checkout/pay" >
Which in turn would send:
VALIDATE /checkout/pay HTTP/1.1 Method-For: DELETE …
Where the server would respond:
HTTP/1.1 412 Precondition Failed Date: Fri, 31 Jun 2014 22:21:59 GMT Content-Type: text/json Vary: Method, Method-For
This means that:
- We don't end up with
VALIDATE-DELETE
,VALIDATE-PUT
,VALIDATE-POST
,VALIDATE-HEAD
,VALIDATE-NEW-SHINY
methods - Until full adoption by browsers server side support can retrofit functionality.
- Older user agents can easily not worry about what the new verbs and parameters so long as the server assumes no support if no
Method-For
header is not sent - Server should treat request as a normal
POST
interaction with no side effects - Server can then send back the corresponding approval / validation issues mentioned above
- Older user agents can easily not worry about what the new verbs and parameters so long as the server assumes no support if no
- User agents on sites with
VALIDATE
support can automatically send the requests safely - Forms could display differently based upon the
methodfor
andmethod=”VALIDATE”
Further discussions into integration
Method discovery
Frameworks and user agents would also be able to quickly resolve if the form could support the method by running an OPTIONS request which could likely be cached for a significant amount of time.
Messaging
Deciding upon a standard for negotiation between the client and server for how validation responses would be formed is key for JavaScript to really pick up and get use out of the VALIDATE verb.
Specifications like JSON API could be adapted and expanded to provide the same kind of validations as specified here: JSON API review or serialised versions of Robin Berjon's Web Schema.