package er.rest.routes; import com.webobjects.appserver.WOActionResults; import com.webobjects.appserver.WOApplication; import com.webobjects.appserver.WOContext; import com.webobjects.appserver.WOResponse; import com.webobjects.appserver.WOSession; import com.webobjects.foundation.NSMutableDictionary; import er.extensions.appserver.ERXHttpStatusCodes; import er.extensions.foundation.ERXProperties; import er.rest.ERXRestContext; import er.rest.ERXRestRequestNode; import er.rest.format.ERXRestFormat; import er.rest.format.ERXWORestResponse; import er.rest.format.IERXRestWriter; /** * ERXRouteResults encapsulates the data necessary to produce a RESTful response. This object exists to defer the * generation of the response (so you can chain together rest responders). * * @property ERXRest.strictMode (default "true") If set to true, creating a ressource will return status code 201 Created, if set to false, will return 200 OK * * @author mschrag */ public class ERXRouteResults implements WOActionResults { private WOContext _context; private ERXRestContext _restContext; private ERXRestFormat _format; private ERXRestRequestNode _responseNode; private NSMutableDictionary<String, String> _headers; /** * Constructs an ERXRouteResults. * * @param context * the current context * @param restContext * the REST context * @param format * the intended format of this response * @param responseNode * the ERXRestRequestNode to render */ public ERXRouteResults(WOContext context, ERXRestContext restContext, ERXRestFormat format, ERXRestRequestNode responseNode) { _context = context; _restContext = restContext; _format = format; _responseNode = responseNode; _headers = new NSMutableDictionary<>(); } /** * Adds a header for the resulting WOResponse. * * @param header the header to add * @param key the key to add */ public void setHeaderForKey(String header, String key) { _headers.setObjectForKey(header, key); } /** * Returns the intended format of this response. * * @return the intended format of this response */ public ERXRestFormat format() { return _format; } /** * Returns the ERXRestRequestNode to render. * * @return the ERXRestRequestNode to render */ public ERXRestRequestNode responseNode() { return _responseNode; } /** * Generates a WOResponse out of this ERXRouteResults. * * @return a generated WOResponse */ @Override public WOResponse generateResponse() { boolean isStrictMode = ERXProperties.booleanForKeyWithDefault("ERXRest.strictMode", true); WOResponse response = WOApplication.application().createResponseInContext(_context); IERXRestWriter writer = _format.writer(); if (writer == null) { throw new IllegalStateException("There is no writer for the format '" + _format.name() + "'."); } writer.appendToResponse(_responseNode, new ERXWORestResponse(response), _format.delegate(), _restContext); if (_headers.count() > 0) { for (String key : _headers.keySet()) { response.setHeader(_headers.objectForKey(key), key); } } if (("POST".equals(_context.request().method())) && (isStrictMode)) { response.setStatus(ERXHttpStatusCodes.CREATED); } // PR: ERXRouteResults is not extending from WOResponse, so this code can't be in ERXRouteController.processActionResults WOSession session = _context._session(); if (session != null && session.storesIDsInCookies()) { session._appendCookieToResponse(response); } return response; } }