zoukankan      html  css  js  c++  java
  • Web框架的应用

    从今天开始,我们将要学习有关Web框架的一些内容,在学习之前先来学习一下http协议,即基于http是如何通信的。

    http

    概要:http是基于tcp/ip通信协议来传输数据的。

    优点:

    1.简单快速

    2.灵活

    3.无连接

    4.无状态

    http请求协议

    http中有两种请求方式,一种是get请求,一种是post请求

    请求协议必须遵循以下格式:

    请求首行:    //请求方式,请求协议,路径和版本
    请求头信息: //请求头的内容,即为key:value格式,例如:Host:localhost
    空行           //用来区分请求头与请求内容
    请求体        //get没有请求体,post有请求体

    浏览器发送给服务端的请求一般都为这种格式,如果不是这种格式将无法解读,http协议中有很多请求方法,其中最为常见的就是get和post方法。

    get请求

    GET /562f25980001b1b106000338.jpg HTTP/1.1
    Host    img.mukewang.com
    User-Agent    Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36
    Accept    image/webp,image/*,*/*;q=0.8
    Referer    http://www.imooc.com/
    Accept-Encoding    gzip, deflate, sdch
    Accept-Language    zh-CN,zh;q=0.8

    http默认的请求方法是get请求

    get请求方法的特点:

    (1)没有请求体

     (2)请求的数据量有限

    (3)get请求数据会暴露在地址栏中,数据不安全。

    get请求常用的三种操作方式:

    GET请求常用的操作:
    1. 在浏览器的地址栏中直接给出URL,那么就一定是GET请求
    2. 点击页面上的超链接也一定是GET请求
    3. 提交表单时,表单默认使用GET请求,但可以设置为POST

    get请求的请求头信息

    1、Host
    
    请求的web服务器域名地址
    
    2、User-Agent
    
    HTTP客户端运行的浏览器类型的详细信息。通过该头部信息,web服务器可以判断出http请求的客户端的浏览器的类型。
    
    3、Accept
    
    指定客户端能够接收的内容类型,内容类型的先后次序表示客户都接收的先后次序
    
    4、Accept-Lanuage
    
    指定HTTP客户端浏览器用来展示返回信息优先选择的语言
    
    5、Accept-Encoding
    
    指定客户端浏览器可以支持的web服务器返回内容压缩编码类型。表示允许服务器在将输出内容发送到客户端以前进行压缩,以节约带宽。
    而这里设置的就是客户端浏览器所能够支持的返回压缩格式。
    
    6、Accept-Charset
    
    HTTP客户端浏览器可以接受的字符编码集
    
    7、Content-Type
    
    显示此HTTP请求提交的内容类型。一般只有post提交时才需要设置该属性
    
    有关Content-Type属性值有如下两种编码类型:
    
    (1)“application/x-www-form-urlencoded”: 表单数据向服务器提交时所采用的编码类型,默认的缺省值就是“application/x-www-form-urlencoded”。
         然而,在向服务器发送大量的文本、包含非ASCII字符的文本或二进制数据时这种编码方式效率很低。
    
    (2)“multipart/form-data”: 在文件上载时,所使用的编码类型应当是“multipart/form-data”,它既可以发送文本数据,也支持二进制数据上载。
    
    当提交为表单数据时,可以使用“application/x-www-form-urlencoded”;当提交的是文件时,就需要使用“multipart/form-data”编码类型。
    请求头信息

    post请求

    POST / HTTP1.1
    Host:www.wrox.com
    User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
    Content-Type:application/x-www-form-urlencoded
    Content-Length:40
    Connection: Keep-Alive
    
    name=Professional%20Ajax&publisher=Wiley

    GET和POST的区别

      1. GET提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连,如EditPosts.aspx?name=test1&id=123456. POST方法是把提交的数据放在HTTP包的Body中.

      2. GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制.

      3. GET方式需要使用Request.QueryString来取得变量的值,而POST方式通过Request.Form来获取变量的值。

      4. GET方式提交数据,会带来安全问题,比如一个登录页面,通过GET方式提交数据时,用户名和密码将出现在URL上,如果页面可以被缓存或者其他人可以访问这台机器,就可以从历史记录获得该用户的账号和密码.

    http响应协议

    响应格式:

    一般情况下,服务器接收并做出响应

    http响应也由四个部分组成:状态行、消息报头、空行、响应正文(html页面)

    第一部分:状态行,由HTTP协议版本号, 状态码, 状态消息 三部分组成。

    第一行为状态行,(HTTP/1.1)表明HTTP版本为1.1版本,状态码为200,状态消息为(ok)

    第二部分:消息报头,用来说明客户端要使用的一些附加信息

    第二行和第三行为消息报头,
    Date:生成响应的日期和时间;Content-Type:指定了MIME类型的HTML(text/html),编码类型是UTF-8

    有关Content-Type属性值有如下两种编码类型:
    
    (1)“application/x-www-form-urlencoded”: 表单数据向服务器提交时所采用的编码类型,默认的缺省值就是“application/x-www-form-urlencoded”。
    然而,在向服务器发送大量的文本、包含非ASCII字符的文本或二进制数据时这种编码方式效率很低。 (2)“multipart/form-data”: 在文件上载时,所使用的编码类型应当是“multipart/form-data”,它既可以发送文本数据,也支持二进制数据上载。 当提交为表单数据时,可以使用“application/x-www-form-urlencoded”;当提交的是文件时,就需要使用“multipart/form-data”编码类型。
    第三部分:空行,消息报头后面的空行是必须的
    第四部分:响应正文,服务器返回给客户端的文本信息。

    空行后面的html部分为响应正文。

    状态代码有三位数字组成,第一个数字定义了响应的类别,共分五种类别:
    1xx:指示信息--表示请求已接收,继续处理
    2xx:成功--表示请求已被成功接收、理解、接受
    3xx:重定向--要完成请求必须进行更进一步的操作
    4xx:客户端错误--请求有语法错误或请求无法实现
    5xx:服务器端错误--服务器未能实现合法的请求
    
    常见状态码:
    OK                        //客户端请求成功
    Bad Request               //客户端请求有语法错误,不能被服务器所理解
    Unauthorized              //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用 
    Forbidden                 //服务器收到请求,但是拒绝提供服务
    Not Found                 //请求资源不存在,eg:输入了错误的URL
    Internal Server Error     //服务器发生不可预期的错误
    Server Unavailable        //服务器当前不能处理客户端的请求,一段时间后可能恢复正常
    响应状态码

     web应用与web框架

    相对于所有的web应用来说,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。

    import socket
    
    def handle_request(client):
    
        buf = client.recv(1024)
        client.send("HTTP/1.1 200 OK
    
    ".encode("utf8"))
        client.send("<h1 style='color:red'>Hello, yuan</h1>".encode("utf8"))
    
    def main():
    
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.bind(('localhost',8001))
        sock.listen(5)
    
        while True:
            connection, address = sock.accept()
            handle_request(connection)
            connection.close()
    
    if __name__ == '__main__':
    
        main()

    wsgiref模块

    from wsgiref.simple_server import make_server
    
    
    def application(environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/html')])
        return [b'<h1>Hello, web!</h1>']
    
    
    httpd = make_server('', 8080, application)
    
    print('Serving HTTP on port 8000...')
    # 开始监听HTTP请求:
    httpd.serve_forever()

     其中 make_sever中存放的数据为make_sever('127.0.0.1',8080,自定义的函数)

    eg: def  application(environ,start_respon):

        pass

    environ中存放所有的请求数据,start_respon中存放请求头

    注:对比socketSever模块

    接下来写一个自己的web框架

    manage.py(启动文件)

    from wsgiref.simple_server import make_server
    
    #  request            response
    
    
    from app01.views import *
    
    from app01 import urls
    
    
    def routers():
    
        URLpattern=urls.URLpattern
    
        return URLpattern
    
    
    def applications(environ,start_response):
    
        path=environ.get("PATH_INFO")   //PATH_INFO后存放具体的路径
    PATH_INFO
    
    
    PATH_INFO
    print("path",path) start_response('200 OK', [('Content-Type', 'text/html'),('Charset', 'utf8')]) urlpattern=routers() func=None for item in urlpattern: if path==item[0]: func=item[1] break if func: return [func(environ)] else: return [b"<h1>404!<h1>"] # return [b"<h1>hello world<h1>"] if __name__ == '__main__': t=make_server("",8810,applications) print("server is working...") t.serve_forever()

    urls(存放路径与函数的映射关系)

    from app01.views import *
    
    
    URLpattern = (
        ("/login/", login),
    )

    views(和函数有关)

    import pymysql
    
    from urllib.parse import parse_qs
    
    
    def login(request):
    
        if request.get("REQUEST_METHOD")=="POST":
            print("+++++",request)
    
    
            #当请求方式是GET时
            # user_union,pwd_union=request.get("QUERY_STRING").split("&")   #QUERY_STRING中的数据为()
            # _,user=user_union.split("=")
            # _,pwd=pwd_union.split("=")
    
            # 环境变量 CONTENT_LENGTH 可能是空值 或者 值丢失   
            try:
                request_body_size = int(request.get('CONTENT_LENGTH', 0))
            except (ValueError):
                request_body_size = 0
            # 当请求方式是POST时, 变量将会被放在存在域wsgi.input文件中的HTTP请求信息中, 由WSGI 服务器一起发送.
            request_body = request['wsgi.input'].read(request_body_size)
            d = parse_qs(request_body)
    
    
            user=d.get(b"user")[0].decode("utf8")
            pwd=d.get(b"pwd")[0].decode("utf8")
    
            print("user",user,pwd)
    
    
            #连接数据库
            conn = pymysql.connect(host='',port= 3306,user = 'root',passwd='',db='s6') #db:库名
            #创建游标
            cur = conn.cursor()
    
            SQL="select * from userinfo2 WHERE NAME ='%s' AND PASSWORD ='%s'"%(user,pwd)
    
            cur.execute(SQL)
    
            if cur.fetchone():
    
                f=open("templates/backend.html","rb")
    
                data=f.read()
                data=(data.decode("utf8"))%user
                return data.encode("utf8")
    
            else:
                 return b"user or pwd is wrong"
    
    
        else:
            f = open("templates/login.html", "rb")
    
            data = f.read()
            f.close()
    
            return data

    models(和数据库有关)

    import pymysql
    
    
    import pymysql
    #连接数据库
    conn = pymysql.connect(host='',port= 3306,user = 'root',passwd='',db='s6') #db:库名
    #创建游标
    cur = conn.cursor()
    
    # sql='''
    # create table userinfo2(
    #         id INT PRIMARY KEY ,
    #         name VARCHAR(32) ,
    #         password VARCHAR(32)
    # )
    #
    # '''
    #
    # cur.execute(sql)
    #
    # cur.executemany("insert into userinfo2 values(%s,%s,%s)", [(1,"yuan","123"),
    #                                                           (2,"alex","456"),
    #                                                           (3,"egon","789")])
    
    
    cur.execute("select * from userinfo2 WHERE NAME='yuan' AND PASSWORD ='123'")
    #提交
    conn.commit()
    #关闭指针对象
    cur.close()
    #关闭连接对象
    conn.close()
  • 相关阅读:
    Java 第十一届 蓝桥杯 省模拟赛 洁净数
    Java 第十一届 蓝桥杯 省模拟赛 第十层的二叉树
    Java 第十一届 蓝桥杯 省模拟赛 第十层的二叉树
    Java 第十一届 蓝桥杯 省模拟赛 第十层的二叉树
    Java 第十一届 蓝桥杯 省模拟赛 70044与113148的最大公约数
    Java 第十一届 蓝桥杯 省模拟赛 70044与113148的最大公约数
    20. Valid Parentheses
    290. Word Pattern
    205. Isomorphic Strings
    71. Simplify Path
  • 原文地址:https://www.cnblogs.com/moning/p/7701393.html
Copyright © 2011-2022 走看看