serverwallet

Server-side payment links with metadata.
Log | Files | Refs

app.py (2669B)


      1 import os
      2 import logging
      3 import re
      4 import lmdb
      5 
      6 from srvaddrgen import DbKey
      7 from srvaddrgen.btc import btc_reserve
      8 from srvaddrgen.msg import Message
      9 
     10 logging.basicConfig(level=logging.DEBUG)
     11 logg = logging.getLogger()
     12 
     13 path_btc = re.compile('^/bitcoin$')
     14 
     15 reasons = {
     16     400: 'Bad Request',
     17     404: 'Not Found',
     18         }
     19 class Responder(Exception):
     20 
     21     def __init__(self, responder_method):
     22         self.m = responder_method
     23         self.code = 200
     24         self.reason = 'OK'
     25         self.content = None
     26       
     27 
     28     def get_status(self):
     29         return str(self.code) + ' ' + self.reason
     30 
     31 
     32     def get_content(self):
     33         if self.content == None:
     34             return b''
     35         if isinstance(self.content, bytes):
     36             return self.content
     37         return self.content.encode('utf-8')
     38 
     39 
     40     def complete(self, content=None, reason=None):
     41         self.content = content
     42         if reason != None:
     43             self.reason = reason
     44 
     45 
     46     def croak(self, code, err=None, reason=None):
     47         self.code = code
     48         if reason != None:
     49             self.reason = reason
     50         else:
     51             self.reason = reasons[code]
     52         headers = [('Content-Type', 'text/plain')]
     53         if err != None:
     54             self.content = err
     55         status = self.get_status()
     56         self.m(status, headers)
     57         return self.get_content()
     58 
     59 
     60     def flush(self):
     61         headers = [('Content-Type', 'text/plain')]
     62         status = self.get_status()
     63         self.m(status, headers)
     64         return self.get_content()
     65 
     66 
     67     def __str__(self):
     68         if self.content == None:
     69             return ''
     70         return self.content
     71 
     72 
     73 def application(environ, start_response):
     74     o = Responder(start_response)
     75 
     76     db_path = os.environ.get('SRVADDRGEN_DB_PATH', 'srvaddrgen_data')
     77     dbenv = lmdb.open(db_path, readonly=False)
     78 
     79     method = environ['REQUEST_METHOD']
     80     v = environ['PATH_INFO']
     81     r = None
     82 
     83     if path_btc.match(v):
     84         if method != 'POST':
     85             o.croak(400, 'This endpoint accepts json POST only', reason='POST only')
     86             dbenv.close()
     87             return o.flush()
     88         b = environ['wsgi.input'].read()
     89         msg = None
     90         try:
     91             msg = Message.parse_json(b)
     92         except KeyError as e:
     93             o.croak(400, 'Missing message item: ' + str(e))
     94             dbenv.close()
     95             return o.flush()
     96 
     97         logg.debug('msg! ' + str(msg))
     98         msg.set_origin(environ['REMOTE_ADDR'])
     99         try:
    100             btc_reserve(o, msg, dbenv)
    101         except Responder as e:
    102             logg.error('btc failed: ' + str(o))
    103             o = e
    104 
    105     else:
    106         o.croak(404)
    107     
    108     dbenv.close()
    109 
    110     return o.flush()