2

I've got an app based on djangoappengine, Backbone.js and Django REST Framework that uses PATCH requests to update models via {patch: true} on a model.save call.

I've found that when testing locally the dev_appserver returns:

ERROR 2014-02-19 04:37:04,531 dev_appserver.py:3081] code 501, message Unsupported method ('PATCH')

INFO 2014-02-19 04:37:04,532 dev_appserver.py:3090] "PATCH /api/posts/5707702298738688 HTTP/1.1" 501 -

Yet when I deploy it and access it through appspot the server happily accepts the request. Which forces me to deploy every time I make a change and want to test it.

I'm running the latests version (1.89) of the Python SDK, and found and old fixed issue that seems to tackle it but it seems other people have had it.

I tried this patch but it didn't make a difference. I don't understand why the development server would reject them and not the production server, is there something I need to change?

Thanks.

Community
  • 1
  • 1
Yeray Diaz
  • 1,700
  • 14
  • 15
  • That fixed issue concerns the PATCH method in the URL Fetch Service, not the development web server. [Issue 975](https://code.google.com/p/googleappengine/issues/detail?id=975) says PROPPPATCH could be fixed for WebDAV support, and that PATCH is still unsupported on the development web server :-( – Martin Berends Feb 19 '14 at 14:21

1 Answers1

0

To update a resource, you can use POST with the x-http-method-override to patch. This is a valid RESTful operation and using POST will be more compatible with firewall and older user agents. The data in the request should indicate what is to be updated.

var url = '/api/posts/5707702298738688'
var patch_ops =  [
        { "op": "replace", "path": "/properties/", "author": text}
        { "op": "add", "path": "/replies/", {"author": text, "comment":"blah"}}
        /*
            { "op": "remove", "path": "/a/b/c" },
            { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] },
            { "op": "replace", "path": "/a/b/c", "value": 42 },
            { "op": "move", "from": "/a/b/c", "path": "/a/b/d" },
            { "op": "copy", "from": "/a/b/d", "path": "/a/b/e" } 
       */
    ];

 var xhr = jQuery.ajax({
        type: "POST",
        beforeSend: function (request)
        {
            request.setRequestHeader("X-HTTP-Method-Override", "PATCH");
        },
        url: url,
        data: my_json_string,
        dataType:"json",
        success: function(data) {
            return data;
        },
        error: function(xhr, textStatus, error){
              return error;
        }
    });

Server handler:

def post(self, object_name):
    if self.request.headers['x-http-method-override'] == 'PATCH':
        # update according to patch operations
        patch_ops_str= self.request.body.decode('utf-8')    
        try:
            patch_ops = json.loads(new_area_geojson_str)
        except:
            self.response.set_status(400)
            return self.response.out.write('{"status": "error", "reason": "JSON Parse error" }')

     else:
         self.response.set_status(405)
         return self.response.out.write('{"status": "error", "reason": "post not accepted without x-http-method-override to PATCH" }')

Adapted from Please do not patch like an idiot

intotecho
  • 4,925
  • 3
  • 39
  • 54