JavaScript, PostGIS, Python

A simple CherryPy RESTful JSON server

A simple CherryPy RESTful JSON server

I have recently been working with CherryPy. It seems really cool, but it is quite hard to find simple and clear online examples for some things. In this case I wanted to set up a RESTful server that can accept POST requests containing JSON/GeoJSON, and return JSON/GeoJSON, with the request coming from JavaScript in a web page (no jQuery).

As with many web things there are many layers and it is a lot of work to debug what is exactly going wrong when it doesn’t work! Notable things to remember:

  • CORS – the server (i.e. CherryPy) has to explicitly allow this origin
  • formatting – data must be proper formatted JSON strings in both directions – there are tools to help with this

The following is the code stripped down to it’s minimal working configuration. There may be glaring security holes with this approach, so use with caution and read the docs! Feel free to comment below if you have anything to add to this.

Here is the CherryPy code – the POST method accepts some JSON, and returns the incoming data along with some of its own.

import cherrypy
import json

class DataView(object):
    exposed = True

    @cherrypy.tools.accept(media='application/json')

    def POST(self):
        rawData = cherrypy.request.body.read(int(cherrypy.request.headers['Content-Length']))
        b = json.loads(rawData)
        return json.dumps({'x': 4, 'c': b})

def CORS():
    cherrypy.response.headers["Access-Control-Allow-Origin"] = "http://localhost"

if __name__ == '__main__':
    conf = {
        '/': {
            'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
            'tools.CORS.on': True,
        }
    }
    cherrypy.tools.CORS = cherrypy.Tool('before_handler', CORS)
    cherrypy.quickstart(DataView(), '/d/', conf)

Save this as cherryserver.py and start it in the normal way (i.e. python cherryserver.py). Note that, for testing, my JavaScript is on localhost, so the CORS method contains a header explicitly allowing this origin. In the Quickstart call the class DataView is mounted to the URL /d/.

Very basic web page that makes a POST request containing some JSON and then displays the returned JSON:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8"></meta>

  <script>
    var HttpClient = function() {

      this.post = function(aUrl, data, aCallback) {
        var httpRequest = new XMLHttpRequest();
        httpRequest.open("POST", aUrl, true);
        httpRequest.onreadystatechange = function() {
          if (httpRequest.readyState == 4 && httpRequest.status == 200)
            aCallback(httpRequest.responseText);
        };
        httpRequest.send(JSON.stringify(data));
      };
    };

    var req = new HttpClient();
    var rURL = 'http://localhost:8080/d/';
    req.post(rURL, {"a": 1, "delta": "data"}, function(response) {
      document.getElementById('main').innerHTML = response;
    });

</script>
</head>
<body>

<div>Hello world</div>


<div id='main'></div>

</body>

As above, please do comment if you have any suggestions about making it simpler, improving security, or wish to see some future posts along the lines of: JavaScript, GeoJSON, Python and a PostGIS back-end!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s