serverwallet

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

app.py (2647B)


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