REST Handler
ColdBox supports native REST handling via the RestHandler and native routing.
Last updated
ColdBox supports native REST handling via the RestHandler and native routing.
Last updated
ColdBox 6 has native REST capabilities alongside the RestHandler
and a customizable Response
object into the core. This RestHandler
will provide you with utilities and approaches to make all of your RESTFul services:
Uniformity on Responses
A consistent and extensible response object
Consistent Error handling
Invalid route handling
Internal Events
Much more
In previous versions of ColdBox support for RESTful services was provided by adding the base handler and the response object to our application templates. Integration into the core brings ease of use, faster handling and above all: a uniform approach for each ColdBox version in the future.
For the creation of REST handlers you can inherit from our base class coldbox.system.RestHandler
, directly via extends="coldbox.system.Resthandler"
or by using the restHandler
annotation.
This will give you access to our enhanced API of utilities and the native response object via the event object getResponse()
method.
You will then leverage that response object (https://apidocs.ortussolutions.com/coldbox/current/index.html?coldbox/system/web/context/Response.html) to do the following actions:
Set the data to be converted to JSON, XML or whatever
Set pagination data
Set errors
Set if the data is binary or not
Set location
headers
Set message arrays
Set json
call backs
Set json
query formats
Set response contentType
Set response statusCode
Set response headers
Much More
Upgrade Pointers: The response object will be accessible using the event.getResponse()
method but will still be available as prc.response.
If you are using cbORM
make sure to check the chapter Automatic Rest Crud
The Rest handler gives you the following actions coded for you out of the box. You can override them if you want, but the idea is that this base takes you a very long way.
Core Actions
Purpose
aroundHandler()
Wraps all rest actions uniformly to provide consistency and error trapping.
onError()
An implicit error handler is provided just in case anything explodes in your restful actions. Sends an appropriate 500 error
onValidationException()
Traps any and makes sure it sends the appropriate 400 response with the invalid data. Useful for using cbValidation, for example with the validateOrFail()
methods.
onEntityNotFoundException()
Traps any or exceptions and makes sure it send an appropriate 404 response. Useful for leveraging cborm or Quick ORM
onInvalidHTTPMethod()
Traps any invalid HTTP method security exception and sends the appropriate 405 not allowed response
onMissingAction()
Traps any invalid actions/resource called in your application and sends the appropriate 404 response
onAuthenticationFailure()
Traps InvalidCredentials
exceptions and sends the appropriate 403 invalid credentials response. If you are using cbSecurity it will also verify jwt token expiration and change the error messages accordingly.
onAuthorizationFailure()
Traps PermissionDenied
exceptions and sends the appropriate 401 response. This Action can be used when a user does not have authorization or access to your application or code. Usually you will call this manually or from a security library like cbSecurity or cbGuard. It will send a 401 not authorized response.
onInvalidRoute()
Action that can be used as a catch all from your router so it can catch all routes that are invalid. It will send a 404 response accordingly.
onExpectationFailed()
Utility method for when an expectation of the request fails ( e.g. an expected parameter is not provided ). This action is called manually from your own handlers and it will output a 417 response back to the user.
onAnyOtherException
Fires when ANY exception that is not excplicitly trapped is detected. This basically logs the issue and offers a 500 error. You can now intercept it and do whatever you need on ANY type of untrapped exception.
The aroundHandler
() provided in the RestHandler
will intercept all rest calls in order to provide consistency and uniformity to all your actions. It will try/catch for major known exceptions, time your requests, add extra output on development and much more. Here are a list of the features available to you:
Automatic trapping of the following exceptions:
EntityNotFound
InvalidCredentials
PermissionDenied
RecordNotFound
TokenInvalidException
ValidationException
If the trapped exception is not one from above, then we will call the onAnyOtherException()
action. This action will log automatically the exception with extra restful metadata according to the environment you are executing the action with. It will also setup an exception response for you.
If in a development
environment it will respond with much more information necessary for debugging both in the response object and headers
If you are in a development
environment it will set the following headers for you in the response object automatically.
x-current-event
x-current-route
x-current-routed-url
x-current-routed-namespace
The following headers are sent in each request no matter the environment:
x-response-time
: The time the request took in CF
x-cached-response
: If the request is cached via event caching
The aroundHandler()
is also smart in detecting the following outputs from a handler, which will ignore the REST response object:
Handler return
results
Setting a view or layout to render
Explicit renderData()
calls
The RestHandler
also gives you HTTP method security out of the box by convention based on ColdBox resources. The following is already created for you using the this.allowedMethods
structure:
Also note that since this is a base class, you can override this structure or append to it as you see fit.
The Response
object is used by the developer to set into it what the response will be by the API call. The object is located at coldbox.system.web.context.Response
and can be retrieved by the request context object's getResponse()
method.
Every response is created from the internal properties in the following JSON representation:
You can change this response by extending the response object and doing whatever you want.
The Response
object has the following properties you can use via their getter and setter methods.
binary
boolean
false
If the data
property is binary
contentType
string
---
Custom content type of the response
data
struct
---
The data struct marshalled in the response
error
boolean
false
Boolean bit denoting an exception or problem in the API call
format
string
json
The response format of the API. Defaults to json
.
jsonCallback
string
---
If using a callback then set the callback method here.
jsonQueryFormat
string
true
This parameter can be a Boolean value that specifies how to serialize ColdFusion queries or a string with possible values row, column, or struct
location
string
---
The location header to send with the response
messages
array
---
Array of messages to send in the response packet
pagination
struct
{
offset,
maxRows,
page,
totalRecords,
totalPages
}
A pagination struct to return
responseTime
numeric
0
The time the request and response took
statusCode
numeric
200
The status code to send
statusText
string
OK
The status text to send
A part from the setters/getters from the properties above, the response object has some cool convenience methods:
The response object also has as STATUS_TEXTS
public struct exposed so you can use it for easy status text lookups:
If you would like to extend or modify the behavior of the core RestHandler
then you will have to create your own base handler that inherits from it. Then all of your concrete handlers will inherit from your very own handler.
The response object can be found here: coldbox.system.web.context.Response
and the rest handler constructs it by calling the request context’s getResponse
() method. The method verifies if there is a prc.response
object and if it exists it returns it, else it creates a new one. So if you would like to use your very own, then just make sure that before the request you place your own response object in the prc
scope.
Here is a simple example using a preProcess()
interceptor. Create a simple interceptor with commandbox e.g
and add the following method:
Don't forget to register your interceptor in config/Coldbox.cfc:
That’s it. Once that response object is in the prc
scope, ColdBox will utilize it. Just make sure that your custom Response object satisfies the methods in the core one. If you want to modify the output of the response object a good place to do that would be in the getDataPacket()
method of your own MyResponseObject
. Just make sure this method will return a struct
.