pythonweb服务器部署iis_python搭建简单的web服务器

由于要做自动化和性能测试,工作中需要有一个能够控制返回消息数据的web服务器,所以用python初步实现了一个简单的web服务器,能够处理HTTP的请求(GET,POST,PUT),并完成响应。

先简单说明下原理,python中实现web服务器大概分两个步骤:

1. 创建一个套接字,绑定到指定的IP和端口,保持监听

2. 创建一个handle类,当收到请求消息时,作出响应

主要使用的类有两个:

HTTPServer:HTTP服务器的基类,提供了HTTP服务器的常用方法,创建服务器时可以直接声明这个类,也可以根据需要从这个类继承。

CGIHTTPRequestHandler:处理请求的handle类,继承自BaseHTTPRequestHandler类,在python文档中说明该类可以处理GET和POST请求,自己试了一下发现也可以处理PUT请求。

源码如下:

import socket

from os import curdir,sep

from BaseHTTPServer import HTTPServer

from CGIHTTPServer import CGIHTTPRequestHandler

import json

class HttpHandler(CGIHTTPRequestHandler):

def do_GET(self):

try:

f = open(curdir + sep + self.path)

print self.path

print 'This is a GET method!'

self.send_response(200)

self.send_header('Content-type',

'text/html')

self.end_headers()

self.wfile.write(f.read())

f.close()

except IOError:

self.send_error(404,'File Not Found:%s' % self.path)

def do_POST(self):

try:

print self.path

print 'This is a POST method!'

self.data = self.request.recv(1024).strip()

self.data = json.loads(self.data)

print self.data

sendData = {}

if self.path == '/getfile':

f = open(curdir + sep + '/test_body.txt')

fileContent = f.read()

sendData['content'] = fileContent

f.close()

self.send_response(200)

self.send_header('Content-type',

'text/html')

self.end_headers()

self.wfile.write(sendData)

except:

self.send_error(404,'Invalid request:%s!' % self.path)

def do_PUT(self):

try:

print self.path

print 'This is a PUT method!'

self.data = self.request.recv(1024).strip()

print self.data

sendData = {}

if self.path == '/getfile':

f = open(curdir + sep + '/test_body.txt')

fileContent = f.read()

sendData['content'] = fileContent

f.close()

self.send_response(200)

self.send_header('Content-type',

'text/html')

self.end_headers()

self.wfile.write(sendData)

except:

self.send_error(404,'Invalid request:%s!' % self.path)

def main():

try:

localIp = socket.gethostbyname(socket.gethostname())

server_address = (localIp,8080)

http_server = HTTPServer(server_address,HttpHandler)

sa = http_server.socket.getsockname()

print "Serving HTTP on", sa[0], "port", sa[1], "..."

print 'Press ^C once or twice to quit.'

http_server.serve_forever()

except KeyboardInterrupt:

print '^C received,shutting down server.'

http_server.socket.close()

if __name__ == '__main__':

main()

在main()函数中新建了一个HTTPServer类,绑定到本机的8080端口,并保持监听。当收到请求时,根据请求的方法类型进入不同的do_*函数。函数的处理逻辑很简单,如果发送的URL合法,设置返回码为200,然后读取一个文件的内容,并写入到返回消息中。这样一个简单的web服务器就完成了,可以用RESTClient测试一下。

HTTPS相对于HTTP增加了SSL通道,客户端和服务器端必须有相互信任的证书才可以通信。自己对这方面的内容之前完全不了解,费了很大的功夫才初步把HTTPS的请求调通。

相比于HTTP的服务器,HTTPS改动的地方主要是建立服务器的时候:

class SecureHTTPServer(HTTPServer):

def __init__(self, server_address, HandlerClass):

BaseServer.__init__(self, server_address, HandlerClass)

self.socket = ssl.SSLSocket(socket.socket(self.address_family,self.socket_type),keyfile='./server.key', certfile='./server.crt', server_side=True)

self.server_bind()

self.server_activate()

这里新声明了一个SecureHTTPServer类,继承自HTTPServer类,在这个类中重新定义了构造函数,主要是新创建了一个SSLSocket类型的套接字,并指定了这个套接字的keyfile和certfile。keyfile和certfile这两个文件是安装了OpenSSL后手动生成的,执行如下openssl命令在本地生成pem文件:

req -new -x509 -keyout server.pem -out server.pem -day 365 -nodes

将server.pem文件中CERTIFICATE部分拷贝出来另存为server.crt。执行如下命令在本地生成或者删除证书:

keytool -import -alias certificatekey -file server.crt -keystore server.jks

keytool -delete -alias certificatekey -keystore server.jks

将server.jk上传到发送请求的系统作为证书库。

新声明一个handler类来处理收到的请求,并添加了多线程机制:

class SecureHTTPHandler(CGIHTTPRequestHandler):

# def setup(self):

# self.connection = self.request

# # self.rbufsize = 8192

# # self.wbufsize = 8192

# self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)

# self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)

def commonProcess(self):

#处理请求的通用函数

try:

#设置不阻塞

self.request.setblocking(0)

#设置超时时间为5秒

self.request.settimeout(5)

#自己的处理代码

f = open(curdir + sep + self.path)

print self.path

print 'This is a GET method!'

self.send_response(200)

self.send_header('Content-type',

'text/html')

self.end_headers()

self.wfile.write(f.read())

f.close()

except:

logging.error('Invalid request:%s!' % self.path)

self.send_error(404,'Invalid request:%s!' % self.path)

def do_GET(self):

logging.info('Received url is %s' % self.path)

logging.info('This is a GET method!')

#self.commonProcess()

t = threading.Thread(target = self.commonProcess,args = ())

t.start()

t.join(5)

def do_POST(self):

logging.info('Received url is %s' % self.path)

logging.info('This is a POST method!')

#self.commonProcess()

t = threading.Thread(target = self.commonProcess,args = ())

t.start()

t.join(5)

def do_PUT(self):

logging.info('Received url is %s' % self.path)

logging.info('This is a PUT method!')

#self.commonProcess()

t = threading.Thread(target = self.commonProcess,args = ())

t.start()

t.join(5)

在main()函数中要声明这个类的对象来创建服务器:

https_server = SecureHTTPServer(server_address,SecureHTTPHandler)

以下是客户端的测试代码:

import httplib

def main():

conn = httplib.HTTPSConnection(host = "127.0.0.1", port = 8443, key_file='./server.key', cert_file='./server.crt' , source_address = ('127.0.0.1',8080))

print "requesting..."

conn.request('PUT', '/test_body.txt')

r1 = conn.getresponse()

#打印响应码和响应状态信息

print r1.status, r1.reason

另外,python中的twisted框架在处理web服务器时似乎功能很强大,后续可以深入研究一下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值