| 1 | import twisted |
|---|
| 2 | from twisted.internet import reactor, defer |
|---|
| 3 | from twisted.web import server, static, resource |
|---|
| 4 | from twisted.python import versions |
|---|
| 5 | |
|---|
| 6 | import pyamf |
|---|
| 7 | from pyamf.remoting.gateway.twisted import TwistedGateway |
|---|
| 8 | from pyamf.remoting.gateway import expose_request |
|---|
| 9 | from pyamf import register_class |
|---|
| 10 | |
|---|
| 11 | import sqlalchemy |
|---|
| 12 | from sqlalchemy import create_engine |
|---|
| 13 | from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey |
|---|
| 14 | from sqlalchemy.orm import mapper, sessionmaker |
|---|
| 15 | |
|---|
| 16 | import logging |
|---|
| 17 | |
|---|
| 18 | logging.basicConfig( |
|---|
| 19 | level=logging.DEBUG, |
|---|
| 20 | format='%(asctime)s %(levelname)-5.5s [%(name)s] %(message)s' |
|---|
| 21 | ) |
|---|
| 22 | |
|---|
| 23 | # We define our tables within a catalog called MetaData, using the |
|---|
| 24 | # Table construct, which is used in a manner similar to SQL's CREATE |
|---|
| 25 | # TABLE syntax: |
|---|
| 26 | metadata = MetaData() |
|---|
| 27 | |
|---|
| 28 | users_table = Table('users', metadata, |
|---|
| 29 | Column('id', Integer, primary_key=True), |
|---|
| 30 | Column('name', String(50)), |
|---|
| 31 | Column('fullname', String), |
|---|
| 32 | Column('password', String), |
|---|
| 33 | Column('ip', String(50)) |
|---|
| 34 | ) |
|---|
| 35 | |
|---|
| 36 | |
|---|
| 37 | # Create a rudimentary User class to correspond to our users table. |
|---|
| 38 | # It only need subclass Python's built-in object class (i.e. it's a |
|---|
| 39 | # new style class): |
|---|
| 40 | class User(object): |
|---|
| 41 | def __init__(self, name, fullname, password, ip): |
|---|
| 42 | self.name = name |
|---|
| 43 | self.fullname = fullname |
|---|
| 44 | self.password = password |
|---|
| 45 | self.ip = ip |
|---|
| 46 | |
|---|
| 47 | def __repr__(self): |
|---|
| 48 | return "<User('%s','%s', '%s')>" % (self.name, self.fullname, |
|---|
| 49 | self.ip) |
|---|
| 50 | |
|---|
| 51 | # Use the mapper function to create a mapping between users_table and |
|---|
| 52 | # User. The mapper() function creates a new Mapper object and stores |
|---|
| 53 | # it away for future reference, associated with our class. |
|---|
| 54 | mapper(User, users_table) |
|---|
| 55 | register_class(User, 'org.pyamf.User') |
|---|
| 56 | |
|---|
| 57 | class example: |
|---|
| 58 | """ |
|---|
| 59 | An example class that can be used as a PyAMF service |
|---|
| 60 | """ |
|---|
| 61 | def __init__(self): |
|---|
| 62 | self.logger = pyamf.logging.instance_logger(self) |
|---|
| 63 | self.pyamf_version = versions.getVersionString( |
|---|
| 64 | versions.Version('PyAMF', *pyamf.__version__)) |
|---|
| 65 | self.sqlalchemy_version = 'SQLAlchemy %s' % sqlalchemy.__version__ |
|---|
| 66 | self.twisted_version = 'Twisted %s' % twisted.version.base() |
|---|
| 67 | |
|---|
| 68 | # Use an in-memory-only SQLite database. |
|---|
| 69 | self.engine = create_engine('sqlite:///:memory:', echo=True) |
|---|
| 70 | |
|---|
| 71 | # Define a Session class which will serve as a factory for new |
|---|
| 72 | # Session objects |
|---|
| 73 | Session = sessionmaker(bind=self.engine) |
|---|
| 74 | |
|---|
| 75 | # This will create new Session objects which are bound to the |
|---|
| 76 | # database |
|---|
| 77 | self.session = Session() |
|---|
| 78 | |
|---|
| 79 | # Next, we can issue CREATE TABLE statements derived from our table |
|---|
| 80 | # metadata, by calling create_all() and passing it the engine instance |
|---|
| 81 | # which points to our database. This will check for the presence of a |
|---|
| 82 | # table first before creating, so it's safe to call multiple times: |
|---|
| 83 | metadata.create_all(self.engine) |
|---|
| 84 | |
|---|
| 85 | self.logger.debug(self.twisted_version) |
|---|
| 86 | self.logger.debug(self.pyamf_version) |
|---|
| 87 | self.logger.debug(self.sqlalchemy_version) |
|---|
| 88 | |
|---|
| 89 | def test1(self, request): |
|---|
| 90 | return "Test 1 Success!" |
|---|
| 91 | |
|---|
| 92 | def testn(self, request, n): |
|---|
| 93 | ip = exposedRequest(request) |
|---|
| 94 | |
|---|
| 95 | return "%s said %s!" % (ip, n) |
|---|
| 96 | |
|---|
| 97 | def add(self, request, username, fullname, password): |
|---|
| 98 | """ |
|---|
| 99 | """ |
|---|
| 100 | ip = exposedRequest(request) |
|---|
| 101 | new_user = User(username, fullname, password, ip) |
|---|
| 102 | |
|---|
| 103 | self.session.add(new_user) |
|---|
| 104 | self.session.commit() |
|---|
| 105 | |
|---|
| 106 | return new_user |
|---|
| 107 | |
|---|
| 108 | # This function is decorated to expose the underlying HTTP request |
|---|
| 109 | # This allows for accessing things such as the requesting client's IP |
|---|
| 110 | @expose_request |
|---|
| 111 | def exposedRequest(request): |
|---|
| 112 | return request.getClientIP() |
|---|
| 113 | |
|---|
| 114 | if __name__ == '__main__': |
|---|
| 115 | # Create a dictionary mapping the service namespaces to a function |
|---|
| 116 | # or class instance |
|---|
| 117 | service = { |
|---|
| 118 | 'example': example(), |
|---|
| 119 | } |
|---|
| 120 | |
|---|
| 121 | # Place the namespace mapping into a TwistedGateway |
|---|
| 122 | gateway = TwistedGateway(service) |
|---|
| 123 | |
|---|
| 124 | # A base root resource for the twisted.web server |
|---|
| 125 | root = resource.Resource() |
|---|
| 126 | |
|---|
| 127 | # Publish the PyAMF gateway at the root URL |
|---|
| 128 | root.putChild('', gateway) |
|---|
| 129 | |
|---|
| 130 | # Start the twisted reactor and listen on HTTP port 8080 |
|---|
| 131 | print 'Running AMF gateway on http://localhost:8080' |
|---|
| 132 | |
|---|
| 133 | reactor.listenTCP(8080, server.Site(root)) |
|---|
| 134 | reactor.run() |
|---|
| 135 | |
|---|
| 136 | |
|---|