因为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