📜 ⬆️ ⬇️

Using RESTful Controllers for AngularJS Resources

As mentioned earlier, Angulyar provides the $ resource class to increase the level of abstraction between client-side code and the server API . Therefore, it is now quite easy to perform CRUD operations over the network. But what happens when you need to execute a command for a RESTful resource that goes beyond the standard CRUD methods (i.e. create, read, update, delete)? Fortunately, Angulyar works quite well with RESTful "controllers".

In accordance with the Mark Masse REST Code , there are four resource archetypes:


Document, Collection and Storage represent resources. Controllers, on the other hand, are responsible for changing resources. You can use verbs in HTTP to indicate action on a resource, but for mediocre CRUD operations this does not always make sense. Take the following resources as an example:
')

Having a message collection (the first resource) and a separate message (the second resource), how to report on the clearing of all messages? Or how to move this message to the archive? CRUD does not quite meet these requirements. But controllers are great for operations of this type:


Here we use the “clear-all” and “archive” Controllers to modify the Collection and Archiving of the Document, respectively.

Starting to use controllers for our resources, we came to the URL scheme, which has great variability. Angular's $ resource allows you to do this, but you'll have to use a few “smart” features to customize the data binding.

Based on the above concept of working with messages, in the context of Angular we would have to define our resource using the following template:


The problem is that, currently, there is some ambiguity around the first URL parameter. Is the ": id" reference to the Collection-based Controller? Or is this a Document ID link?

To eliminate this uncertainty, Angulyar allows you to define several parameters in the same part of the template URL:


Note that the second part of the URL pattern contains two parameters:


So far I use only one of them, while Angulyar will build a RESTful resource properly. To demonstrate this, I wrote a demo in which the message resource is defined and then used as shown above:

<!doctype html> <html ng-app="Demo"> <head> <meta charset="utf-8" /> <title>  RESTful    AngularJS</title> <!-- . .   ,     AngularJS  ngResource. --> <script type="text/javascript" src="../angular-1.0.2/angular.js"></script> <script type="text/javascript" src="../angular-1.0.2/angular-resource.js"></script> <script type="text/javascript"> //    ngResource   //   . var app = angular.module( "Demo", [ "ngResource" ] ); // ,  app . app.run( function( $resource ) { //   ,     //  ,    get()  query(),   //   HTTP.     RESTful //        // ,       CRUD. var messages = $resource( "./api.cfm/messages/:listController:id/:docController", { id: "@id", listController: "@listController", docController: "@docController" }, { clear: { method: "POST", params: { listController: "clear-all" } }, archive: { method: "POST", params: { docController: "archive" } } } ); //    ,   //    . // GET  ID. messages.query(); // POST   . messages.clear(); // GET  ID. messages.get( { id: 4 } ); // POST   . messages.archive( { id: 8 } ); } ); </script> </head> <body> <!--   . --> </body> </html> 

Please note that my Angulean resource is viewed by two different controllers:


When resource methods were involved above, then, ultimately, four requests were made to the following addresses:


As you can see, Angulyar correctly identified the URLs according to the REST. Kayf!

If interested, here is the test API file:

 <!---    ,   . ---> <cfset resourcePath = cgi.path_info /> <!--- : ,  ColdFusion 10 ,         POST.  , . ---> <cfif ( cgi.request_method neq "GET" )> <cfset requestBody = getHTTPRequestData().content /> </cfif> <!---   ,  ,      . ---> <cfif reFind( "^/messages$", resourcePath )> <cfset response = "GET without ID." /> <cfelseif reFind( "^/messages/clear-all$", resourcePath )> <cfset response = "POST with clear-all Controller." /> <cfelseif reFind( "^/messages/\d+$", resourcePath )> <cfset response = "GET with ID." /> <cfelseif reFind( "^/messages/\d+/archive+$", resourcePath )> <cfset response = "POST with archive controller" /> <cfelse> <cfset response = "Hmm, couldn't match resource." /> </cfif> <!---    JSON.   ,   . ---> <cfset serializedResponse = serializeJSON( response ) /> <!---     . ---> <cfheader name="X-Debug-Path" value="#cgi.path_info#" /> <!---      . ---> <cfcontent type="application/json" variable="#charsetDecode( serializedResponse, 'utf-8' )#" /> 


For some reason, ColdFusion 10 hung up on POST requests, until I got access to the request body (via the getHttpRequestData () function). This happened only if the request body contained JSON (JavaScript Object Notation) data. When it was empty, the query did not hang. I don’t understand thoroughly the processing of requests and I don’t know if it makes sense, however, I’ll note that ColdFusion 9 doesn’t do that.

Original

Source: https://habr.com/ru/post/180941/


All Articles