Advertisement
s243a

rest_test4.py

Nov 12th, 2018
284
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 18.41 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.         mDict, suceeded=parseMsg(msgline)
  181.         mnode_or_client=Dict.get('node_or_client',False)
  182.         if cb is None:
  183.             cb=lambda msg: self.print_and_put_cb(msg,HTML_lb="<br>",chkSender=True)
  184.         if node_or_client:
  185.             self.do_logfunc(msgline,cb)
  186.             cb(msgline) #The default callback (i.e. cb) is print_and_put_cb which rpints then calls put_cb
  187.     def parseMsg(self,msg):
  188.         mDict=parseSenderLine(msg)
  189.         sender=mDict.get('sender',None)
  190.         if (sender == 'CLIENT') or (sender == 'CLIENT'):
  191.             mDict['node_or_client')=True
  192.             try: #Not sure if we need a try/except here
  193.                 #k, v = mgStrToKey(mDict['msg_str'])
  194.                 #mDict['k']=v
  195.                 mDict=parseFCPMsgStr(mDict['msg_str']) # I haven't decided if a dictionary should be returned or a seperate key/value
  196.             except:
  197.                 pass
  198.         return mDict    
  199.     def parseSenderLine(self,msg_line):
  200.        regex=r'^(?P<sender>\S+)[:]\s+(?P<msg_str>[^\n])\n<0,1>'
  201.        try: #Not sure if we need a try/except here
  202.            m=match(regex,msg_line)
  203.            mDict=m.groupdict()
  204.            asert len(mDict['msg_str'])>0 #,"Could not parse msg_str"
  205.        except AssertionError:
  206.            print("Could not parse msg_str")
  207.            print("msg_line="+msg_line)
  208.            return mDict, False
  209.        return mDict, True
  210.     def parseFCPMsgStr(self,msg_line): #I should think of a better name for this
  211.         mDict, succeeded = self.parseSenderLine(msg_line)
  212.         if succeeded:
  213.             k, v, hasKeyVal = line.split("=", 1)
  214.             if hasKeyVal:
  215.                 mDict['parsed'][k]=v
  216.             else
  217.                 mDict['parsed'][mDict['msg_str']]=True #Maybe do some checks here such as length and for white space characters
  218.         return mDict, succeeded
  219.     def print_and_put_cb(self,msg,HTML_lb="<br>",chkSender=True):
  220.         print self.msg_to_str(msg)
  221.         if self.body is not None:
  222.             self.bodyPut_cb(msg,HTML_lb=HTML_lb,chkSender=chkSender)
  223.     def bodyPut_cb(self,msg,HTML_lb="<br>",chkSender=True):
  224.         #parseMsg
  225.         if chkSender:
  226.             if filterForBody(msg):
  227.                 self.body.put(self.msg_to_str(msg)+HTML_lb)
  228.         else
  229.             self.body.put(self.msg_to_str(msg)+HTML_lb):
  230.            
  231.     def filterForBody(self,msg):
  232.         if msg.startswith("NODE:") or msg.startswith("CLIENT:"):
  233.             return True
  234.         else:
  235.             return False
  236.  
  237.     def detectEndMsg(self,msg):
  238.        
  239.         if filterForBody(self,msg):
  240.             node_or_client = True
  241.         else
  242.             node_or_client = False
  243.         if
  244.         return node_or_client
  245.        
  246.  
  247.     def msg_to_str(self,msg):
  248.         if type(msg) == str:
  249.             return msg
  250.         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
  251.             return msg['msg_str']
  252.         else:
  253.             return "Empty Message"
  254.     def tail(self,lines=0,cb=None,delta=None):
  255.         if cb is None:
  256.             cb=self.print_and_put_cb
  257.         if lines == 0:
  258.             N=self.msgMax
  259.         else:
  260.             N=min(self.msgMax,lines)
  261.         for i in range(self.msgPost,self.msgPos-N+1,-1):
  262.             msg_i=self.meseges[i%self.msgMax]
  263.             if delta is not None:
  264.                 t2=datetime.now()
  265.                 t1=msg_i['time']
  266.                 delta2=t2-t1
  267.                 if delta2.delta.microseconds > delta.microseconds:
  268.                     break
  269.             cb(self.meseges[i%self.msgMax])
  270.                  
  271.         #self.body.put(msgline)  
  272.     def myLogger(self, level, msg):
  273.         print("level="+level + " msg=" + msg)
  274.         if level > self.job.verbosity:
  275.             return  
  276.         if not msg.endswith(self.Brk):
  277.             msg += "\n"
  278.        
  279.         strBuff.write(msg)
  280.         self.isReady = True
  281.         #strBuff.flush()
  282.         #time.sleep(0.001)
  283.     def getLogger(self): #THis might be redundant
  284.         return self.myLogger              
  285.     def isReady(self):
  286.         return self.ready
  287.     def flush(self):
  288.         val=self.strBuff.getvalue()
  289.         self.strBuff.close()
  290.         self.strBuff = StringIO.StringIO()
  291.         self.isRead=False
  292.         return val
  293.     def getValue(self):
  294.         self.strBuff.getValue()
  295.     def readBuf(self):
  296.         if self.ready:
  297.             val = self.flush()
  298.             ready = True
  299.             return val, ready
  300.         else:
  301.             ready = False
  302.             val = ""
  303.             return val, ready
  304.         return val, ready
  305.     def isComplete(self): # We might also want to check for an EndMessage and wait if needed
  306.         return self.complete
  307.         #if self.job.msg['hdr'] == 'PutSuccessful':
  308.         #    return True
  309.         #elif self.job.msg['hdr'] == 'PutFailed':
  310.         #    return True
  311.     def callback(self, status, value):
  312.         if status == 'PutSuccessful':
  313.             self.complete=True
  314.         elif status == 'PutFailed':
  315.             self.complete=True
  316.         #elif status == 'URIGenerated':
  317.         #    self.complete=True        
  318.         #self.msg=value
  319.     def getCallback(self):
  320.         return self.callback    
  321. class FreeWorkerFactory:
  322.  
  323.     #self.job = None #A freenet job
  324.     #self.g = None
  325.     #self.body = None
  326.     #self.OutputType =None
  327.    
  328.     def __init__(self,job_or_uri,**kw):
  329.         self.kw={}
  330.         self.kw['message']=kw.get('message',None)
  331.         self.kw['file']=kw.get(file,None)
  332.         self.loggerContainer=kw.get('loggerContainer',None)
  333.         #if self.kw['logger'] is not None:
  334.         #    loggerContainer
  335.         self.host=kw.get('host',"127.0.0.1")
  336.         self.port=self.kw.get('port',9481)
  337.         self.OutputType=self.kw.get('OutputType','HTML')
  338.         #selffcpPort,aBody,OutputType
  339.         if type(job_or_uri) is str:
  340.             print("__init__" + "uri as input")
  341.             if job_or_uri in jobs:                
  342.                 print("uri in jobs")
  343.                 self.job=jobs[job_or_uri]
  344.             else:
  345.                 print("making job")
  346.                 node = fcp.FCPNode(fcpHost,verbosity='fcp.DETAIL',port=self.kw)
  347.                 val = self.kw['message']
  348.                 ksk = job_or_uri
  349.                 uri = "KSK@" + ksk
  350.                 node.put("KSK@"+ksk, data=val, mimetype="text/plain", verbosity=fcp.DETAIL)
  351.                 self.job = node.get(uri, async=True)
  352.         else:
  353.             print("__init__"+"job as input")
  354.             self.job=job_or_uri
  355.         if self.OutputType == "HTML":
  356.             self.Brk="<br>"
  357.         elif self.OutputType == "UNIX":
  358.             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
  359.         self.body=None
  360.         self.setBody(kw.get('body',None))    
  361.     #def freenetWorker(self):
  362.     #    #  Empty Callback: http://echochamber.me/viewtopic.php?t=64825
  363.     #    #stop_me = lambda *_, **_: None
  364.     def on_data(self):
  365.         # we can poll the job
  366.         while True:
  367.             val, ready = self.loggerContainer.readBuf()
  368.             if ready:
  369.                 print val
  370.                 self.body.put(val)    
  371.             if self.loggerContainer.isComplete():
  372.                 print "Yay! job complete"
  373.                 self.body.put(job.getResult()) #Returns the completion message.
  374.                 break        
  375.             else:
  376.                 print "Waiting" + datetime.now().strftime('%s(s) %m/%d/%Y')+self.Brk
  377.                 self.body.put("Waiting" + datetime.now().strftime('%s(s) %m/%d/%Y')+self.Brk)
  378.                 time.sleep(0.001)
  379.                 gevent.sleep(5) #This yields control to another greenlet
  380.         self.on_finish() #Maybe we can sequence the greenlets instead of putting this here.
  381.     def on_finish(self):
  382.         self.body.put('</body></html>') #There should be a way to seperate these last two lines from this method.
  383.         self.body.put(StopIteration)
  384.     def header(self,start_response=None):
  385.         if self.OutputType == "HTML":
  386.             if start_response is not None:
  387.                 start_response('200 OK', [('Content-Type', 'text/html')])
  388.         self.body.put(' ' * 1000)
  389.         if self.OutputType == "HTML":
  390.             self.body.put("<html><body><h1>Current Time:</h1>")  
  391.            
  392.     def handle(self,environ=None, start_response=None,aBody=None):
  393.         lambda a: self.start(self,enviorn,start_response)
  394.         #g = Greenlet.spawn(on_data, body)
  395.     def setBody(self,aBody=None):
  396.         if aBody is None:
  397.            if self.body is None:
  398.                self.body = queue.Queue()
  399.                self.g = Greenlet(self.on_data)
  400.                self.loggerContainer.body=self.body
  401.         else:
  402.            self.body = aBody
  403.     def start(self,environ=None, start_response=None,aBody=None): # Not sure
  404.         #https://stackoverflow.com/questions/20824218/how-to-implement-someasyncworker-from-bottle-asynchronous-primer
  405.         #g = Greenlet.spawn(current_time, lambda a: on_data(body))
  406.         print("Set Body")
  407.         self.setBody(aBody)
  408.         print("header")
  409.         self.header(start_response)
  410.         print("start")
  411.         self.g.start()            
  412.         return self.body, self.g
  413.  
  414. #@enable_cors
  415.        
  416. @app.post('/KSK/insert')
  417. def rest_test():
  418.     fcpHost=request.json.get('host','127.0.0.1')
  419.     fcpVerbosity=request.json.get('verbosity',fcp.NOISY)
  420.     fcpPort=request.json.get('port',9481)
  421.    
  422.  
  423.  
  424.    
  425.     val = request.json.get('message')
  426.     ksk = request.json.get('ksk')
  427.     uri = "KSK@" + ksk
  428.    
  429.     print "Inserting %s, containing '%s'" % (uri, val)
  430.     # do the put - note that 'data=' inserts a string directly
  431.     # note too that mimetype is optional, defaulting to text/plain
  432.     #node.put("KSK@"+ksk, data=val, mimetype="text/plain")
  433.     # ------------------------------------------
  434.     # now, demonstrate asynchronous requests    
  435.     print "Launching asynchronous request"
  436.     lgrCnt=loggerContainer()
  437.     node = fcp.FCPNode(host=fcpHost,verbosity=fcp.NOISY,port=fcpPort,logfunc=lgrCnt.logfunc)    
  438.     job = node.put(uri, data=val, async=True) #, verbosity=fcp.DETAIL
  439.     loggerContainer.job=job
  440.     loggerContainer.node=node
  441.     jobs["KSK@"+ksk]=job    
  442.  
  443.     #node.logfunc=lgrCnt.logfunc
  444.     job._log=lgrCnt.getLogger()
  445.     job.callback=lgrCnt.getCallback()
  446.    
  447.     worker = FreeWorkerFactory(job,loggerContainer=lgrCnt)
  448.     body, g = worker.start() #Returns the greenelet
  449.     #body = gevent.queue.Queue()    
  450.     #worker = getFreenetWorker(job)
  451.     #worker.on_data(body.put)
  452.     #Finish https://stackoverflow.com/questions/20824218/how-to-implement-someasyncworker-from-bottle-asynchronous-primer
  453.     #worker.on_finish(lambda: body.put(StopIteration)) #    body.put('</body></html>')      
  454.  
  455.     return body      
  456.     #yield job_waitt("KSK@"+ksk)
  457.     #return "KSK Inserted" # We probably want to do wsomething smarter than this.
  458.    
  459.     # or we can await its completion
  460.  
  461. #@app.route('/USK@<hashKey:nocomma>,<ecryptionKey:nocomma>,<encryption:nocomma>/<metaData:path>')
  462. #def hello(hashKey,ecryptionKey,encryption,metaData):
  463. #    
  464. #    mimetype, val1 = node.get(uri)
  465. #    return ('hashKey=' + hashKey + '<br>' +
  466. #             'ecryptionKey=' + ecryptionKey + '<br>' +
  467. #             'encryption=' + encryption + '<br>' +
  468. #             'metaData='   + metaData)
  469. #            
  470. #Regular eressions use a seperate filter; https://bottlepy.org/docs/dev/routing.html
  471. app.run(host='localhost', port=8082, debug=True)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement