forked from indymedia/epicyon
Move webfinger cache
parent
4b68f1b437
commit
ff338e4de2
|
@ -0,0 +1,39 @@
|
||||||
|
__filename__ = "cache.py"
|
||||||
|
__author__ = "Bob Mottram"
|
||||||
|
__license__ = "AGPL3+"
|
||||||
|
__version__ = "0.0.1"
|
||||||
|
__maintainer__ = "Bob Mottram"
|
||||||
|
__email__ = "bob@freedombone.net"
|
||||||
|
__status__ = "Production"
|
||||||
|
|
||||||
|
# cache of actor json
|
||||||
|
# If there are repeated lookups then this helps prevent a lot
|
||||||
|
# of needless network traffic
|
||||||
|
personCache = {}
|
||||||
|
|
||||||
|
# cached webfinger endpoints
|
||||||
|
cachedWebfingers = {}
|
||||||
|
|
||||||
|
def storePersonInCache(personUrl: str,personJson) -> None:
|
||||||
|
"""Store an actor in the cache
|
||||||
|
"""
|
||||||
|
personCache[personUrl]=personJson
|
||||||
|
|
||||||
|
def storeWebfingerInCache(handle: str,wf) -> None:
|
||||||
|
"""Store a webfinger endpoint in the cache
|
||||||
|
"""
|
||||||
|
cachedWebfingers[handle]=wf
|
||||||
|
|
||||||
|
def getPersonFromCache(personUrl: str):
|
||||||
|
"""Get an actor from the cache
|
||||||
|
"""
|
||||||
|
if personCache.get(personUrl):
|
||||||
|
return personCache[personUrl]
|
||||||
|
return None
|
||||||
|
|
||||||
|
def getWebfingerFromCache(handle: str):
|
||||||
|
"""Get webfinger endpoint from the cache
|
||||||
|
"""
|
||||||
|
if cachedWebfingers.get(handle):
|
||||||
|
return cachedWebfingers[handle]
|
||||||
|
return None
|
|
@ -137,10 +137,10 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.wfile.write(json.dumps(getPerson).encode('utf-8'))
|
self.wfile.write(json.dumps(getPerson).encode('utf-8'))
|
||||||
self.GETbusy=False
|
self.GETbusy=False
|
||||||
return
|
return
|
||||||
getPersonKey = personKeyLookup(thisDomain,self.path)
|
personKey = personKeyLookup(thisDomain,self.path)
|
||||||
if getPersonKey:
|
if personKey:
|
||||||
self._set_headers('text/html; charset=utf-8')
|
self._set_headers('text/html; charset=utf-8')
|
||||||
self.wfile.write(getPersonKey.encode('utf-8'))
|
self.wfile.write(personKey.encode('utf-8'))
|
||||||
self.GETbusy=False
|
self.GETbusy=False
|
||||||
return
|
return
|
||||||
# check that a json file was requested
|
# check that a json file was requested
|
||||||
|
|
28
person.py
28
person.py
|
@ -15,34 +15,6 @@ from webfinger import createWebfingerEndpoint
|
||||||
from webfinger import storeWebfingerEndpoint
|
from webfinger import storeWebfingerEndpoint
|
||||||
from posts import createOutbox
|
from posts import createOutbox
|
||||||
|
|
||||||
# cache of actor json
|
|
||||||
# If there are repeated lookups then this helps prevent a lot
|
|
||||||
# of needless network traffic
|
|
||||||
personCache = {}
|
|
||||||
|
|
||||||
def storePersonInCache(personUrl: str,personJson) -> None:
|
|
||||||
personCache[personUrl]=personJson
|
|
||||||
|
|
||||||
def getPersonFromCache(personUrl: str):
|
|
||||||
if personCache.get(personUrl):
|
|
||||||
return personCache[personUrl]
|
|
||||||
return None
|
|
||||||
|
|
||||||
def getPersonKey(username: str,domain: str,keyType='public'):
|
|
||||||
"""Returns the public or private key of a person
|
|
||||||
"""
|
|
||||||
handle=username+'@'+domain
|
|
||||||
baseDir=os.getcwd()
|
|
||||||
keyFilename=baseDir+'/keys/'+keyType+'/'+handle.lower()+'.key'
|
|
||||||
if not os.path.isfile(keyFilename):
|
|
||||||
return ''
|
|
||||||
keyPem=''
|
|
||||||
with open(keyFilename, "r") as pemFile:
|
|
||||||
keyPem=pemFile.read()
|
|
||||||
if len(keyPem)<20:
|
|
||||||
return ''
|
|
||||||
return keyPem
|
|
||||||
|
|
||||||
def generateRSAKey() -> (str,str):
|
def generateRSAKey() -> (str,str):
|
||||||
key = RSA.generate(2048)
|
key = RSA.generate(2048)
|
||||||
privateKeyPem = key.exportKey("PEM").decode("utf-8")
|
privateKeyPem = key.exportKey("PEM").decode("utf-8")
|
||||||
|
|
63
posts.py
63
posts.py
|
@ -11,15 +11,17 @@ import json
|
||||||
import commentjson
|
import commentjson
|
||||||
import html
|
import html
|
||||||
import datetime
|
import datetime
|
||||||
import os, shutil
|
import os
|
||||||
|
import shutil
|
||||||
import threading
|
import threading
|
||||||
|
import sys
|
||||||
|
import trace
|
||||||
|
from cache import storePersonInCache
|
||||||
|
from cache import getPersonFromCache
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
from random import randint
|
from random import randint
|
||||||
from session import getJson
|
from session import getJson
|
||||||
from session import postJson
|
from session import postJson
|
||||||
from person import getPersonFromCache
|
|
||||||
from person import storePersonInCache
|
|
||||||
from person import getPersonKey
|
|
||||||
try:
|
try:
|
||||||
from BeautifulSoup import BeautifulSoup
|
from BeautifulSoup import BeautifulSoup
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -31,6 +33,51 @@ sendThreads = []
|
||||||
# stores the results from recent post sending attempts
|
# stores the results from recent post sending attempts
|
||||||
postLog = []
|
postLog = []
|
||||||
|
|
||||||
|
class threadWithTrace(threading.Thread):
|
||||||
|
def __init__(self, *args, **keywords):
|
||||||
|
threading.Thread.__init__(self, *args, **keywords)
|
||||||
|
self.killed = False
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
self.__run_backup = self.run
|
||||||
|
self.run = self.__run
|
||||||
|
threading.Thread.start(self)
|
||||||
|
|
||||||
|
def __run(self):
|
||||||
|
sys.settrace(self.globaltrace)
|
||||||
|
self.__run_backup()
|
||||||
|
self.run = self.__run_backup
|
||||||
|
|
||||||
|
def globaltrace(self, frame, event, arg):
|
||||||
|
if event == 'call':
|
||||||
|
return self.localtrace
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def localtrace(self, frame, event, arg):
|
||||||
|
if self.killed:
|
||||||
|
if event == 'line':
|
||||||
|
raise SystemExit()
|
||||||
|
return self.localtrace
|
||||||
|
|
||||||
|
def kill(self):
|
||||||
|
self.killed = True
|
||||||
|
|
||||||
|
def getPersonKey(username: str,domain: str,keyType='public'):
|
||||||
|
"""Returns the public or private key of a person
|
||||||
|
"""
|
||||||
|
handle=username+'@'+domain
|
||||||
|
baseDir=os.getcwd()
|
||||||
|
keyFilename=baseDir+'/keys/'+keyType+'/'+handle.lower()+'.key'
|
||||||
|
if not os.path.isfile(keyFilename):
|
||||||
|
return ''
|
||||||
|
keyPem=''
|
||||||
|
with open(keyFilename, "r") as pemFile:
|
||||||
|
keyPem=pemFile.read()
|
||||||
|
if len(keyPem)<20:
|
||||||
|
return ''
|
||||||
|
return keyPem
|
||||||
|
|
||||||
def permitted(url: str,federationList) -> bool:
|
def permitted(url: str,federationList) -> bool:
|
||||||
"""Is a url from one of the permitted domains?
|
"""Is a url from one of the permitted domains?
|
||||||
"""
|
"""
|
||||||
|
@ -74,7 +121,7 @@ def getPersonBox(session,wfRequest,boxName='inbox'):
|
||||||
personUrl = getUserUrl(wfRequest)
|
personUrl = getUserUrl(wfRequest)
|
||||||
if not personUrl:
|
if not personUrl:
|
||||||
return None
|
return None
|
||||||
personJson=getPersonFromCache(personUrl)
|
personJson = getPersonFromCache(personUrl)
|
||||||
if not personJson:
|
if not personJson:
|
||||||
personJson = getJson(session,personUrl,asHeader,None)
|
personJson = getJson(session,personUrl,asHeader,None)
|
||||||
if not personJson.get(boxName):
|
if not personJson.get(boxName):
|
||||||
|
@ -307,7 +354,7 @@ def threadSendPost(session,postJsonObject,federationList,inboxUrl: str,signature
|
||||||
tries=0
|
tries=0
|
||||||
backoffTime=60
|
backoffTime=60
|
||||||
for attempt in range(20):
|
for attempt in range(20):
|
||||||
postResult = postJson(session,postJsonObject,federationList,inboxUrl,signatureHeader):
|
postResult = postJson(session,postJsonObject,federationList,inboxUrl,signatureHeader)
|
||||||
if postResult:
|
if postResult:
|
||||||
postLog.append(postJsonObject['published']+' '+postResult+'\n')
|
postLog.append(postJsonObject['published']+' '+postResult+'\n')
|
||||||
# keep the length of the log finite
|
# keep the length of the log finite
|
||||||
|
@ -358,9 +405,9 @@ def sendPost(session,username: str, domain: str, toUsername: str, toDomain: str,
|
||||||
|
|
||||||
# Keep the number of threads being used small
|
# Keep the number of threads being used small
|
||||||
while len(sendThreads)>10:
|
while len(sendThreads)>10:
|
||||||
sendThreads[0].stop()
|
sendThreads[0].kill()
|
||||||
sendThreads.pop(0)
|
sendThreads.pop(0)
|
||||||
thr = threading.Thread(target=threadSendPost,args=(session,postJsonObject.copy(),federationList,inboxUrl,signatureHeader.copy()),daemon=True)
|
thr = threadWithTrace(target=threadSendPost,args=(session,postJsonObject.copy(),federationList,inboxUrl,signatureHeader.copy()),daemon=True)
|
||||||
sendThreads.append(thr)
|
sendThreads.append(thr)
|
||||||
thr.start()
|
thr.start()
|
||||||
return 0
|
return 0
|
||||||
|
|
10
webfinger.py
10
webfinger.py
|
@ -14,6 +14,8 @@ import json
|
||||||
import commentjson
|
import commentjson
|
||||||
import os
|
import os
|
||||||
from session import getJson
|
from session import getJson
|
||||||
|
from cache import storeWebfingerInCache
|
||||||
|
from cache import getWebfingerFromCache
|
||||||
|
|
||||||
def parseHandle(handle):
|
def parseHandle(handle):
|
||||||
if '.' not in handle:
|
if '.' not in handle:
|
||||||
|
@ -31,14 +33,14 @@ def parseHandle(handle):
|
||||||
|
|
||||||
return username, domain
|
return username, domain
|
||||||
|
|
||||||
cachedWebfingers = {}
|
|
||||||
|
|
||||||
def webfingerHandle(session,handle: str,https: bool):
|
def webfingerHandle(session,handle: str,https: bool):
|
||||||
username, domain = parseHandle(handle)
|
username, domain = parseHandle(handle)
|
||||||
if not username:
|
if not username:
|
||||||
return None
|
return None
|
||||||
if cachedWebfingers.get(username+'@'+domain):
|
wf=getWebfingerFromCache(username+'@'+domain)
|
||||||
return cachedWebfingers[username+'@'+domain]
|
if wf:
|
||||||
|
return wf
|
||||||
prefix='https'
|
prefix='https'
|
||||||
if not https:
|
if not https:
|
||||||
prefix='http'
|
prefix='http'
|
||||||
|
@ -50,7 +52,7 @@ def webfingerHandle(session,handle: str,https: bool):
|
||||||
#except:
|
#except:
|
||||||
# print("Unable to webfinger " + url)
|
# print("Unable to webfinger " + url)
|
||||||
# return None
|
# return None
|
||||||
cachedWebfingers[username+'@'+domain] = result
|
storeWebfingerInCache(username+'@'+domain, result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def generateMagicKey(publicKeyPem):
|
def generateMagicKey(publicKeyPem):
|
||||||
|
|
Loading…
Reference in New Issue