Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Support additional HTTP methods: PUT, DELETE

    As part of a new project we are building all of our services as fully RESTful such that the HTTP method determines the action desired and the URI just the resource. In building a new RestfulDataSource I have copied and modified the getServiceInputs to support "putParams" and "deleteParams".

    It would be a welcome addition to have SmartClient natively support these additional HTTP methods to avoid duplication of code and manual maintenance of base code fixes.

    #2
    Hi David,

    I don't think that override is necessary - you should be able to simply leave dataProtocol as "getParams" or "postParams" but simply set dsRequest.httpMethod to "PUT" or "DELETE". As long as you're digging through source, you'll notice that Comm.js respects these values.

    If you can confirm this works for you, we'll add docs to note that this is the right approach.

    Comment


      #3
      Thanks for the feedback. I was able to specify the httpMethod as part of the DataSource operationBindings as listed below and it worked in my limited testing. This is much preferred to overloading getServiceInputs.

      Code:
          operationBindings:[
             {operationType:"fetch", dataProtocol:"getParams"},
             {operationType:"add", dataProtocol:"postParams"},
             {operationType:"remove", dataProtocol:"getParams", requestProperties:{httpMethod:"DELETE"}},
             {operationType:"update", dataProtocol:"getParams", requestProperties:{httpMethod:"PUT"}}
          ],

      Comment


        #4
        Thanks. We've added docs to reflect this practice.

        Just curious, what's your backend? Rails or something?

        Comment


          #5
          No. We have an existing backend library in .Net for which smartclient-targeted, restful services are being developed. All of this to replace an aging and fat VB client.

          Comment


            #6
            Ah, good to hear. Congratulations on using a state of the art architecture.

            Comment


              #7
              A little more feedback on this solution. The httpMethod override does not work with dataProtocol: postMessage. It appears the following code from DataSource.getServiceInputs always overrides the desired httpMethod:
              Code:
                      // remaining possibilities ("postMessage", "postXML", "soap") all POST a request body
              
                      var serviceInputs = {
                          actionURL: dataURL,
                          httpMethod: "POST"
                      };

              Comment


                #8
                Quite right. That's now been fixed. However, you should be able to avoid duplicating getServiceInputs via the following workaround (this is untested, as I can't easily test it):

                Code:
                getDataFormat : function (dsRequest) {
                   if (isc.isAn.Object(dsRequest) && dsRequest.operationType == "update") {
                       dsRequest.httpMethod = "PUT";
                   }
                   return this.Super("getDataFormat", arguments);
                },
                This assumes you had decided to use dataProcotol:"postMessage" or similar for operationType:"update" where you specify httpMethod:"PUT" - is that right?

                Comment


                  #9
                  Yes, that's what I'm looking for. Basically, for adds and updates I want to use postMessage so I can include an xml or json formatted object as the message body rather than a form's format. I'll give your workaround a try.

                  Comment


                    #10
                    It appears this workaround does not work. I believe it is because the dsRequest passed to getDataFormat is embedded in the rpcRequest that has the httpMethod that needs to be updated.

                    Code:
                    From sendDSRequest:
                    
                            var inputs = this.getServiceInputs(dsRequest);
                            var rpcRequest = isc.addProperties({}, dsRequest, inputs);
                    
                            // hold onto the dsRequest that initiated this call, and the indirect callback
                            rpcRequest._dsRequest = dsRequest;
                    
                    ...
                    
                            var dataFormat = this.getDataFormat(dsRequest);

                    Comment


                      #11
                      You're correct, getDataFormat() won't work. Somehow the more direct approach did not occur to me:

                      Code:
                      getServiceInputs : function (dsRequest) {
                         var inputs = this.Super("getServiceInputs", arguments);
                         if (dsRequest.operationType == "update") inputs.httpMethod = "PUT";
                         return inputs;
                      },
                      You don't like what a method is doing so you override it, right? Must have had too much coffee yesterday.

                      Comment


                        #12
                        Perfect! Although I use inheritance constantly server-side, it just hasn't clicked for me in javascript yet so I didn't catch that either... Now I can get the json serialization working... Thanks!

                        Comment


                          #13
                          RESTful

                          I'm still going through David's example he linked on this post - http://forums.smartclient.com/showthread.php?t=2945, if you find the link is broken - use this one http://smartclientexperience.blogspot.com/

                          Would Isomorphic be able to indicate if there is any intention to provide a supported RESTful data source - I see the following as requirements of a RESTful datasource (mostly stuff that David has implemented) over and above the functionality of the existing RestDataSource.

                          1. Default implementations of update and delete that use PUT and DELETE HTTP methods

                          2. The ability to specify request parameters as part of a dynamic URL (in REST the URL is intended to specify the resource, rather than using GET parameters or POST/PUT body - these just contain the information required to perform the operation on the resource)

                          3. Support for population of the HTTP Authorization header (which is badly named - should be Authentication) - session tracking in cookies violates REST statelessness - authentication should be checked on each request based on this header. AWS has one possible implementation http://docs.amazonwebservices.com/Am...ntication.html. One good reason for this - if you want your REST service to be consumed by something other than a UI, the good old login screen isn't avilable. Another reason is that service interoperability isn't necessarily session based (the idea of login, sit down and do some stuff, and then logout). So if you want your service interface to be the same for messaging and UI interaction, you don't want session cookies. All that said, I am using session cookies :) - consequently my non-UI based messaging API is currently limited to unauthenticated access. But if you want a truly RESTful DataSource it should support this header.

                          4. Possibly the use of OPTIONS to identify which operations are allowed, although this is probably a bit tricky - i.e. when exactly do you call OPTIONS? I am providing it from an authorisation perspective - i.e. 'What can I do to this resource?' and the answer may change depending on the HTTP Authorization header (or session cookie :)). Perhaps just supporting this would be useful, so it can be called manually by the client code, with the result being that client side validation will provide some sort of 'Operation not available' behaviour. Another use would be to query the datasource for the purpose of excluding or greying out control options - e.g. if 'myDS.canUpdate() then render edit button' type logic. To be honest though, I can see this generating way too many HTTP requests, so it may not be viable unless someone has a clever idea, or provides a convincing argument or method about the number of requests.

                          5. Construction of the XML/JSON POST/PUT message body from the recordXPath, valueXPath combination - i.e. the server defines the message format, not the client.

                          Others may have other requirements - thanks,

                          Colin
                          Last edited by hawkettc; 30 Nov 2008, 09:03.

                          Comment


                            #14
                            PS

                            A good showcase might be pointing the new REST datasource at the Amazon service without modification :)
                            Last edited by hawkettc; 30 Nov 2008, 09:22.

                            Comment


                              #15
                              1. Already supported. See this post. 7.0 has docs that suggest this approach for pure REST implementations.

                              2. Already supported via modifying/adding actionURL in transformRequest(). Could be made simply via something like "pathSegmentFields" which would automatically add certain criteria fields as path segments.

                              3. Already supported - see rpcRequest.httpHeaders. Specific support for particular methods of authentication may not make sense in the framework until standards gel, but examples might be useful

                              4. We haven't looked into whether enough browsers allow an OPTIONS request, and whether there are existing services where this has an important function. Can you share?

                              5. Support for automatically round-tripping such messages makes sense. Note it's already there for WSDL (useFlatFields).

                              Comment

                              Working...
                              X