summaryrefslogtreecommitdiff
path: root/lib/server.py
blob: 9261730c0fa43b1813af4717caa303c476ec4d6a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
"""All webserver logic lives here, including routes"""
from flask import Flask
from flask import request, jsonify

import sys, os
import cherrypy
from paste.translogger import TransLogger

sys.path.append("./lib")
from pb import *
from param import BadParamError
from config import SERVER_HOST, SERVER_PORT

#FIXME add remote_addr and this jsonp thing

class InvalidUsage(Exception):
    """error class for InvalidUsage"""
    status_code = 400

    def __init__(self, message, status_code=None, payload=None):
        Exception.__init__(self)
        self.message = message
        if status_code is not None:
            self.status_code = status_code
        self.payload = payload

    def to_dict(self):
        rv = dict(self.payload or ())
        rv['message'] = self.message
        return rv

class Server(object):
    """Main server class"""
    def __init__(self):
        self.app = Flask(__name__)
        self._wsgi_server = None
        @self.app.route('/test', methods=['GET'])
        def test():
            return "HELLO WORLD!"
        @self.app.route('/im/api/<pb_classname>', methods=['POST'])
        def pb(pb_classname):
            ip = '127.0.0.1' #fixme
            return self._response_post(
                pb_classname, 
                request.form.to_dict(),
                remote_addr=ip
            )

        @self.app.errorhandler(InvalidUsage)
        def handle_invalid_usage(error):
            response = jsonify(error.to_dict())
            response.status_code = error.status_code
            return response

        self._classname_aliases = {
            'generate' : 'PbGenerate',
            'imgrid' : 'PbGrid',
            'imbreak' : 'PbBreaker',
            'impattern' : 'PbPattern',
            'imgradient' : 'PbGradient',
            'landscape' : 'PbLandscape',
        }

    def _find_class_by_name(self, pb_classname):
        pb_classname = self._classname_aliases.get(pb_classname, None) or pb_classname
        try:
            return filter(lambda c: c.__name__ == pb_classname, Pb.__subclasses__())[0]
        except IndexError:
            raise InvalidUsage('No such api', status_code=410)

    def _response_post(self, pb_classname, request_form, remote_addr=None):
        pb_class = self._find_class_by_name(pb_classname)
        classnames = map(lambda c: c.__name__, Pb.__subclasses__())
        try:
            pb = pb_class(**request_form)
            pb.create()
            pb.file_s3move()
            pb.db_send(remote_addr=remote_addr)
            json_data = jsonify(pb.file_dict())
            if pb.params.callback: #accounts for jsonp
                return "%s(%s)" % (pb.params.callback, json_data)
            return json_data

        except BadParamError:
            for i in request_form.keys():
                sys.stderr.write('\'%s\':\'%s\'\n' % (i, request_form[i] or None))
            return jsonify({'error' : 'Bad Params'})
        except PbProcessError:
            return jsonify({'error' : 'Problem with server-side processing' })

    def run(self, host=SERVER_HOST, port=SERVER_PORT):
        self.app.run(host=host, port=port)

    def run_wsgi(self, server_port=SERVER_PORT, host=SERVER_HOST):
        #http://fgimian.github.io/blog/2012/12/08/setting-up-a-rock-solid-python-development-web-server/
        # Enable WSGI access logging via Paste
        app_logged = TransLogger(self.app)

        # Mount the WSGI callable object (app) on the root directory
        cherrypy.tree.graft(app_logged, '/')

        # Set the configuration of the web server
        cherrypy.config.update({
            'engine.autoreload_on': True,
            'log.screen': True,
            'server.socket_port': server_port,
            'server.socket_host': host
        })
        cherrypy.engine.start()
        cherrypy.engine.block()