浅析HTTP中POST和GET区别并用Python模拟其响应和请求

来源:互联网 发布:win10极速系统优化 编辑:程序博客网 时间:2024/05/04 09:04

最近在几周在做手游崩溃信息收集和上传,拿到崩溃信息后,使用的是HTTP的POST方法上传到公司共用的服务器的,因此做简单总结。本文首先简单介绍了HTTP协议,主要说明了POST方法和GET方法的区别;然后用Python实现了 对POST方法和GET方法的响应;最后用Python模拟了POST方法和GET方法的请求。

HTTP协议简介

    HTTP是Hyper Text Transfer Protocol(超文本传输协议)的缩写,简单来说它是一个应用层的协议,它允许将超文本标记语言(HTML)文档从Web服务器传送到客户端的浏览器。HTTP是一个无状态的协议,即同一个客户端的这次请求和上次请求是没有对应关系,对http服务器来说,它并不知道这两个请求来自同一个客户端,为了解决这个问题,Web程序引入了Cookie机制来维护状态。
    HTTP协议通常基于TCP协议来实现的,有时也基于于TLS或SSL协议(这个两个协议也是基于TCP协议来说实现)来实现,这个时候,就成了我们常说的HTTPS,每次HTTP操作都至少有下面几个过程:首先客户端与服务端建立连接;建立建立后,客户端按照协议格式发送请求;服务端接到请求后,同样按照某个格式返回响应数据;最后客户端与服务端断开连接。
    通常我们打开一个网页,需要浏览器发送多次请求,因为一个网页中可能引用了其他文件,比如图片等文件,这时候浏览器会自动再次发送请求去获取图片等数据,直到网页上的数据被完全显示出来。

POST和GET区别

    HTTP协议定义了很多与服务器交互的方法,最基本的有4种,分别是GET,POST,PUT,DELETE. 一个URL地址用于描述一个网络上的资源,而HTTP中的GET, POST, PUT, DELETE就对应着对这个资源的查,改,增,删4个操作,其中最常见请求方式是GET和POST,并且现在浏览器一般只支持GET和POST方法。GET一般用于获取/查询资源信息,而POST一般用于更新资源信息,他们之间主要区别如下:
    1)根据HTTP规范,GET用于信息获取,而且应该是安全的和幂等的,这里安全是指该操作用于获取信息而非修改信息,幂等是指对同一URL的多个请求应该返回同样的结果(这一点在实质实现时,可能并不满足);
POST表示可能修改变服务器上的资源的请求。
    2)GET请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,参数之间以&相连,如果数据是英文字母/数字,原样发送,如果是空格,转换为+,如果是中文/其他字符,
则直接把字符串用BASE64编码;POST把提交的数据则放置在是HTTP包的包体中。
    3)因为GET是通过URL提交数据,那么GET可提交的数据量就跟URL的长度有直接关系,理论上URL长度是没有限制的,即HTTP协议没有规定URL的长度,但在实质中,特定的浏览器可能对这个长度做了限制;理论上POST也是没有大小限制的,HTTP协议规范也没有进行大小限制,但在服务端通常会对这个大小做一个限制,当然这个限制比GET宽松的多,即使用POST可以提交的数据量比GET大得多。
    最后,网上有人说,POST的安全性要比GET的安全性高,实质上POST跟GET都是明文传输,这可以通过类似WireShark工具看到。总之,Get是向服务器发索取数据的一种请求,而Post是向服务器提交数据的一种请求。

POST和GET方法响应Python实现

    下面代码实现对POST方法和GET方法的响应:

