服务器接收用户注册信息教程

第一次数据请求,服务器接收用户注册信息

本小节将是我们编写服务器端代码的开始。现在假设有这样一个 App(见下图),用户需要通过该界面提交注册信息。服务器端在接收到客户端的注册请求后,返回注册成功信息,并将该用户写入数据库表用户信息中。

客户端模拟

考虑到本小册讲解的是服务器端,这里不作 App 端的介绍,我们将使用 HTTP 发包工具来模拟上面的 App 注册信息的提交。

HTTP 发包工具:Getman

约定服务器端 HTTP server 的端口号为 8000,服务器端和客户端定义的请求是 /users/regist,那么完整的 URL 为 http://150.109.33.132:8000/users/regist?(请用自己的云虚拟机 IP 替换其中的 IP)。

参数为手机号(phone)、密码(password)及验证码(code),参数放入 HTTP 的 body 中,具体为:
{"phone":"18866668888","password":"demo123456","code":"123456"}

注:

  1. 确保服务器端 8000 端口已放通;
  1. 在实际的项目中,密码不会明文的传输,一般会在客户端先使用 md5 进行加密,服务器端存储的也是加密后的密码字符串。本小册作为学习示例,将使用明文讲解。

发包器模拟如下:

客户端的请求至此已初步完成,现在,服务器端接收到客户端这个请求后,将如何处理呢?

服务器端处理

调用逻辑

客户端以 POST 的方式,发送注册请求至服务器端,请求进入服务器端的 main.py 后,将调用 url_router 转发到 users_url.py 中,在 users_urls.py 中,对应的 URL 将调用 users_views.pyRegistHandle 类, RegistHandle 为真正的代码处理逻辑,在校验用户信息正确的情况下,返回 JSON 格式的注册成功信息给客户端。

编写服务器端入口函数

main.py 是 Tornado 作为 HTTP 服务器的统一入口,根据前面的约定,Tornado 对外服务的端口号为 8000。

复制代码
#! /usr/bin/python3
# -*- coding:utf-8 -*-
# Author: demo
# Email: demo@demo.com
# Version: demo

import tornado.ioloop
import tornado.web
import os
import sys
from tornado.options import define,options

class Application(tornado.web.Application):
    def __init__(self):
        #定义 Tornado 服务器的配置项,如 static/templates 目录位置、debug 级别等
        settings = dict(
            debug=True,
            static_path=os.path.join(os.path.dirname(__file__),"static"),
            template_path=os.path.join(os.path.dirname(__file__), "templates")
        )
        tornado.web.Application.__init__(self, **settings)
 
 
 
if __name__ == '__main__':
    print ("Tornado server is ready for service\r")
    tornado.options.parse_command_line()
    Application().listen(8000, xheaders=True)
    tornado.ioloop.IOLoop.instance().start()

保存 main.py 代码后,在服务器端运行此段代码

此时再次点击 HTTP 发包模拟器发送注册信息

URL: http://150.109.33.132:8000/users/regist?

入参:{"phone":"18866668888","password":"demo123456","code":"123456"}

再次查看服务器端

此条打印说明,客户端的 HTTP 请求已到达服务器,服务器接收成功但处理失败了,原因为找不到路径 /users/regist。下面在服务器端编写针对 /users/regist 的处理代码。

编写路由转发

首先,服务器端从 main.py 收到客户端的请求后,需要将其转发给对应的处理模块。进入 common 目录,创建 url_router.py 文件

url_router.py 中输入如下代码。

复制代码
#!/usr/bin/python3
# -*- coding:utf-8 -*-

from __future__ import unicode_literals
from importlib import import_module

def include(module):
    '''根据传入的字符串,调用相应的模块,如 module 为字符串 regist 时,
    调用views.users.users_views.RegistHandle 模块
    '''
    res = import_module(module)
    urls = getattr(res, 'urls', res)
    return urls
    
    
def url_wrapper(urls):
    '''拼接请求 url,调用对应的模块,如拼接 users 和 regist 成 url /users/regist,
    调用 views.users.users_views.RegistHandle 模块
    '''
    wrapper_list = []
    for url in urls:
        path, handles = url
        if isinstance(handles, (tuple, list)):
            for handle in handles:
                #分离获取字符串(如regist)和调用类(如views.users.users_views.RegistHandle)
                pattern, handle_class = handle
                #拼接url,新的url调用模块
                wrap = ('{0}{1}'.format(path, pattern), handle_class)
                wrapper_list.append(wrap)
        else:
            wrapper_list.append((path, handles))
    return wrapper_list

接下来修改 main.py,调用 url_router.py 将用户请求的路径转发给对应的请求模块。

增加如下几行,从 common 目录的 url_router 导入所需函数( from common.url_router import include, url_wrapper),并在 Application 的类中,拼接转发路由。

完成后的代码如下:

复制代码
#! /usr/bin/python3
# -*- coding:utf-8 -*-
# Author: demo
# Email: demo@demo.com
# Version: demo

import tornado.ioloop
import tornado.web
import os
import sys
from tornado.options import define,options
from common.url_router import include, url_wrapper
from tornado.options import define,options


