[ckan-changes] commit/ckan: dread: [lib/base]: Fix #1206 - Accept POSTs to API of Content-Type application/json.

Bitbucket commits-noreply at bitbucket.org
Thu Jun 30 16:16:01 UTC 2011


1 new changeset in ckan:

http://bitbucket.org/okfn/ckan/changeset/27f2bf88be51/
changeset:   27f2bf88be51
branch:      feature-1141-moderated-edits-ajax
user:        dread
date:        2011-06-30 18:06:33
summary:     [lib/base]: Fix #1206 - Accept POSTs to API of Content-Type application/json.
affected #:  5 files (2.2 KB)

--- a/ckan/lib/base.py	Wed Jun 29 18:06:20 2011 +0100
+++ b/ckan/lib/base.py	Thu Jun 30 18:06:33 2011 +0200
@@ -146,14 +146,23 @@
         '''
         cls.log.debug('Retrieving request params: %r' % request.params)
         cls.log.debug('Retrieving request POST: %r' % request.POST)
-        try:
-            request_data = request.POST.keys()
-        except Exception, inst:
-            msg = _("Could not find the POST data: %r : %s") % \
-                  (request.POST, inst)
-            raise ValueError, msg
+        cls.log.debug('Retrieving request POST body: %r' % request.body)
+        if request.POST:
+            try:
+                request_data = request.POST.keys() or request.body
+            except Exception, inst:
+                msg = _("Could not find the POST data: %r : %s") % \
+                      (request.POST, inst)
+                raise ValueError, msg
+            request_data = request_data[0]
+        elif request.body:
+            try:
+                request_data = request.body
+            except Exception, inst:
+                msg = _("Could not find the POST data: %r : %s") % \
+                      (request.POST, inst)
+                raise ValueError, msg
         if request_data:
-            request_data = request_data[0]
             request_data = json.loads(request_data, encoding='utf8')
             if not isinstance(request_data, dict):
                 raise ValueError, _("Request params must be in form of a json encoded dictionary.")


--- a/ckan/tests/functional/api/base.py	Wed Jun 29 18:06:20 2011 +0100
+++ b/ckan/tests/functional/api/base.py	Thu Jun 30 18:06:33 2011 +0200
@@ -1,8 +1,13 @@
 import re
+try:
+    from cStringIO import StringIO
+except ImportError:
+    from StringIO import StringIO
 
 from pylons import config
 import webhelpers.util
 from nose.tools import assert_equal
+from paste.fixture import TestRequest
 
 from ckan.tests import *
 import ckan.model as model
@@ -300,3 +305,20 @@
         self.user = model.User.by_name(self.user_name)
         self.extra_environ={'Authorization' : str(self.user.apikey)}
 
+    def post_json(self, offset, data, status=None, extra_environ=None):
+        ''' Posts data in the body in application/json format, used by
+        javascript libraries.
+        (rather than Paste Fixture\'s default format of
+        application/x-www-form-urlencoded)
+
+        '''
+        environ = self.app._make_environ()
+        environ['CONTENT_TYPE'] = 'application/json'
+        environ['CONTENT_LENGTH'] = str(len(data))
+        environ['REQUEST_METHOD'] = 'POST'
+        environ['wsgi.input'] = StringIO(data)
+        if extra_environ:
+            environ.update(extra_environ)
+        self.app._set_headers({}, environ)
+        req = TestRequest(offset, environ, expect_errors=False)
+        return self.app.do_request(req, status=status)        


--- a/ckan/tests/functional/api/model/test_package.py	Wed Jun 29 18:06:20 2011 +0100
+++ b/ckan/tests/functional/api/model/test_package.py	Thu Jun 30 18:06:33 2011 +0200
@@ -91,6 +91,19 @@
                 extra_environ=self.extra_environ)
         self.remove()        
 
+    def test_register_post_json(self):
+        assert not self.get_package_by_name(self.package_fixture_data['name'])
+        offset = self.package_offset()
+        data = self.dumps(self.package_fixture_data)
+        res = self.post_json(offset, data, status=self.STATUS_201_CREATED,
+                             extra_environ=self.extra_environ)
+        # Check the database record.
+        self.remove()
+        package = self.get_package_by_name(self.package_fixture_data['name'])
+        assert package
+        self.assert_equal(package.title, self.package_fixture_data['title'])
+        
+
     def test_register_post_bad_request(self):
         test_params = {
             'name':u'testpackage06_400',


--- a/doc/api/howtouse.rst.inc	Wed Jun 29 18:06:20 2011 +0100
+++ b/doc/api/howtouse.rst.inc	Thu Jun 30 18:06:33 2011 +0200
@@ -3,6 +3,8 @@
 
 To send request data, create a simple data structure, then convert it to a JSON string, then percent-encode the JSON string, then send it as the request body. Response data will be in the response body.
 
+If using curl, the default Content-Type header will be ``application/x-www-form-urlencoded`` and the JSON string gets sent as a single parameter key. However Javascript libraries tend to set Content-Type to be ``application/json`` and the JSON string is the body to the POST. The latter content became acceptable from CKAN version 1.4.2.
+
 Notes:
 
  * When you update an object, fields that you don't supply will remain as they were before.


--- a/doc/index.rst	Wed Jun 29 18:06:20 2011 +0100
+++ b/doc/index.rst	Thu Jun 30 18:06:33 2011 +0200
@@ -28,7 +28,6 @@
    load_testing
    distributed
    database_dumps
-   admin
    deb
    vm
    buildbot

Repository URL: https://bitbucket.org/okfn/ckan/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.




More information about the ckan-changes mailing list