2021SC@SDUSC
经过几周的代码学习,已经完成了大部分代码的分析,还剩下一些零散的文件。
_version.py主要是描述了当前的WsgiDAV版本号。
例子
预发布版(alpha, beta,候选版本):
“3.0.0a1”、“3.0.0b1”、“3.0.0rc1”
最终版本:
“3.0.0”
发展版(将3.0.0标记为“使用”)。不发布):
“3.0.0.dev1”
注意:
安装pywin32时,MSI版本的编号必须为a.b.c ?
“3.0.0a4”似乎在这种情况下不工作。
compat.py:支持Python 2和Python 3的工具函数。
对于python2:
if PY2:
from base64 import decodestring as base64_decodebytes
from base64 import encodestring as base64_encodebytes
from cgi import escape as html_escape
def is_basestring(s):
"""Return True for any string type (for str/unicode on Py2 and bytes/str on Py3)."""
return isinstance(s, basestring)
def is_bytes(s):
"""Return True for bytestrings (for str on Py2 and bytes on Py3)."""
return isinstance(s, str)
def is_native(s):
"""Return True for native strings (for str on Py2 and Py3)."""
return isinstance(s, str)
def is_unicode(s):
"""Return True for unicode strings (for unicode on Py2 and str on Py3)."""
return isinstance(s, unicode)
def to_bytes(s, encoding="utf8"):
"""Convert unicode (text strings) to binary data (str on Py2 and bytes on Py3)."""
if type(s) is unicode:
s = s.encode(encoding)
elif type(s) is not str:
s = str(s)
return s
to_native = to_bytes
"""Convert data to native str type (bytestring on Py2 and unicode on Py3)."""
def to_unicode(s, encoding="utf8"):
"""Convert data to unicode text (unicode on Py2 and str on Py3)."""
if type(s) is not unicode:
s = unicode(s, encoding)
return s
处理python3的情况
# Python 3
from base64 import decodebytes as base64_decodebytes
from base64 import encodebytes as base64_encodebytes
from html import escape as html_escape
def is_basestring(s):
"""Return True for any string type (for str/unicode on Py2 and bytes/str on Py3)."""
return isinstance(s, (str, bytes))
def is_bytes(s):
"""Return True for bytestrings (for str on Py2 and bytes on Py3)."""
return isinstance(s, bytes)
def is_native(s):
"""Return True for native strings (for str on Py2 and Py3)."""
return isinstance(s, str)
def is_unicode(s):
"""Return True for unicode strings (for unicode on Py2 and str on Py3)."""
return isinstance(s, str)
def to_bytes(s, encoding="utf8"):
"""Convert a text string (unicode) to bytestring (str on Py2 and bytes on Py3)."""
if type(s) is not bytes:
s = bytes(s, encoding)
return s
def to_native(s, encoding="utf8"):
"""Convert data to native str type (bytestring on Py2 and unicode on Py3)."""
if type(s) is bytes:
s = str(s, encoding)
elif type(s) is not str:
s = str(s)
return s
to_unicode = to_native
"""Convert binary data to unicode (text strings) on Python 2 and 3."""
对WSGI进行支持。
将环境变量转换为WSGI 'bytes-as-unicode'字符串
def unicode_to_wsgi(u):
# Taken from PEP3333; the server should already have performed this, when
# passing environ to the WSGI application
return u.encode(_filesystemencoding, "surrogateescape").decode("iso-8859-1")
将本机字符串转换为WSGI / HTTP兼容的字节串
def wsgi_to_bytes(s):
"""Convert a native string to a WSGI / HTTP compatible byte string."""
# Taken from PEP3333
return s.encode("iso-8859-1")
dav_error.py:实现用于通知WebDAV和HTTP错误的DAVError类。分为DAVErrorCondition、DAVError两个类。
DAVError:通用错误类,用于标记HTTP和WEBDAV错误.
关键代码
返回可读的字符串。
def get_user_info(self):
"""Return readable string."""
if self.value in ERROR_DESCRIPTIONS:
s = "{}".format(ERROR_DESCRIPTIONS[self.value])
else:
s = "{}".format(self.value)
if self.context_info:
s += ": {}".format(self.context_info)
elif self.value in ERROR_RESPONSES:
s += ": {}".format(ERROR_RESPONSES[self.value])
if self.src_exception:
s += "\n Source exception: '{}'".format(self.src_exception)
if self.err_condition:
s += "\n Error condition: '{}'".format(self.err_condition)
return s
返回一个元组(内容类型,响应页面)。
def get_response_page(self):
"""Return a tuple (content-type, response page)."""
# If it has pre- or post-condition: return as XML response
if self.err_condition:
return ("application/xml", compat.to_bytes(self.err_condition.as_string()))
# Else return as HTML
status = get_http_status_string(self)
html = []
html.append(
"<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN' "
"'http://www.w3.org/TR/html4/strict.dtd'>"
)
html.append("<html><head>")
html.append(
" <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>"
)
html.append(" <title>{}</title>".format(status))
html.append("</head><body>")
html.append(" <h1>{}</h1>".format(status))
html.append(" <p>{}</p>".format(compat.html_escape(self.get_user_info())))
html.append("<hr/>")
html.append(
"<a href='https://github.com/mar10/wsgidav/'>WsgiDAV/{}</a> - {}".format(
__version__, compat.html_escape(str(datetime.datetime.now()), "utf-8")
)
)
html.append("</body></html>")
html = "\n".join(html)
return ("text/html", compat.to_bytes(html))
除去这两个类,还有一些函数也十分重要。
返回HTTP响应代码为整数,例如204
def get_http_status_code(v):
"""Return HTTP response code as integer, e.g. 204."""
if hasattr(v, "value"):
return int(v.value) # v is a DAVError
else:
return int(v)
返回HTTP响应字符串,例如204 ->('204无内容')。返回字符串总是包含描述性文本,以满足Apache mod_dav。' v ':状态码或DAVError
def get_http_status_string(v):
code = get_http_status_code(v)
try:
return ERROR_DESCRIPTIONS[code]
except KeyError:
return "{} Status".format(code)
将任何非daverror异常转换为HTTP_INTERNAL_ERROR
def as_DAVError(e):
if isinstance(e, DAVError):
return e
elif isinstance(e, Exception):
# traceback.print_exc()
return DAVError(HTTP_INTERNAL_ERROR, src_exception=e)
else:
return DAVError(HTTP_INTERNAL_ERROR, "{}".format(e))
debug_filter.py:
用于调试的WSGI中间件(可选)。此模块将请求和响应信息转储到控制台(具体取决于此)在当前的调试配置。
初始化:
定义HTTP方法和石蕊测试,这应该打开详细模式
(目前硬编码)。
为每个请求:
增加' ' environ['verbose'] ' '的值,如果请求应该被调试。同时转储请求和响应的头部和主体。然后将请求传递给下一个中间件。
这些配置设置被评估:
*详细*
这也被其他模块使用。这个过滤器添加了额外的信息。取决于值。
* debug_methods *
在处理某些请求方法时,将详细度提高到3。这个选项
当``verbose < 2``时被忽略。
配置::
debug_methods = ["PROPPATCH", "PROPFIND", "GET", "HEAD", "DELET E",
" put ", " copy ", " move ", " lock ", " unlock ",
]
* debug_litmus *
提高冗长到3,而处理石蕊测试,包含某些
子字符串。当``verbose < 2``时,此选项将被忽略。
配置::
Debug_litmus = ["notowner_modify", "props: 16",]
文件中只包含WsgiDavDebugFilter一个类。
主要代码:
def __init__(self, wsgidav_app, next_app, config):
super(WsgiDavDebugFilter, self).__init__(wsgidav_app, next_app, config)
self._config = config
# self.out = sys.stdout
self.passedLitmus = {}
# These methods boost verbose=2 to verbose=3
self.debug_methods = config.get("debug_methods", [])
# Litmus tests containing these string boost verbose=2 to verbose=3
self.debug_litmus = config.get("debug_litmus", [])
# Exit server, as soon as this litmus test has finished
self.break_after_litmus = [
# "locks: 15",
]