[python] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #!/usr/bin/python  
  2. #coding=utf8  
  3. """ 
  4. import sys 
  5. reload(sys) 
  6. sys.setdefaultencoding('utf-8') 
  7. """  
  8. from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer  
  9. from os import curdir, sep  
  10. import cgi  
  11. import logging  
  12. import time  
  13.   
  14. PORT_NUMBER = 8080  
  15. RES_FILE_DIR = "."  
  16.   
  17. class myHandler(BaseHTTPRequestHandler):  
  18.       
  19.     def do_GET(self):  
  20.         if self.path=="/":  
  21.             self.path="/index_example3.html"  
  22.   
  23.         try:  
  24.             #根据请求的文件扩展名,设置正确的mime类型  
  25.             sendReply = False  
  26.             if self.path.endswith(".html"):  
  27.                 mimetype='text/html'  
  28.                 sendReply = True  
  29.             if self.path.endswith(".jpg"):  
  30.                 mimetype='image/jpg'  
  31.                 sendReply = True  
  32.             if self.path.endswith(".gif"):  
  33.                 mimetype='image/gif'  
  34.                 sendReply = True  
  35.             if self.path.endswith(".js"):  
  36.                 mimetype='application/javascript'  
  37.                 sendReply = True  
  38.             if self.path.endswith(".css"):  
  39.                 mimetype='text/css'  
  40.                 sendReply = True  
  41.   
  42.             if sendReply == True:  
  43.                 #读取相应的静态资源文件,并发送它  
  44.                 f = open(curdir + sep + self.path, 'rb')  
  45.                 self.send_response(200)  
  46.                 self.send_header('Content-type',mimetype)  
  47.                 self.end_headers()  
  48.                 self.wfile.write(f.read())  
  49.                 f.close()  
  50.             return  
  51.   
  52.         except IOError:  
  53.             self.send_error(404,'File Not Found: %s' % self.path)  
  54.   
  55.     def do_POST(self):  
  56.         logging.warning(self.headers)  
  57.         form = cgi.FieldStorage(  
  58.             fp=self.rfile,  
  59.             headers=self.headers,  
  60.             environ={'REQUEST_METHOD':'POST',  
  61.                     'CONTENT_TYPE':self.headers['Content-Type'],  
  62.                     })  
  63.   
  64.         file_name = self.get_data_string()  
  65.         path_name = '%s/%s.log' % (RES_FILE_DIR,file_name)  
  66.         fwrite = open(path_name,'a')  
  67.   
  68.         fwrite.write("name=%s\n" % form.getvalue("name",""))  
  69.         fwrite.write("addr=%s\n" % form.getvalue("addr",""))  
  70.         fwrite.close()  
  71.   
  72.         self.send_response(200)  
  73.         self.end_headers()  
  74.         self.wfile.write("Thanks for you post")  
  75.   
  76.     def get_data_string(self):  
  77.         now = time.time()  
  78.         clock_now = time.localtime(now)  
  79.         cur_time = list(clock_now)  
  80.         date_string = "%d-%d-%d-%d-%d-%d" % (cur_time[0],  
  81.                 cur_time[1],cur_time[2],cur_time[3],cur_time[4],cur_time[5])  
  82.         return date_string        
  83. try:  
  84.     server = HTTPServer(('', PORT_NUMBER), myHandler)  
  85.     print 'Started httpserver on port ' , PORT_NUMBER  
  86.   
  87.     server.serve_forever()  
  88.   
  89. except KeyboardInterrupt:  
  90.     print '^C received, shutting down the web server'  
  91.     server.socket.close()  
    对于上面POST响应实现,值得一提的是,若客户端发送过来一个文件,则方法getvalue()会把整个文件内容读入内存,这可能不是我们想要的,这时可以使用form的属性file或filename,比如下面代码,计算上传代码的行数:

[python] view plaincopy在CODE上查看代码片派生到我的代码片
  1. fileitem = form["userfile"]  
  2. if fileitem.file:  
  3.     linecount = 0  
  4.     while 1:  
  5.         line = fileitem.file.readline()  
  6.         if not line: break  
  7.         linecount = linecount + 1  
POST和GET方法请求Python实现
    下面代码实现了GET方法的请求:

[python] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #!/usr/bin/env python  
  2. #coding=utf8  
  3.    
  4. import httplib  
  5.    
  6. httpClient = None  
  7.    
  8. try:  
  9.     httpClient = httplib.HTTPConnection('localhost'8080, timeout=30)  
  10.     httpClient.request('GET''/test0.html')  
  11.    
  12.     #response是HTTPResponse对象  
  13.     response = httpClient.getresponse()  
  14.     print response.status  
  15.     print response.reason  
  16.     print response.read()  
  17. except Exception, e:  
  18.     print e  
  19. finally:  
  20.     if httpClient:  
  21.         httpClient.close()  
    下面代码实现了POST方法的请求:
[python] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #!/usr/bin/env python  
  2. #coding=utf8  
  3.    
  4. import httplib, urllib  
  5.    
  6. httpClient = None  
  7. try:  
  8.     params = urllib.urlencode({'name''Maximus''addr'"GZ"})  
  9.     headers = {"Content-type""application/x-www-form-urlencoded"  
  10.                     , "Accept""text/plain"}  
  11.    
  12.     httpClient = httplib.HTTPConnection("localhost"8080, timeout=30)  
  13.     httpClient.request("POST""/test0.html", params, headers)  
  14.    
  15.     response = httpClient.getresponse()  
  16.     print response.status  
  17.     print response.reason  
  18.     print response.read()  
  19.     print response.getheaders() #获取头信息  
  20. except Exception, e:  
  21.     print e  
  22. finally:  
  23.     if httpClient:  
  24.         httpClient.close()  
参考资料

http://www.cnblogs.com/TankXiao/archive/2012/02/13/2342672.html
http://www.cnblogs.com/hyddd/archive/2009/03/31/1426026.html
http://www.acmesystems.it/python_httpserver
http://georgik.sinusgear.com/2011/01/07/how-to-dump-post-request-with-python/
http://www.01happy.com/python-httplib-get-and-post/

https://docs.python.org/2/library/basehttpserver.html#module-BaseHTTPServer


1 0
原创粉丝点击