def with_response_headers(headers, code=200): header = 'HTTP/1.1 {} Good\r\n'.format(code) log('header的值', header) # items() 函数以列表返回可遍历的(键, 值) 元组数组。 header += ''.join('{}: {}\r\n'.format(k, v) for k, v in headers.items()) return header
def route_login(request): headers = { 'Content-Type:': 'text/html', } log('requests and Cookie', headers, request.cookies) username = current_user(request) if request.method == 'POST': form = request.form() u = User.new(form) if u.validate_login(): # 设置一个随机字符串来当令牌 session_id = random_str() # 键是随机值,用户名是键(u.username) session[session_id] = u.username headers['Set-Cookie'] = 'user={}'.format(session_id) # 存在此用户后加上cookie # headers['Set-Cookie'] = 'user={}'.format(u.username) result = '登陆成功' else: result = '用户名或密码错误' else: result = '' body = template('login.html') body = body.replace('{{result}}', result) body = body.replace('{{username}}', username) header = response_with_headers(headers) log('header的值一', header) r = header + '\r\n' + body return r.encode(encoding='utf-8')
def add_cookies(self): cookies = self.headers.get('Cookie', '') kvs = cookies.split(';') log('Cookie', kvs) for kv in kvs: if '=' in kv: k, v = kv.split('=') self.cookies[k] = v
def load(path): """ 本函数从一个文件中载入数据并转化为 dict 或者 list path 是保存文件的路径 """ with open(path, 'r', encoding='utf-8') as f: s = f.read() log('load======', s) # json.loads是把字符串转成字典 return json.loads(s)
def all(cls): """ 得到一个类的所有存储实例 """ path = cls.db_path() log('path的值', path) # 得到path的数据后,用load载入数据 # models被传入了很多字典的列表 models = load(path) # 列表推导把每一个字典都传给一new函数,使他们变成对象而不是字典 ms = [cls.new(m) for m in models] return ms
def save(data, path): """ 本函数把一个 dict 或者 list 写入文件 data 是 dict 或者 list path 是保存文件的路径 """ # json.dumps()函数是将字典转化为字符串 # indent 是缩进 # ensure_ascii=False 用于保存中文 s = json.dumps(data, indent=2, ensure_ascii=False) with open(path, 'w+', encoding='utf-8') as f: log('save', path, s, data) f.write(s)
def save(self): """ 用于把一个Model的实例保存到文件中 """ models = self.all() log('models', models) models.append(self) # __dict__ 是包含了对象所有属性和值的字典 # 把所有的对象用字典表示 __dict__ l = [m.__dict__ for m in models] path = self.db_path() save(l, path)
def redirect(url): """ 浏览器在收到 302 响应的时候 会自动在 HTTP header 里面找 Location 字段并获取一个 url 然后自动请求新的 url """ headers = { 'Location': url, } # 增加 Location 字段并生成 HTTP 响应返回 # 注意, 没有 HTTP body 部分 r = response_with_headers(headers, 302) + '\r\n' log('r的值', r) return r.encode(encoding='utf-8')
def find_by(cls, **kwargs): """ 用法如下,kwargs 是只有一个元素的 dict u = User.find_by(username='******') """ log('kwargs, ', kwargs) k, v = '', '' for key, value in kwargs.items(): k, v = key, value all = cls.all() for m in all: # getattr(m, k) 等价于 m.__dict__[k] if v == m.__dict__[k]: return m return None
def form(self): """ form 函数用于把 body 解析为一个字典并返回 body 的格式如下 a=b&c=d&e=1 """ # unquote用于把url中一些不符合规范的字符转码,比如浏览器会把url中的空格变成%20 # username=g+u%20a%3F&password= # 转成username=g u&a?&password= body = urllib.parse.unquote(self.body) log('此时的body', body) args = body.split('&') f = {} for arg in args: k, v = arg.split('=') f[k] = v return f
def route_register(request): header = 'HTTP/1.1 200 Good\r\nContent-Type: text/html\r\n' if request.method == 'POST': form = request.form() u = User.new(form) if u.validate_register(): log('这是判断--------') u.save() result = '注册成功<br> <pre>{}</pre>'.format(User.all()) else: result = '用户名或者密码长度必须大于2' else: result = '' body = template('register.html') body = body.replace('{{result}}', result) r = header + '\r\n' + body return r.encode(encoding='utf-8')
def route_message(request): username = current_user(request) if username == '【游客】': log('**debug, route msg 未登陆') if request.method == 'POST': form = request.form() msg = Message.new(form) # msg加入message_list列表 message_list.append(msg) header = 'HTTP/1.1 200 Good\r\nContent-Type: text/html\r\n' body = template('html_basic.html') # <br>是页面上的回车 # Python join() 方法用于将列表中的元素以指定的字符连接生成一个新的字符串 msgs = '<br>'.join([str(m) for m in message_list]) body = body.replace('{{messages}}', msgs) r = header + '\r\n' + body return r.encode(encoding='utf-8')
def request_parse(path): # parse_path用于把path 和 query 分离 path, query = parse_path(path) request.path = path request.query = query log('path and query', path, query) """ 根据 path 调用相应的处理函数 没有处理的 path 会返回 404 """ lis_path = { '/photos': route_static } lis_path.update(route_dict) response = lis_path.get(path, error) return response(request)
def remove(self): models = self.all() if self.__dict__.get('id') is not None: # 有 id 说明已经是存在于数据文件中的数据 # 那么就找到这条数据并替换之 index = -1 log('index的值', index) for i, m in enumerate(models): if m.id == self.id: index = i break # 看看是否找到下标 # 如果找到,就替换掉这条数据 if index > -1: del models[index] # 保存 l = [m.__dict__ for m in models] path = self.db_path() save(l, path)
def run(host='', port=2000): with socket.socket() as s: s.bind((host, port)) while True: s.listen(5) content, addres = s.accept() r = content.recv(1000).decode('utf-8') log('r and addres, {}\n{}'.format(r, addres)) # 防止客户端发送空请求导致程序崩溃 if len(r.split()) < 2: continue path = r.split()[1] # 设置request的 method request.method = r.split()[0] request.body = r.split('\r\n\r\n', 1)[1] log("body的值", request.body) response = request_parse(path) content.sendall(response) content.close()
def save(self): """ 用 all 方法读取文件中的所有 model 并生成一个 list 把 self 添加进去并且保存进文件 """ log('debug save') models = self.all() log('models', models) first_index = 0 if self.__dict__.get('id') is None: # 加上 id if len(models) > 0: log('用 log 可以查看代码执行的走向') # 不是第一个数据 self.id = models[-1].id + 1 else: # 是第一个数据 log('first index', first_index) self.id = first_index models.append(self) else: # 有 id 说明已经是存在于数据文件中的数据 # 那么就找到这条数据并替换之 index = -1 for i, m in enumerate(models): if m.id == self.id: index = i break # 看看是否找到下标 # 如果找到,就替换掉这条数据 if index > -1: models[index] = self # 保存 l = [m.__dict__ for m in models] path = self.db_path() save(l, path)
def template(name): path = 'template/' + name log('path', path) with open(path, 'r', encoding='utf-8') as f: return f.read()