request change and readme modification

This commit is contained in:
dobefore 2022-02-04 19:21:18 +08:00 committed by Vikash Kothary
parent 728af26c2e
commit a506785273
2 changed files with 24 additions and 39 deletions

View File

@ -52,12 +52,9 @@ Installing
$ ./ankisyncctl.py adduser <username> $ ./ankisyncctl.py adduser <username>
4. Setup a proxy to unchunk the requests. 4. Setup a proxy to trans-write the requests (Optional) .
Ankisyncd currently support the header "Transfer-Encoding: chunked" used by Anki.
Webob does not support the header "Transfer-Encoding: chunked" used by Anki If you want to enable secure connection or have a better security,a proxy can be set up.
and therefore ankisyncd sees chunked requests as empty. To solve this problem
setup Nginx (or any other webserver of your choice) and configure it to
"unchunk" the requests for ankisyncd.
For example, if you use Nginx on the same machine as ankisyncd, you first For example, if you use Nginx on the same machine as ankisyncd, you first
have to change the port in `ankisyncd.conf` to something other than `27701`. have to change the port in `ankisyncd.conf` to something other than `27701`.

View File

@ -396,23 +396,23 @@ class Requests(object):
self.environ=environ self.environ=environ
@property @property
def params(self): def params(self):
return self._p return self.request_items_dict
@params.setter @params.setter
def params(self,value): def params(self,value):
""" """
A dictionary-like object containing both the parameters from A dictionary-like object containing both the parameters from
the query string and request body. the query string and request body.
""" """
self._p= value self.request_items_dict= value
@property @property
def path(self)-> str: def path(self)-> str:
return self.environ['PATH_INFO'] return self.environ['PATH_INFO']
@property @property
def POST(self): def POST(self):
return self._x return self._request_items_dict
@POST.setter @POST.setter
def POST(self,value): def POST(self,value):
self._x=value self._request_items_dict=value
@property @property
def parse(self): def parse(self):
'''Return a MultiDict containing all the variables from a form '''Return a MultiDict containing all the variables from a form
@ -424,10 +424,10 @@ class Requests(object):
input = env.get('wsgi.input') input = env.get('wsgi.input')
length = 0 if content_len == '' else int(content_len) length = 0 if content_len == '' else int(content_len)
body=b'' body=b''
d={} request_items_dict={}
if length == 0: if length == 0:
if input is None: if input is None:
return d return request_items_dict
if env.get('HTTP_TRANSFER_ENCODING','0') == 'chunked': if env.get('HTTP_TRANSFER_ENCODING','0') == 'chunked':
# readlines and read(no argument) will block # readlines and read(no argument) will block
# convert byte str to number base 16 # convert byte str to number base 16
@ -452,7 +452,7 @@ class Requests(object):
# only strip \r\n if there are extra \n # only strip \r\n if there are extra \n
# eg b'?V\xc1\x8f>\xf9\xb1\n\r\n' # eg b'?V\xc1\x8f>\xf9\xb1\n\r\n'
data.append(item[:-2]) data.append(item[:-2])
d['data']=b''.join(data) request_items_dict['data']=b''.join(data)
others=data_other[len(data):] others=data_other[len(data):]
boundary=others[0] boundary=others[0]
others=b''.join(others).split(boundary.strip()) others=b''.join(others).split(boundary.strip())
@ -462,31 +462,22 @@ class Requests(object):
i=i.splitlines() i=i.splitlines()
key=re.findall(b'name="(.*?)"',i[2],flags=re.M)[0].decode('utf-8') key=re.findall(b'name="(.*?)"',i[2],flags=re.M)[0].decode('utf-8')
v=i[-1].decode('utf-8') v=i[-1].decode('utf-8')
d[key]=v request_items_dict[key]=v
return d return request_items_dict
if query_string !='': if query_string !='':
# GET method # GET method
body=query_string body=query_string
d=urllib.parse.parse_qs(body) request_items_dict=urllib.parse.parse_qs(body)
for k,v in d.items(): for k,v in request_items_dict.items():
d[k]=''.join(v) request_items_dict[k]=''.join(v)
return d return request_items_dict
# request server with web browser
if self.path=='/' :
d= {'url':b'Anki Sync Server'}
return d
if self.path=='/favicon.ico' :
d= {'url':b''}
return d
else: else:
body = env['wsgi.input'].read(length) body = env['wsgi.input'].read(length)
if body is None or body ==b'': if body is None or body ==b'':
# return 'empty body' return request_items_dict
return d
# process body to dict # process body to dict
repeat=body.splitlines()[0] repeat=body.splitlines()[0]
items=re.split(repeat,body) items=re.split(repeat,body)
@ -495,24 +486,24 @@ class Requests(object):
items.pop(0) items.pop(0)
for item in items: for item in items:
if b'name="data"' in item: if b'name="data"' in item:
bt=None data_field=None
# remove \r\n # remove \r\n
if b'application/octet-stream' in item: if b'application/octet-stream' in item:
# Ankidroid case # Ankidroid case
item=re.sub(b'Content-Disposition: form-data; name="data"; filename="data"',b'',item) item=re.sub(b'Content-Disposition: form-data; name="data"; filename="data"',b'',item)
item=re.sub(b'Content-Type: application/octet-stream',b'',item) item=re.sub(b'Content-Type: application/octet-stream',b'',item)
bt=item.strip() data_field=item.strip()
else: else:
# PKzip file stream and others # PKzip file stream and others
item=re.sub(b'Content-Disposition: form-data; name="data"; filename="data"',b'',item) item=re.sub(b'Content-Disposition: form-data; name="data"; filename="data"',b'',item)
bt=item.strip() data_field=item.strip()
d['data']=bt request_items_dict['data']=data_field
continue continue
item=re.sub(b'\r\n',b'',item,flags=re.MULTILINE) item=re.sub(b'\r\n',b'',item,flags=re.MULTILINE)
key=re.findall(b'name="(.*?)"',item)[0].decode('utf-8') key=re.findall(b'name="(.*?)"',item)[0].decode('utf-8')
v=item[item.rfind(b'"')+1:].decode('utf-8') v=item[item.rfind(b'"')+1:].decode('utf-8')
d[key]=v request_items_dict[key]=v
return d return request_items_dict
class chunked(object): class chunked(object):
'''decorator''' '''decorator'''
def __init__(self, func): def __init__(self, func):
@ -608,7 +599,6 @@ class SyncApp:
# cgi file can only be read once,and will be blocked after being read once more # cgi file can only be read once,and will be blocked after being read once more
# so i call Requests.parse only once,and bind its return result to properties # so i call Requests.parse only once,and bind its return result to properties
# POST and params (set return result as property values) # POST and params (set return result as property values)
# can switch back to previous version easily by commenting following two lines
req.params=req.parse req.params=req.parse
req.POST=req.params req.POST=req.params
try: try:
@ -629,8 +619,6 @@ class SyncApp:
compression = 0 compression = 0
try: try:
# can switch back to previous version easily
# data = req.POST['data'].file.read()
data = req.POST['data'] data = req.POST['data']
data = self._decode_data(data, compression) data = self._decode_data(data, compression)
except KeyError: except KeyError: