Ejemplo n.º 1
0
def make_response(request, headers=None):
    """构造响应报文"""
    # 默认状态码为 200
    status = 200
    # 处理静态资源请求
    if request.path.startswith('/static'):
        route, methods = routes.get('/static')
    else:
        route, methods = routes.get(request.path)

    # 如果请求方法不被允许返回 405 状态码
    if request.method not in methods:
        status = 405
        data = 'Method Not Allowed'
    else:
        # 请求首页时 route 实际上就是我们在 controllers.py 中定义的 index 视图函数
        data = route(request)

    # 如果返回结果为 Response 对象,直接获取响应报文
    if isinstance(data, Response):
        response_bytes = bytes(data)
    else:
        # 返回结果为字符串,需要先构造 Response 对象,然后再获取响应报文
        response = Response(data, headers=headers, status=status)
        response_bytes = bytes(response)

    logger(f'response_bytes: {response_bytes}')
    return response_bytes
Ejemplo n.º 2
0
def register(request):
    """注册

    Args:
        request: 请求对象

    Returns:
        GET 请求:
            返回注册页面
        POST 请求:
            注册成功将重定向到登录页
            注册失败返回失败原因提示短语
    """
    if request.method == 'POST':
        # 获取表单中的用户名和密码
        form = request.form
        logger(f'form: {form}')
        username = form.get('username')
        raw_password = form.get('password')

        # 验证用户名和密码是否合法
        if not username or not raw_password:
            return '无效的用户名或密码'.encode('utf-8')
        user = User.find_by(username=username, ensure_one=True)
        if user:
            return '用户名已存在'.encode('utf-8')

        # 对密码进行散列计算,创建并保存用户信息
        password = User.generate_password(raw_password)
        user = User(username=username, password=password)
        user.save()
        # 注册成功后重定向到登录页面
        return redirect('/login')

    return render_template('auth/register.html')
Ejemplo n.º 3
0
def edit(request):
    """编辑 todo 视图函数"""
    # 处理 POST 请求
    if request.method == 'POST':
        form = request.form
        logger(f'form: {form}')

        id = int(form.get('id', -1))
        content = form.get('content')

        if id != -1 and content:
            todo = Todo.get(id=id)
            if todo:
                todo.content = content
                todo.save()
        return redirect('/index')

    # 处理 GET 请求
    args = request.args
    logger(f'args: {args}')

    id = int(args.get('id', -1))
    if id == -1:
        return redirect('/index')

    todo = Todo.get(id=id)
    if not todo:
        return redirect('/index')

    context = {
        'todo': todo,
    }
    return render_template('todo/edit.html', **context)
Ejemplo n.º 4
0
def current_user(request):
    """获取当前登录用户

    Args:
        request: 请求对象

    Returns:
        如果已登录,返回当前登录用户对象,否则返回 None
    """
    # 从 Cookie 中获取 session_id
    cookies = request.cookies
    logger(f'cookies: {cookies}')
    session_id = cookies.get('session_id')

    # 查找 Session 并验证其是否过期
    session = Session.get(session_id)
    if not session:
        return None
    if session.is_expired():
        session.delete()
        return None

    # 查找当前登录用户
    user = User.get(session.user_id)
    if not user:
        return None
    return user
Ejemplo n.º 5
0
def process_connection(client):
    """处理客户端请求

    Args:
        client: 客户端请求对象

    Returns:
        None
    """
    request_bytes = b''
    while True:
        chunk = client.recv(BUFFER_SIZE)
        request_bytes += chunk
        if len(chunk) < BUFFER_SIZE:
            break

    # 请求报文
    request_message = request_bytes.decode('utf-8')
    logger(f'request_message: {request_message}')

    # 解析请求报文
    request = Request(request_message)
    try:
        # 根据请求报文构造响应报文
        response_bytes = make_response(request)
    except Exception as e:
        logger(e)
        # 返回给用户 500 页面
        response_bytes = bytes(errors[500]())
    # 返回响应
    client.sendall(response_bytes)

    # 关闭连接
    client.close()
Ejemplo n.º 6
0
def new(request):
    """新建 todo 视图函数"""
    form = request.form
    logger(f'form: {form}')

    content = form.get('content')
    if content:
        todo = Todo(content=content)
        todo.save()
    return redirect('/index')
Ejemplo n.º 7
0
def delete(request):
    """删除 todo 视图函数"""
    form = request.form
    logger(f'form: {form}')

    id = int(form.get('id', -1))
    if id != -1:
        todo = Todo.get(id=id)
        if todo:
            todo.delete()
    return redirect('/index')
Ejemplo n.º 8
0
def main():
    """入口函数"""
    with socket.socket() as s:
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind((HOST, PORT))
        s.listen(5)
        logger(f'running on http://{HOST}:{PORT}')

        while True:
            client, address = s.accept()
            logger(f'client address: {address}')
            # 创建新的线程来处理客户端连接
            t = threading.Thread(target=process_connection, args=(client, ))
            t.start()
Ejemplo n.º 9
0
def edit(request):
    """编辑 todo 视图函数

    Args:
        request: 请求对象

    Returns:
        GET 请求:
            返回编辑页面
        POST 请求:
            更新当前编辑项,重定向到首页
    """
    if request.method == 'POST':
        form = request.form
        logger(f'form: {form}')

        id = int(form.get('id', -1))
        content = form.get('content')

        if id != -1 and content:
            user = current_user(request)
            if user:
                todo = Todo.find_by(id=id, user_id=user.id, ensure_one=True)
                if todo:
                    todo.content = content
                    todo.save()
        return redirect('/index')

    args = request.args
    logger(f'args: {args}')

    id = int(args.get('id', -1))
    if id == -1:
        return redirect('/index')

    user = current_user(request)
    if not user:
        return redirect('/index')

    todo = Todo.find_by(id=id, user_id=user.id, ensure_one=True)
    if not todo:
        return redirect('/index')

    context = {
        'todo': todo,
    }
    return render_template('todo/edit.html', **context)
Ejemplo n.º 10
0
def login(request):
    """登录

    Args:
        request: 请求对象

    Returns:
        GET 请求:
            返回登录页面
        POST 请求:
            登录成功将重定向到首页
            登录失败返回失败原因提示短语
    """
    # 如果用户已经登录,直接重定向到首页
    if current_user(request):
        return redirect('/index')

    if request.method == 'POST':
        message = '用户名或密码不正确'.encode('utf-8')

        # 获取表单中的用户名和密码
        form = request.form
        logger(f'form: {form}')
        username = form.get('username')
        raw_password = form.get('password')

        # 验证用户名和密码是否正确
        if not username or not raw_password:
            return message
        user = User.find_by(username=username, ensure_one=True)
        if not user:
            return message
        password = user.password
        if not User.validate_password(raw_password, password):
            return message

        # 创建 Session 并将 session_id 写入 Cookie 实现登录
        session = Session(user_id=user.id)
        session.save()
        cookies = {
            'session_id': session.id,
        }
        return redirect('/index', cookies=cookies)

    return render_template('auth/login.html')
Ejemplo n.º 11
0
def new(request):
    """新建 todo 视图函数

    Args:
        request: 请求对象

    Returns:
        重定向到首页
    """
    form = request.form
    logger(f'form: {form}')

    content = form.get('content')
    if content:
        user = current_user(request)
        if user:
            todo = Todo(content=content, user_id=user.id)
            todo.save()
    return redirect('/index')
Ejemplo n.º 12
0
def delete(request):
    """删除 todo 视图函数

    Args:
        request: 请求对象

    Returns:
        删除当前项,重定向到首页
    """
    form = request.form
    logger(f'form: {form}')

    id = int(form.get('id', -1))
    if id != -1:
        user = current_user(request)
        if user:
            todo = Todo.find_by(id=id, user_id=user.id, ensure_one=True)
            if todo:
                todo.delete()
    return redirect('/index')
Ejemplo n.º 13
0
def process_connection(client):
    """处理客户端请求"""
    # 接收请求报文数据
    request_bytes = b''
    while True:
        chunk = client.recv(BUFFER_SIZE)
        request_bytes += chunk
        if len(chunk) < BUFFER_SIZE:
            break

    # 请求报文
    request_message = request_bytes.decode('utf-8')
    logger(f'request_message: {request_message}')

    # 解析请求报文,构造请求对象
    request = Request(request_message)
    # 根据请求对象构造响应报文
    response_bytes = make_response(request)
    # 返回响应
    client.sendall(response_bytes)

    # 关闭连接
    client.close()