因为EMSVPS的服务器实在有太多的问题,故现在改回比较稳定的burst.net机器。现在Paypal支持Unionpay的卡,5.95USD/mo大概人民币38元。burst.net的机器提供512M内存和2个IP地址,内存充足的时候跑起Wordpress的确轻松很多了。现在一个IP用作博客服务,另外一个IP用作提供一些Web服务。
因为不同的Web服务都需要监听一个服务端口,为了能让他们共用一个IP上的80端口,需要一个代理分发请求的程序。例如
访问http://lab.xiaoxia.org/server/*的请求分发到localhost:10000的服务,
访问http://lab.xiaoxia.org/whois/*的请求分发到localhost:10001的服务,
而访问http://lab.xiaoxia.org/*的请求,直接获取www目录下的资源文件,例如index.html。
因为使用的都是同一个域名,不同的只是路径,要根据不同的路径选择不同的服务端口,我使用了正则表达式来解决这个问题。
效果见 http://lab.xiaoxia.org/
我现在的分发规则如下:
# Host Request Path Handle Method Forward Host or Root Forward Path lab.xiaoxia.org /server/(.*) proxy localhost:10000 /$1 lab.xiaoxia.org /mail/(.*).action proxy localhost:10005 /$1.action lab.xiaoxia.org /mail/(.*) resource /var/mail /mail/$1 lab.xiaoxia.org /hashlib/(.*).action proxy localhost:10002 / lab.xiaoxia.org /whois/request/(.*) proxy localhost:10003 /$1 lab.xiaoxia.org /iplookup/request/(.*) proxy localhost:10004 /$1 lab.xiaoxia.org /(.*) resource www /$1
今晚写的WebGateway.py的代码如下。可以优化效率的地方很多,但对目前来说,已经足够。本来写了一个epoll版本的,但是代码太复杂太多了,就抛弃了,不利于阅读和维护。对于Python代码来说,应该坚持KISS (Keep It Simple & Stupid) 原则。
规则文件可以经常修改,而不需要重启WebGateway。
#!/usr/bin/python
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from httplib import HTTPResponse
from SocketServer import ThreadingMixIn
import socket, threading
import posixpath, shutil, mimetypes, urlparse
import time, sys, re, traceback, os
threading.stack_size(128*1024)
ConnectionTimeout = 30.0
ServiceConfigFile = "services.list"
class Handler(BaseHTTPRequestHandler):
def proxy(self, proxy_host, proxy_port, url):
try:
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.s.settimeout(ConnectionTimeout)
self.s.connect((proxy_host, proxy_port))
header = " ".join((self.command, url, "HTTP/1.1")) + "\r\n"
header += str(self.headers) + "\r\n"
self.s.send(header)
# Send Post data
if(self.command=='POST'):
self.s.send(self.rfile.read(int(self.headers['Content-Length'])))
response = HTTPResponse(self.s, method=self.command)
response.begin()
# Reply to the browser
status = "HTTP/1.1 " + str(response.status) + " " + response.reason
header = status + '\r\n'
for hh, vv in response.getheaders():
if hh.upper()!='TRANSFER-ENCODING':
header += hh + ': ' + vv + '\r\n'
self.wfile.write(header + '\r\n')
while True:
response_data = response.read(8192)
if not response_data: break
self.wfile.write(response_data)
self.s.close()
except:
print('error in ' + self.requestline + '\n' + traceback.format_exc())
def getResource(self, www_root, path):
path = path.split("?")[0].split("#")[0]
path = posixpath.normpath(path).strip("/")
fullpath = os.path.join(www_root, path)
# Default page
if os.path.isdir(fullpath):
fullpath = os.path.join(fullpath, "index.html")
mtype = mimetypes.guess_type(fullpath)[0]
if mtype is None: mtype = "text/plain"
if os.path.isfile(fullpath):
f = open(fullpath, "rb")
self.send_response(200)
self.send_header("Content-Type", mtype + "; charset=\"utf-8\"")
fs = os.fstat(f.fileno())
self.send_header("Content-Length", str(fs[6]))
self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
self.end_headers()
shutil.copyfileobj(f, self.wfile)
else:
self.send_error(404, "File not found %s" % path)
def getService(self):
hostname = self.headers["host"].split(":")[0].lower()
self.headers["X-Forwarded-For"] = self.connection.getpeername()[0]
for line in file(ServiceConfigFile).readlines():
var = line.split()
if var[0].lower() == hostname:
r = re.match(var[1], self.path)
if r:
i = 1
for k in r.groups():
var[4] = var[4].replace("$" + str(i), k)
i += 1
if var[2] == "proxy":
ip, port = var[3].split(":")
self.proxy(ip, 80 if port == "" else int(port), var[4])
elif var[2] == "resource":
self.getResource(var[3], var[4])
else:
self.send_error(500, "Unknown method")
return
self.send_error(400, "Bad Request")
do_POST = getService
do_GET = getService
class ThreadingHTTPServer(ThreadingMixIn, HTTPServer): pass
try:
server = ThreadingHTTPServer(("", 8000), Handler)
server.serve_forever()
except KeyboardInterrupt:
exit()
表示看不懂,不过也算明白了如果多个程序公用一个端口的原理~~~~
大牛您谦虚了!
国外的VPS到底不行啊
国内的设备和服务都不行啊,直接从国外交涉然后获取,服务还好一些,代理那些风险太大
用paypal支付的还是信用卡支付的?
paypal
绑定银行卡可以支付usd。
国内、。。。
9月1日入了一个 贵州免备案的,emsvps的。
信不过emsvps了,有点山寨。
小虾在网上,也做了一个实验室啊!
对!有些东西做出来玩玩蛮有意思的,自己有时候也需要。
虾哥!能不能把我的在线QQtea加密解密的也放到你的实验室里啊!方便分析linuxQQ或者macqq协议啊
好啊!!!能把你的程序发到我邮箱吗?
python 的确是个好东西,学习中。
一起学习吧!
速度挺快的,也不贵。
据说directspace的也不错,不过还没有开始了解。我也快成vps老手了
DS吐不出ipv6,我去
DS好像说给两个IPv6吧
你有没有什么较好的关于json和python的教程,或者python的dict直接就是json格式的数据。如果不麻烦的话你大概给你讲一下吧,谢谢!
在python里:
import json
help(json)
如果你要看json,可以去w3school.com
谢谢啦!
不用谢!
呵呵,想法不错,学习啦!
不过有些重复造轮子,用nginx作反向代理其实性能/功能更强呢
我觉得学习配置nginx的时间会比我用python写这么一个小程序的时间要长哦!!!起码要一个晚上才能摸索会nginx,但我写个转发小程序不到1小时就好了。
呵呵,这倒是难说,术业有专攻,对你来说可能是这样,对我来说配置nginx更简单呢。
貌似这样对搜索引擎不太友好吧
为何这么说呢?
你指的是哪一点?能举例说明?
Pingback引用通告: Python写简单的网络服务器示例 « Xiaoxia[PG]
微博是多少呢,我来follow
Pingback引用通告: Thought this was cool: Python写简单的网络服务器示例 « CWYAlpha