zoukankan      html  css  js  c++  java
  • web 框架

    http协议

     HTTP协议是Hyper Text Transfer Protocol (超文本传输协议)的缩写,是用于从万维网(www:world wide web)服务器传输超文本到本地浏览器的传输协议。

      HTTP协议是一个基于TCP/IP通讯协议来传递数据(HTML 文件,图片文件,查询结果等)

      HTTP协议是一个属于应用层的面向对象的协议,由于其简洁,快捷的方式,使用于分布式超文本信息系统。

      HTTP协议工作于客户端 --- >>> 服务端架构上。

          浏览器作为HTTP客户端通过URL向HTTP服务器WEB服务器发送所有请求。WEB服务器根据接收到的请求后,向客户端发送响应信息。

          

      

    HTTP特点

    1、简单快捷:客户端向服务器请求服务时,只需传送请求方式和路径。请求方式常用的有GET 、HEAD 、POST、每种方式规定了客户端与服务器联系的类型的不同。

    2、灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type 加以标记。

    3、无链接:无连接的含义是限制每一次链接只处理一个请求。服务器处理完客户的请求,并收到客户端的应答后,即断开连接。采用这种方式可以节省传输时间。

    4、无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。

    缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每一次链接传送的数据量增大。另一方便,在服务器不需要先前信息时它的应答就较快。

    HTTP请求协议

    请求协议遵照以下格式:

    请求首行:    # 请求方式    协议和版本,例如:GET /index.html  HTTP/1.1
    
    请求头信息: #  请求头名称:请求头内容,即 key:value 格式 ,例如:Host:localhost
    
    空行   :        #用来与请求体分割开
    
    请求体:        # GET 没有请求体,只有POST有请求体。在 formdata里面

     浏览器发送给服务器的内容就是这个格式的,如果不是这个格式服务器将无法解读!在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 请求数据会暴露在浏览器的地址栏中。

      GET请求常用的操作:

        1、在浏览器的地址栏中直接给出URL,那么就一定是GET请求

        2、点击页面上的超链接也一定是GET请求。

        3、提交表单时,表单默认使用GET请求,但是可以设置为POST

     

      请求头:

         

    1、Host
        请求的web服务器域名地址
     
    2、User-Agent
        HTTP客户端运行的浏览器类型的详细信息。通过该头信息,web服务器可以判断出http请求的客户端的浏览器类型。
    
     3、Accept
        指定客户端能够接收的内容类型,内容类型的先后次序表示客户段接收的先后次序。
    
    4、Accept-Language
        指定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

    HTTP响应协议

    响应格式:

        一般情况下,服务器接收并处理客户端发过来的请求后会返回一个HTTP的响应消息。

    HTTP响应也由四个部分组成,分别是:状体行、消息报头、空行和响应正文。

    HTTP/1.1 200 OK
    Date: Fri, 22 May 2009 06:07:21 GMT
    Content-Type: text/html; charset=UTF-8
    
    <html>
          <head></head>
          <body>
                <!--body goes here-->
          </body>
    </html>
    第一部分:状态行,由HTTP协议版本号, 状态码, 状态消息 三部分组成。

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

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

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

    第三部分:空行,消息报头后面的空行是必须的
    第四部分:响应正文,服务器返回给客户端的文本信息。

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

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

    GET和POST请求的区别

    GET请求
    
    GET /books/?sex=man&name=Professional HTTP/1.1
    Host: www.wrox.com
    User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
    Gecko/20050225 Firefox/1.0.1
    Connection: Keep-Alive
    
    注意最后一行是空行
    POST请求
    
    POST / HTTP/1.1
    Host: www.wrox.com
    User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
    Gecko/20050225 Firefox/1.0.1
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 40
    Connection: Keep-Alive
    
    name=Professional%20Ajax&publisher=Wiley

    1、GET提交,请求的数据会附在URL以后(就是把数据放在HTTP协议头中),以?分割URL和传输数据,多个参数用 & 链接;

        例如:例 如:login.action?name=hyddd&password=idontknow&verify=%E4%BD%A0 %E5%A5%BD。如果数据是英文字母/数字,原样发送,如果是空格,转换为+,如果是中文/其他字符,则直接把字符串用BASE64加密,得出如: %E4%BD%A0%E5%A5%BD,其中%XX中的XX为该符号以16进制表示的ASCII。

      POST提交:把提交的数据放置在HTTP包的包体中。GET提交的数据会在地址栏中显示出来,而POST提交,地址栏不会改变。

    2、传输数据的大小:首先声明:HTTP协议没有对传输的数据大小进行限制,HTTP协议规范也没有对URL长度进行限制。

          而在实际开发中存在的限制主要有:     

    GET:特定浏览器和服务器对URL长度有限制,例如 IE对URL长度的限制是2083字节(2K+35)。对于其他浏览器,如Netscape、FireFox等,理论上没有长度限制,其限制取决于操作系 统的支持。

    因此对于GET提交时,传输数据就会受到URL长度的 限制。

    POST:由于不是通过URL传值,理论上数据不受 限。但实际各个WEB服务器会规定对post提交数据大小进行限制,Apache、IIS6都有各自的配置。

    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上,如果页面可以被缓存或者其他人可以访问这台机器,就可以从历史记录获得该用户的账号和密码.

    web应用

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

    import socket
    
    
    def handle_request(client):
        
        buf = client.recv(1024)
        client.send("HTTP/1.1 200 OK/r/n/r/n".encode("utf-8"))
        client.send("<h1 style='color:red'> Hello ,eggtea </h1>".encode("utf-8"))
        
        
     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()

    最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。

    如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。

          正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口,让我们专心用Python编写Web业务。

    DIY一个自己的web框架

    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")
        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("&")
            # _,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()

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

        

     

     

     

     

  • 相关阅读:
    C#利用反射动态调用类及方法
    系统程序监控软件
    SQL server 2008 安装和远程访问的问题
    sql server 创建临时表
    IIS 时间问题
    windows 2008 安装 sql server 2008
    sql server xml nodes 的使用
    Window 7sp1 安装vs2010 sp1 打开xaml文件崩溃
    CSS资源网址
    Could not load type 'System.ServiceModel.Activation.HttpModule' from assembly 'System.ServiceModel, Version=3.0.0.0
  • 原文地址:https://www.cnblogs.com/liushubao/p/8370879.html
Copyright © 2011-2022 走看看