class Application(tornado.web.Application):
    def __init__(self):
        handlers = url_wrapper([
        (r"/users/", include('views.users.users_urls'))
        ])
        #定义 Tornado 服务器的配置项,如 static/templates 目录位置,debug 级别等
        settings = dict(
            debug=True,
            static_path=os.path.join(os.path.dirname(__file__),"static"),
            template_path=os.path.join(os.path.dirname(__file__), "templates")
        )
        tornado.web.Application.__init__(self, handlers, **settings)
 

if __name__ == '__main__':
    print ("Tornado server is ready for service\r")
    tornado.options.parse_command_line()
    Application().listen(8000, xheaders=True)
    tornado.ioloop.IOLoop.instance().start()

至此,main.py 的路由转发已完成,接下来将编写真正的处理模块。

进入 views 目录,创建 users 目录,该目录将存放所有跟用户信息处理相关的代码。在该目录下,创建 users_urls.pyusers_views.py

其中,users_urls.py 处理针对 users 相关的路由及调用类之间的路由,users_views.py 为真正的逻辑处理。在 users_urls.py 中输入如下代码:

复制代码
#! /usr/bin/python3
# -*- coding:utf-8 -*-


from __future__ import unicode_literals
from .users_views import (
    RegistHandle
)

urls = [
    #从 /users/regist 过来的请求,将调用 users_views 里面的 RegistHandle 类
    (r'regist', RegistHandle)
]

users_views.py 文件中,输入如下代码:

复制代码
#! /usr/bin/python3
# -*- coding:utf-8 -*-

import tornado.web
from tornado.escape import json_decode

# 从commons中导入http_response方法
from common.commons import (
    http_response,
)

# 从配置文件中导入错误码
from conf.base import (
    ERROR_CODE,
)
 
class RegistHandle(tornado.web.RequestHandler):
    """handle /user/regist request
    :param phone: users sign up phone
    :param password: users sign up password
    :param code: users sign up code, must six digital code
    """
        
    def post(self):
        try:
            #获取入参
            args = json_decode(self.request.body)
            phone = args['phone']
            password = args['password']
            verify_code = args['code']
        except:
            # 获取入参失败时,抛出错误码及错误信息
            http_response(self, ERROR_CODE['1001'], 1001)
            return 
            
        # 处理成功后,返回成功码"0"及成功信息"ok"
        http_response(self, ERROR_CODE['0'], 0)

users_views.py 中看到,我们从公共方法库(commons)中导入了方法,并从配置文件中导入了错误码定义。接下来编写 commonsbase 配置文件。

进入 common 目录,并创建 commons.py 文件,在 commons.py 中输入如下代码:

复制代码
#! /usr/bin/python3
# -*- coding:utf-8 -*-

import json

def http_response(self, msg, code):
    self.write(json.dumps({"data": {"msg": msg, "code": code}}))

        
if __name__ == "__main__":
   http_response()

在 conf 目录下,创建 base.py 文件:

base.py 文件中,输入如下代码:

复制代码
#! /usr/bin/python3
# -*- coding:utf-8 -*-

ERROR_CODE = {
    "0": "ok",
    #Users error code
    "1001": "入参非法"
}

至此,我们已经完成了基本的用户注册以及服务器端处理逻辑代码,重新运行 main.py,查看是否启动正常。

现在再从 HTTP 发包模拟器

此时看到返回的 JSON 消息已成功。

再次查看服务器端,此时控制台打印的 log 提示 HTTP 200,表示该条 URL 请求已正确处理并返回。

假如此时 HTTP 发包模拟器入参少了 code 参数,将提示错误信息。

至此,我们第一次客户端与服务器端的数据请求及回复已讲解完毕。完成后的目录结构及文件如下。

代码下载

到目前为止,服务器端代码如下:
demo6

小结

本小节讲解了客户端与服务器端的第一次数据请求及回复。代码比较简单,重点在于理解其中的 URL 路由转发,以达到触类旁通的效果。代码还有很多待完善的地方,如增加 log 管理,进一步抽象类和方法等。下一小节,我们将为代码加入 log 管理。

相关推荐
笨鸟先飞,勤能补拙3 小时前
AI 赋能网络安全:技术全景、成熟度评估与实战案例
人工智能·python·安全·web安全·网络安全·sqlite·github
长和信泰光伏储能4 小时前
京津冀光伏发电:绿色能源的未来之路
python·能源
浦信仿真大讲堂5 小时前
从重复操作到自动化闭环:如何让 CST 与 Python 真正协同起来
python·自动化·cst·仿真软件·达索软件
Gu Gu Study5 小时前
ScoutLoop开放域深度研究引擎(agent的初步设计想法)
人工智能·python
卷无止境6 小时前
写代码这件事,到底该讲究点什么?
后端·python
卷无止境6 小时前
循环复杂度到底在算什么,Python 代码怎么才能写得让人一看就懂
后端·python
lpfasd1236 小时前
MediaCrawler 项目深度分析
chrome·python·chrome devtools
Dxy12393102167 小时前
Python项目打包成EXE完整教程(PyInstaller实战避坑)
开发语言·python
bamb007 小时前
一个项目带你入门AI应用开发01
python
0566467 小时前
Python康复训练——常用标准库
开发语言·python·学习