6. checkAccess()
ā¢ Default implementation in ERXRouteController does nothing
ā¢ Override it in your controller for security check
7. performHtmlActionNamed
ā¢ Does <EntityName><ActionName>Page component exists?
ā¢ No: fall back to controller
ā¢ Yes: Check if component implements IEXRouteComponent
ā¢ Yes: return the component
ā¢ No: fall back to controller
8. shouldFailOnMissingHtmlPage
ā¢ Does the component was not found or don't implement
IEXRouteComponent?
ā¢ If shouldFailOnMissingHtmlPage() returns true, call
performUnknownAction (will return a 404 NotFound)
ā¢ Default is false, override it in your controller if needed.
9. performRouteActionNamed
ā¢ Try to ļ¬nd <actionName>Action method.
ā¢ Not found? Try to ļ¬nd <actionName> method.
ā¢ Still nothing? Check for annotations.
ā¢ Still nothing? Call performUnknownAction
ā¢ Got something? Call performActionWithArguments
14. routeObjectForKey
ā¢ {<keyName>:<keyType>} in route = keyType result =
routeObjectForKey(<keyName>)
ā¢ Object is obtained by ERXRestUtils.coerceValueToTypeNamed
15. coerceValueToTypeNamed
ā¢ Where value is transformed to a object or primitive
ā¢ If it's an EO or POJO, will use
ERXRestClassDescriptionFactory.classDescriptionForEntityName to ļ¬nd the
class
ā¢ Will call
IERXRestDelegate.Factory.delegateForClassDescription().objectOfEntityWithI
D()
16. create(ļ¬lter)
ā¢ Will call ERXRestClassDescriptionFactory.classDescriptionForEntityName
ā¢ Will call
IERXRestDelegate.Factory.delegateForClassDescription().createObjectOfEnti
tyWithID to create a basic EO/POJO
ā¢ Will call updateObjectWithFilter()
18. updateObjectWithFilter
ā¢ Major method
ā¢ Will take content from request and update object (PUT request)
ā¢ Also used to populate new object (POST request)
20. response(object, ļ¬lter)
ā¢ Will built up the object graph with
ERXRestRequestNode.requestNodeWithObjectAndFilter
ā¢ Will call response(format, responseNode)
22. _ļ¬llInWithObjectAndFilter
ā¢ If object is an array, method take itself
ā¢ If not array, will use object's delegate to call primaryKeyForObject, and
call _addAttributesAndRelationshipsForObjectOfEntity
23. response(format, responseNode)
ā¢ Returns result of ERXRouteResults(context, restContext, format,
responseNode)
ā¢ ERXRouteResults.generateResponse() will actually generate the response
in requested format
24. response(ERXRestFetchSpeciļ¬cation,
ļ¬lter)
ā¢ Useful to return list of objects ("index" action)
ā¢ ERXRestFetchSpeciļ¬cation allow you to set ordering, range, ļ¬ltering and
batching from request
ā¢ Will also call response(format, responseNode)
25. response(int)
ā¢ Use that one to send a response without any content in the body
ā¢ Check ERXHttpStatusCodes
27. "id" key
ā¢ ERXRest.idKey : what to use instead of "id"
Default: {"id":2 }
ERRest.idKey=primaryKey {"primaryKey":2 }
28. "nil" key
ā¢ ERXRest.nilKey
To rewrite the "nil" attribute
Default: <someAttribute nil="true"/>
ERXRest.nilKey=cestVide -> <someAttribute cestVide="true"/>
ā¢ ERXRest.writeNilKey
Skip the "nil" attribute
Default: <someAttribute nil="true"/>
ERXRest.writeNilKey=false -> <someAttribute nil="true"/>
29. "type" key
ā¢ ERXRest.typeKey
Allow you to change the name of the "type" attribute
Default: {"type":"NameOfEntity"}
ERXRest.typeKey=entityName {"entityName":"NameOfEntity"}
ā¢ ERXRest.writeTypeKey
If false, won't write the "type" attribute in the response
ERXRest.writeTypeKey=false -> {id: 2, "type":"NameOfEntity"}
30. ERXRest.pluralEntityNames
ā¢ Default is true
ā¢ If set to false, can't use pluralized names
Default: /ra/restEntities
Set to false: /ra/restEntities
31. ERXRest.suppressTypeAttributesForSimpl
eTypes
ā¢ Only for XML format
ā¢ Default value is false
ā¢ Default rendering:
<RestEntity primaryKey="1">
<someAttribute type = "integer">2</someAttribute>
</RestEntity>
ā¢ When set to false:
<RestEntity primaryKey="1">
<someAttribute type = "integer">2</someAttribute>
32. ERXRest.strictMode
ā¢ Default is: true
ā¢ For missing route, will send 405 (Not Allowed) code, if set to false,
will send 404 (Not Found)
ā¢ POST requests: will send 201 (Created), if false will send 200 (OK)
34. ERXRest.parseUnknownExtensions
ā¢ /ra/restEntities/3.fsdfsd
ā¢ If set to true (the default):
HTTP/1.1 200 Apple WebObjects
Content-Type: text/html
ā¢ If set to false:
HTTP/1.0 400 Apple WebObjects
36. ERXRest.defaultFormat
ā¢ ERXRest.defaultFormat=json|xml|plist|html|...
ā¢ Let you specify the default format for all controllers
ā¢ Can override it per controller:
protected ERXRestFormat defaultFormat() {
return ERXRestFormat.json();
}
37. Format detection
ā¢ Format detection is in ERXRouteController.format()
ā¢ Order of detection
ā¢ From extension (.json). Set in
ERXRouteRequestHandler.routeForMethodAndPath()
ā¢ From the Content-Type header
ā¢ Default format (defaultFormat() in controller)
38. Adding new format
ā¢ Your own private format? Use
ERXRestFormat.registerFormatNamed()
ā¢ Format useful for the commumity? Add them to ERXRestFormat
40. Same Origin Policy
ā¢ Problem: browsers won't load data if client and server not on same
domain
ā¢ Numerous ways: window.name transport, JSONP and Cross-origin
resource sharing (CORS)
ā¢ CORS and window.name transport support is part of ERRest
41. CORS
ā¢ Works with Gecko 1.9.1 (Firefox 3.5+), WebKit (Safari 4+, Google
Chrome 3+), Opera 12 and IE 8+
ā¢ Send extra headers to server
ā¢ Client speciļ¬y origin, requested HTTP verb and allowed headers,
server returns allowed origin, methods, headers and max-age
42. CORS preļ¬ight
Client request:
OPTIONS /resources/post-here/ HTTP/1.1
Origin: http://foo.example
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER
Server response:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER
Access-Control-Max-Age: 1728000
Client request:
GET /resources/post-here/ HTTP/1.1
Origin: http://foo.example
Server response:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://foo.example
43. CORS
ā¢ ERXRest.accessControlAllowRequestHeaders
ā¢ ERXRest.accessControlAllowRequestMethods
ā¢ ERXRest.accessControlMaxAge (default: 1728000)
ā¢ ERXRest.accessControlAllowOrigin ('*' to allow all)
44. window.name Transport
ā¢ Dojo use that trick
ā¢ Client send ?windowname=true in URL
ā¢ Enable it on server with:
ERXRest.allowWindowNameCrossDomainTransport=true
ā¢ Will wrap response in HTML code:
<html><script type="text/javascript">window.name='{"id":
4,"type":"RestEntity","someAttribute":"commit transaction"}';</script></html>
46. Status code and exceptions
ā¢ ObjectNotAvailableException, FileNotFoundException,
NoSuchElementException: returns a 404 (Not Found)
ā¢ SecurityException: returns a 403 (Forbidden)
ā¢ ERXNotAllowedException: returns a 405 (Method Not Allowed)
ā¢ ERXValidationException, NSValidation.ValidationException: returns a 400 (Bad
Request)
ā¢ Anything else: returns a 500 (Internal Server Error)
ā¢ Avoid sending 5xx codes if the client made a mistake!
47. Adding support for new data types
ā¢ Add a processor in _ERXJSONConļ¬g
ā¢ Add support code in ERXRestUtils
ā¢ isPrimitive()
ā¢ coerceValueToString()
ā¢ coerceValueToTypeNamed
ā¢ For dates: add formatter in ERXRestUtils