Advertisement
s243a

rest_test3.py

Nov 12th, 2018
299
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 16.55 KB | None | 0 0
  1. import bottle
  2. from bottle import route, run, Bottle, request
  3. import sys, os, re, urllib
  4. import datetime #I think I need this
  5. import time #I think I need this
  6. from gevent import queue
  7. from gevent import Greenlet
  8. import gevent
  9. import StringIO
  10. from datetime import datetime
  11.  
  12. #from gevent import pywsgi #Don't need this yet
  13. fcpHost = "127.0.0.1"
  14. import fcp
  15. #node = fcp.FCPNode(host=fcpHost, verbosity=fcp.DETAIL)
  16. jobs={}
  17. app = Bottle()
  18.  
  19. #https://stackoverflow.com/questions/17262170/bottle-py-enabling-cors-for-jquery-ajax-requests#17262900
  20. # the decorator
  21. def enable_cors(fn):
  22.     def _enable_cors(*args, **kwargs):
  23.         # set CORS headers
  24.         response.headers['Access-Control-Allow-Origin'] = '*'
  25.         response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, OPTIONS'
  26.         response.headers['Access-Control-Allow-Headers'] = 'Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token'
  27.  
  28.         if bottle.request.method != 'OPTIONS':
  29.             # actual request; reply with the actual response
  30.             return fn(*args, **kwargs)
  31.  
  32.     return _enable_cors
  33.  
  34.  
  35. def delim_filter(config):
  36.     bottle.debug(True)
  37.     print("Entering delim_filter")
  38.     ''' Matches a comma separated list of numbers. '''
  39.     aconfig = config or "%20"
  40.     print ("aconfig=" + aconfig)
  41.     delimiter = urllib.unquote(aconfig).decode('utf8')
  42.     print("delimiter=" + delimiter)  
  43.     regexp = r'(?!{a_delim})+({a_delim}(?!{a_delim})+)*'.format(a_delim=re.escape(delimiter))
  44.     print("regexp="+regexp)
  45.     def to_python(match):
  46.         print("Converting Match")
  47.         print("Math=" + match)
  48.         ms = map(urllib.unquote(aconfig).decode,match.split())
  49.         print( "ms=" + ms )
  50.         return ms
  51.  
  52.     def to_url(astr):
  53.         print("Converting to URL")
  54.         print ("astr=" + astr)
  55.         astr2 = delimiter.join(map(urllib.unquote(aconfig).decode,astr))
  56.         print("astr2="+astr2)
  57.         print  astr2
  58.         return astr2
  59.  
  60.     return regexp, to_python, to_url
  61.  
  62. app.router.add_filter('delim', delim_filter)
  63.  
  64. def split_urlArgs(url,delim=" ",
  65.                   decode='All',
  66.                   xfm_de=lambda a: urllib.unquote(a).decode('utf8'),
  67.                   xfm_split=lambda a, b: re.split(a,b), #Typically a is a regular expression and b a string
  68.                   fn_regexp = lambda a: r'(?!{a_delim})+({a_delim}(?!{a_delim})+)*'.format(a_delim=a) ):
  69.     bottle.debug(True)
  70.     ''' Matches a comma separated list of numbers. '''
  71.     print("delimiter=" + delim)  
  72.     if decode == "Args":
  73.         ms = xfm_split(fn_regexp(a),url)
  74.     elif decode == "All":
  75.         url2 = xfm_de(url)    #Decode the URL
  76.         delim= xfm_de(delim) #Decode the delimitor
  77.         ms = xfm_split(fn_regexp(delim),url)
  78.     elif decode == "None":
  79.         ms = xfm_split(fn_regexp(delim),url) #SPlit the URL based on a regular expression.
  80.            
  81.     print( "ms=" + "["+",".join(ms) +"]" )    
  82.     return ms, delim
  83.  
  84. def combine_urlArgs(args,delim=" ",
  85.                     encode='All',
  86.                     xfm_encode=lambda a: urllib.quote(a, safe=''),
  87.                     xfm_join=lambda a, b: a.join(b)): #Typically a is the delimiter and b is a list
  88.     print("Converting to URL")
  89.     print ("astr=" + args)
  90.     if decode == "Args":
  91.         astr2 = xfm_join(delim,(map(lambda a: xfm_encode,args)))
  92.     elif decode == "All":
  93.         astr2 = urllib.unquote(xfm_join(delim,args))
  94.     elif decode=="None":
  95.         astr2 = xfm_join(delim,args)      
  96.     print("astr2="+astr2)
  97.     return astr2    
  98.  
  99.  
  100. #@app.route('/<key>/%09/<cmd>/<args:delim:%09>') # %09 == tab
  101. #@app.route('/<key>/%20/<cmd>/<args:delim:%20>') # %20 == ' '
  102. #@app.route('/<key>/ /<cmd>/<args:delim: >') # %20 == ' '
  103. #@app.route('/<key>/%3B/<cmd>/<args:delim:%3B>') # %3B == ';'
  104. #@app.route('/<key>/;/<cmd>/<args:delim:;>') # %3B == ';'
  105. #@app.route('/<key>/%2C/<cmd>/<args:delim:%2C>') # %2C == ','
  106. #@app.route('/<key>/,/<cmd>/<args:delim:,>') # %2C == ','
  107. @app.route('/<key>/<sep>/<cmd>/<args:path>') # %2C == ','
  108. def mystery(key,cmd,args,sep=""):
  109.     bottle.debug(True)
  110.     print("engering mystery")
  111.     print("sep=" + sep)
  112.     if len(sep) > 0 : # True if seperator is a wild card
  113.         args, sep = split_urlArgs(args,sep)
  114.     if key == '1234': # %2C == ','
  115.         print(key)
  116.         print(cmd)
  117.         print(args)
  118.         #delimiter = urllib.unquote(aconfig).decode('utf8')
  119.         #print(delimiter)            
  120.         result1 = os.popen("IFS=<a_dilim>".format(a_dilim=sep)).read()
  121.         print("result1=" + result1)
  122.         result2 = result1 + "<br>"
  123.         print("result2=" + result2)    
  124.         cmd_str=cmd + sep + sep.join(args)
  125.         print(cmd_str)  
  126.         result3 = result2 +os.popen(cmd_str).read()
  127.         print("result3=" + result3)              
  128.         return "<pre>" + result3 + "</pre>"
  129.         #return result3.replace("\n","<br>")
  130.         #return ('key=' + key + '<br>' +
  131.         #     'sep=' + sep + '<br>' +
  132.         #     'cmd=' + cmd + '<br>' +
  133.         #     'args='   + "[" + ",".join(args)+"]")
  134. def generateFreeWorker(job_or_uri,message=None,afile=None,fcpHost = "127.0.0.1",fcpPort= 9481,aBody=None,OutputType="HTML"):
  135.     fw = FreeWorkerFactory(job_or_uri,message,afile,fcpHost,fcpPort,aBody,OutputType)
  136.     return fw        
  137. #class calbackExecuter:
  138. #    __init__(self,calbacks):
  139. #        self.callbacks=calbacks
  140. #    def execute():
  141. #        for c in self.calbacks():
  142. #            c()
  143. class loggerContainer:
  144.     def __init__(self,job=None,node=None,**kw):
  145.         self.ready = False
  146.         self.strBuff = StringIO.StringIO()
  147.         self.job = job
  148.         self.Brk = kw.get('Brk',"\n")
  149.         self.body = kw.get('body',None) #The html body to write to.
  150.         self.complete=False
  151.         self.msgDict={}
  152.         self.meseges=[None]*5
  153.         self.msgPosNext=0
  154.         self.msgPos=-1
  155.         self.msgMax=5
  156.         self.msgLnCnt=0  
  157.         self.node=node
  158.     def filterMSG(self,msg): #We don't want to see the same log message too often
  159.         t1=self.msgDict.get(msg,None)
  160.         if t1 is not None: #isinstance(t1,datetime):
  161.             t2=datetime.now()
  162.             delta = t2 - t1 #https://stackoverflow.com/questions/2880713/time-difference-in-seconds-as-a-floating-point
  163.             if delta.seconds>20:
  164.                 return True
  165.             else:
  166.                 return False
  167.         return True
  168.     def do_logfunc(self,msgline,cb=None):
  169.         print("self.msgPosNext="+str(self.msgPosNext))
  170.         self.meseges[self.msgPosNext]={ "msg_str" : msgline,
  171.                                         "time" : datetime.now()
  172.                                       }      
  173.         self.msgPos=self.msgPosNext
  174.         print("self.msgMax="+str(self.msgMax))
  175.         self.msgPosNext=((self.msgPosNext+1)%(self.msgMax))
  176.         self.msgDict[msgline]=datetime.now()
  177.         if self.msgLnCnt<self.msgMax:
  178.             self.msgLnCnt=self.msgLnCnt+1        
  179.     def logfunc(self,msgline,cb=None,HTML_lb="<br>"):
  180.         if cb is None:
  181.             cb=self.print_and_put_cb
  182.         if self.filterMSG(msgline):
  183.             self.do_logfunc(msgline,cb)
  184.             cb(msgline)
  185.     def filterForBody(self,msg):
  186.         if msg.startswith("NODE:") or msg.startswith("CLIENT:"):
  187.             return True
  188.         else:
  189.             return False
  190.     def bodyPut_cb(self,msg,HTML_lb="<br>"):
  191.         if filterForBody(msg):
  192.             self.body.put(self.msg_to_str(msg)+HTML_lb)
  193.     def detectEndMsg(self,msg):
  194.        
  195.         if filterForBody(self,msg):
  196.             node_or_client = True
  197.         else
  198.             node_or_client = False
  199.         if
  200.         return node_or_client
  201.        
  202.     def print_and_put_cb(self,msg,HTML_lb="<br>"):
  203.         print self.msg_to_str(msg)
  204.         if self.body is not None:
  205.             self.bodyPut_cb(msg,HTML_lb)
  206.     def msg_to_str(self,msg):
  207.         if type(msg) == str:
  208.             return msg
  209.         elif type(msg) is dict: #isinstance(msg, collections.Mapping): #https://stackoverflow.com/questions/25231989/how-to-check-if-a-variable-is-a-dictionary-in-python
  210.             return msg['msg_str']
  211.         else:
  212.             return "Empty Message"
  213.     def tail(self,lines=0,cb=None,delta=None):
  214.         if cb is None:
  215.             cb=self.print_and_put_cb
  216.         if lines == 0:
  217.             N=self.msgMax
  218.         else:
  219.             N=min(self.msgMax,lines)
  220.         for i in range(self.msgPost,self.msgPos-N+1,-1):
  221.             msg_i=self.meseges[i%self.msgMax]
  222.             if delta is not None:
  223.                 t2=datetime.now()
  224.                 t1=msg_i['time']
  225.                 delta2=t2-t1
  226.                 if delta2.delta.microseconds > delta.microseconds:
  227.                     break
  228.             cb(self.meseges[i%self.msgMax])
  229.                  
  230.         #self.body.put(msgline)  
  231.     def myLogger(self, level, msg):
  232.         print("level="+level + " msg=" + msg)
  233.         if level > self.job.verbosity:
  234.             return  
  235.         if not msg.endswith(self.Brk):
  236.             msg += "\n"
  237.        
  238.         strBuff.write(msg)
  239.         self.isReady = True
  240.         #strBuff.flush()
  241.         #time.sleep(0.001)
  242.     def getLogger(self): #THis might be redundant
  243.         return self.myLogger              
  244.     def isReady(self):
  245.         return self.ready
  246.     def flush(self):
  247.         val=self.strBuff.getvalue()
  248.         self.strBuff.close()
  249.         self.strBuff = StringIO.StringIO()
  250.         self.isRead=False
  251.         return val
  252.     def getValue(self):
  253.         self.strBuff.getValue()
  254.     def readBuf(self):
  255.         if self.ready:
  256.             val = self.flush()
  257.             ready = True
  258.             return val, ready
  259.         else:
  260.             ready = False
  261.             val = ""
  262.             return val, ready
  263.         return val, ready
  264.     def isComplete(self): # We might also want to check for an EndMessage and wait if needed
  265.         return self.complete
  266.         #if self.job.msg['hdr'] == 'PutSuccessful':
  267.         #    return True
  268.         #elif self.job.msg['hdr'] == 'PutFailed':
  269.         #    return True
  270.     def callback(self, status, value):
  271.         if status == 'PutSuccessful':
  272.             self.complete=True
  273.         elif status == 'PutFailed':
  274.             self.complete=True
  275.         #elif status == 'URIGenerated':
  276.         #    self.complete=True        
  277.         #self.msg=value
  278.     def getCallback(self):
  279.         return self.callback    
  280. class FreeWorkerFactory:
  281.  
  282.     #self.job = None #A freenet job
  283.     #self.g = None
  284.     #self.body = None
  285.     #self.OutputType =None
  286.    
  287.     def __init__(self,job_or_uri,**kw):
  288.         self.kw={}
  289.         self.kw['message']=kw.get('message',None)
  290.         self.kw['file']=kw.get(file,None)
  291.         self.loggerContainer=kw.get('loggerContainer',None)
  292.         #if self.kw['logger'] is not None:
  293.         #    loggerContainer
  294.         self.host=kw.get('host',"127.0.0.1")
  295.         self.port=self.kw.get('port',9481)
  296.         self.OutputType=self.kw.get('OutputType','HTML')
  297.         #selffcpPort,aBody,OutputType
  298.         if type(job_or_uri) is str:
  299.             print("__init__" + "uri as input")
  300.             if job_or_uri in jobs:                
  301.                 print("uri in jobs")
  302.                 self.job=jobs[job_or_uri]
  303.             else:
  304.                 print("making job")
  305.                 node = fcp.FCPNode(fcpHost,verbosity='fcp.DETAIL',port=self.kw)
  306.                 val = self.kw['message']
  307.                 ksk = job_or_uri
  308.                 uri = "KSK@" + ksk
  309.                 node.put("KSK@"+ksk, data=val, mimetype="text/plain", verbosity=fcp.DETAIL)
  310.                 self.job = node.get(uri, async=True)
  311.         else:
  312.             print("__init__"+"job as input")
  313.             self.job=job_or_uri
  314.         if self.OutputType == "HTML":
  315.             self.Brk="<br>"
  316.         elif self.OutputType == "UNIX":
  317.             self.Brk="" #We won't use "\n" since print automatically generates the \n. Write can be used instead if one wants to explicitly use the /n
  318.         self.body=None
  319.         self.setBody(kw.get('body',None))    
  320.     #def freenetWorker(self):
  321.     #    #  Empty Callback: http://echochamber.me/viewtopic.php?t=64825
  322.     #    #stop_me = lambda *_, **_: None
  323.     def on_data(self):
  324.         # we can poll the job
  325.         while True:
  326.             val, ready = self.loggerContainer.readBuf()
  327.             if ready:
  328.                 print val
  329.                 self.body.put(val)    
  330.             if self.loggerContainer.isComplete():
  331.                 print "Yay! job complete"
  332.                 self.body.put(job.getResult()) #Returns the completion message.
  333.                 break        
  334.             else:
  335.                 print "Waiting" + datetime.now().strftime('%s(s) %m/%d/%Y')+self.Brk
  336.                 self.body.put("Waiting" + datetime.now().strftime('%s(s) %m/%d/%Y')+self.Brk)
  337.                 time.sleep(0.001)
  338.                 gevent.sleep(5) #This yields control to another greenlet
  339.         self.on_finish() #Maybe we can sequence the greenlets instead of putting this here.
  340.     def on_finish(self):
  341.         self.body.put('</body></html>') #There should be a way to seperate these last two lines from this method.
  342.         self.body.put(StopIteration)
  343.     def header(self,start_response=None):
  344.         if self.OutputType == "HTML":
  345.             if start_response is not None:
  346.                 start_response('200 OK', [('Content-Type', 'text/html')])
  347.         self.body.put(' ' * 1000)
  348.         if self.OutputType == "HTML":
  349.             self.body.put("<html><body><h1>Current Time:</h1>")  
  350.            
  351.     def handle(self,environ=None, start_response=None,aBody=None):
  352.         lambda a: self.start(self,enviorn,start_response)
  353.         #g = Greenlet.spawn(on_data, body)
  354.     def setBody(self,aBody=None):
  355.         if aBody is None:
  356.            if self.body is None:
  357.                self.body = queue.Queue()
  358.                self.g = Greenlet(self.on_data)
  359.                self.loggerContainer.body=self.body
  360.         else:
  361.            self.body = aBody
  362.     def start(self,environ=None, start_response=None,aBody=None): # Not sure
  363.         #https://stackoverflow.com/questions/20824218/how-to-implement-someasyncworker-from-bottle-asynchronous-primer
  364.         #g = Greenlet.spawn(current_time, lambda a: on_data(body))
  365.         print("Set Body")
  366.         self.setBody(aBody)
  367.         print("header")
  368.         self.header(start_response)
  369.         print("start")
  370.         self.g.start()            
  371.         return self.body, self.g
  372.  
  373. #@enable_cors
  374.        
  375. @app.post('/KSK/insert')
  376. def rest_test():
  377.     fcpHost=request.json.get('host','127.0.0.1')
  378.     fcpVerbosity=request.json.get('verbosity',fcp.NOISY)
  379.     fcpPort=request.json.get('port',9481)
  380.    
  381.  
  382.  
  383.    
  384.     val = request.json.get('message')
  385.     ksk = request.json.get('ksk')
  386.     uri = "KSK@" + ksk
  387.    
  388.     print "Inserting %s, containing '%s'" % (uri, val)
  389.     # do the put - note that 'data=' inserts a string directly
  390.     # note too that mimetype is optional, defaulting to text/plain
  391.     #node.put("KSK@"+ksk, data=val, mimetype="text/plain")
  392.     # ------------------------------------------
  393.     # now, demonstrate asynchronous requests    
  394.     print "Launching asynchronous request"
  395.     lgrCnt=loggerContainer()
  396.     node = fcp.FCPNode(host=fcpHost,verbosity=fcp.NOISY,port=fcpPort,logfunc=lgrCnt.logfunc)    
  397.     job = node.put(uri, data=val, async=True) #, verbosity=fcp.DETAIL
  398.     loggerContainer.job=job
  399.     loggerContainer.node=node
  400.     jobs["KSK@"+ksk]=job    
  401.  
  402.     #node.logfunc=lgrCnt.logfunc
  403.     job._log=lgrCnt.getLogger()
  404.     job.callback=lgrCnt.getCallback()
  405.    
  406.     worker = FreeWorkerFactory(job,loggerContainer=lgrCnt)
  407.     body, g = worker.start() #Returns the greenelet
  408.     #body = gevent.queue.Queue()    
  409.     #worker = getFreenetWorker(job)
  410.     #worker.on_data(body.put)
  411.     #Finish https://stackoverflow.com/questions/20824218/how-to-implement-someasyncworker-from-bottle-asynchronous-primer
  412.     #worker.on_finish(lambda: body.put(StopIteration)) #    body.put('</body></html>')      
  413.  
  414.     return body      
  415.     #yield job_waitt("KSK@"+ksk)
  416.     #return "KSK Inserted" # We probably want to do wsomething smarter than this.
  417.    
  418.     # or we can await its completion
  419.  
  420. #@app.route('/USK@<hashKey:nocomma>,<ecryptionKey:nocomma>,<encryption:nocomma>/<metaData:path>')
  421. #def hello(hashKey,ecryptionKey,encryption,metaData):
  422. #    
  423. #    mimetype, val1 = node.get(uri)
  424. #    return ('hashKey=' + hashKey + '<br>' +
  425. #             'ecryptionKey=' + ecryptionKey + '<br>' +
  426. #             'encryption=' + encryption + '<br>' +
  427. #             'metaData='   + metaData)
  428. #            
  429. #Regular eressions use a seperate filter; https://bottlepy.org/docs/dev/routing.html
  430. app.run(host='localhost', port=8082, debug=True)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement