如何从零写一个http python httpserverr

9299人阅读
web开发(8)
java编程(28)
& & & & 一个简单的web服务器在不考虑其性能及健壮性的情况下,通常只需实现的功能包括服务器的启动,它用于监听某一个端口,接收客户端发来的请求,并将响应结果返回给客户端。本文将介绍一个简单web服务器的实现原理,它本身只能处理某个目录下的静态资源文件(文本、图片等)。采用java来实现的话,可以含以下几个模块,而且各个模块间的关系如图1所示。
图1、简单web服务器的模块
&HttpServer即为服务器,它用于服务器的启动及接收用户的请求并返回结果;Request:对用户请求进行分析,解析请求串,并获取对应的访问url;Response:根据用户请求生成响应结果,并将结果输出给客户端。
下面通过代码来具体的看下该服务器的实现过程。
HttpServer是服务器的主实现类,用于关联Request及Response,源代码如下所示:
package com.wow.
import java.io.F
import java.io.IOE
import java.io.InputS
import java.io.OutputS
import java.net.InetA
import java.net.ServerS
import java.net.S
import java.net.UnknownHostE
* 一个简单的web应用服务器
* @author zhaozheng
public class HttpServer {
public static final String WEB_ROOT = System.getProperty(&user.dir&) + File.separator + &webroot&;
private static final String SHUTDOWN_COMMAND = &/SHUTDOWN&;
private boolean shutdown =
public static void main(String[] args) {
HttpServer server = new HttpServer();
server.start();
//启动服务器,并接收用户请求进行处理
public void
ServerSocket serverSocket =
PORT = 8080;
serverSocket = new ServerSocket(PORT, 1, InetAddress.getByName(&127.0.0.1&));
} catch (UnknownHostException e) {
e.printStackTrace();
System.exit(-1);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
//若请求的命令不为SHUTDOWN时,循环处理请求
while(!shutdown) {
Socket socket =
InputStream input =
OutputStream output =
//创建socket进行请求处理
socket = serverSocket.accept();
input = socket.getInputStream();
output = socket.getOutputStream();
//接收请求
Request request = new Request(input);
request.parser();
//处理请求并返回结果
Response response = new Response(output);
response.setRequest(request);
response.sendStaticResource();
//关闭socket
socket.close();
//若请求命令为关闭,则关闭服务器
shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
} catch (IOException e) {
e.printStackTrace();
& & & & 该类本身是一个应用程序,包含main方法,直接通过java命令即可运行。在运行时,它本身会启动一个ServerSocket类用于监听服务器的某个端口。当接收到的命令不是停止服务器的SHUTDOWN时,它会创建一个Socket套接字,用于接收请求及返回响应结果。
& & & & Request类则用于请求的接收,对于Http协议来讲,通过浏览器向服务器发送请求有一定的格式,其实Request也就是接收这些请求信息,并对其进行分析,抽取出所需的信息,包括cookie、url等。其中http发送的请求包括三部分:
请求方法 统一资源标识符 协议/版本请求头&请求实体
其中请求头与请求实体间有一个空行,具体的示例代码如下所示:
GET /index.htm HTTP/1.1
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97 Safari/537.11
Accept: text/html,application/xhtml+xml,application/q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: zh-CN,q=0.8 Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3
Cookie: BAIDUID=D275C16E04D9BB2CF55FD9B9654AECAC:FG=1;
BDREFER=%7Burl%3A%22http%3A///%22%2Cword%3A%22%22%7D;BDUSS=FJ2SzJxSmpKMW1sdVIwMWw3TTBwaHhZRkxFaUdoeG9QLW5GS2dLTUtyZzNhWUpSQVFBQUFBJCQAAAAAAAAAAAouTQytzfcOemhhb3poZW5nNzc1OAAAAAAAAAAAAAAAAAAAAAAAAACAYIArMAAAALCmJHAAAAAA6p5DAAAAAAAxMC4zNi4xNDcblVA3G5VQd; BDUT=5b2fD275C16E04D9BB2CF55FD9B9654AECAC138a; MCITY=-%3A; shifen[]=; H_PS_PSSID=
& & & & Request类用于接收socket套接字发送过来的字节流,并按照http协议请求的格式进行解析。对于简单的web服务器而言,我们只需要解析出它的uri即可,这样即可以通过通过文件匹配的方式找到对应的资源。具体的实现代码如下所示:
package com.wow.
import java.io.IOE
import java.io.InputS
*接收到的请求串的具体格式如下:
* GET /aaa.htm HTTP/1.1
* Host: 127.0.0.1:8080
* Connection: keep-alive
* User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97 Safari/537.11
* Accept: text/html,application/xhtml+xml,application/q=0.9,q=0.8
* Accept-Encoding: gzip,deflate,sdch
* Accept-Language: zh-CN,q=0.8
* Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3
* @author zhaozheng
public class Request {
private InputS
public Request(InputStream input) {
this.input =
public void parser() {
StringBuffer request = new StringBuffer();
byte[] buffer = new byte[2048];
int i = 0;
i = input.read(buffer);
} catch (IOException e) {
e.printStackTrace();
for(int k = 0; k & k++) {
request.append((char)buffer[k]);
uri = parserUri(request.toString());
private String parserUri(String requestData) {
int index1, index2;
index1 = requestData.indexOf(' ');
if(index1 != -1) {
index2 = requestData.indexOf(' ', index1 + 1);
if(index2 & index1) {
return requestData.substring(index1 + 1, index2);
public String getUri() {
& & & & 通过上述代码可以看出parser方法用于解析具体请求,它接收socket的字节流,对其进行处理,获取其中的uri信息。
& & & & 当获取到uri信息后,即可将uri对应到服务器的某个应用或目录中。本文只是实现了一个简单的静态资源服务器,即将uri对应到某个目录下的文件,若文件存在则打开并读取文件信息; 若不存在则直接返回一段错误信息。Response类即用于处理该逻辑,同时它会将文件流写回至socket套接字中,由socket套接字将响应结果返回给客户端。
& & & & 对于http协议而言,响应也是有一定的格式要求的,不能发送任意格式的信息,否则浏览器是无法接收并处理的。Http响应结果也包括三部分:
协议 状态码 描述响应头响应实体段
其中响应头与响应实体段间也是有一个空行的,具体的实例如下所示:
HTTP/1.1 200 OK
Date: Mon, 07 Jan :36 GMT
Server: BWS/1.0
Content-Length: 4029
Content-Type: text/charset=gbk
Cache-Control: private Expires: Mon, 07 Jan :36 GMT
Content-Encoding: gzip
Set-Cookie: H_PS_PSSID=; path=/; domain=.
Connection: Keep-Alive
&html&&head&…&/head&&/html&
& & & & Response类中当访问请求的文件不存在时,需要发送一段固定的响应文本给客户端,该段响应文档的格式必须严格按照http响应格式进行组织,否则客户端接收不到。具体的实现源码如下所示:
package com.wow.
import java.io.F
import java.io.FileInputS
import java.io.IOE
import java.io.OutputS
* 响应结果
* @author zhaozheng
public class Response {
private OutputS
private static final int BUFFER_SIZE = 1024;
public Response(OutputStream output) {
this.output =
public void setRequest(Request request) {
this.request =
//发送一个静态资源给客户端,若本地服务器有对应的文件则返回,否则返回404页面
public void sendStaticResource() {
byte[] buffer = new byte[BUFFER_SIZE];
FileInputStream fis =
File file = new File(HttpServer.WEB_ROOT, request.getUri());
if(file.exists()) {
fis = new FileInputStream(file);
ch = fis.read(buffer);
while(ch != -1) {
output.write(buffer, 0, ch);
ch = fis.read(buffer, 0, BUFFER_SIZE);
String errorMessage = &HTTP/1.1 404 File Not Found \r\n& +
&Content-Type: text/html\r\n& +
&Content-Length: 24\r\n& +
&&h1&File Not Found!&/h1&&;
output.write(errorMessage.getBytes());
} catch (Exception e) {
System.out.println(e.toString());
} finally {
if(fis != null) {
fis.close();
} catch (IOException e) {
e.printStackTrace();
& & & & 分析Response类,sendStaticResource方法中根据请求的uri去目录下查找是否有对应的文件存在,若有则直接读入文件并返回;否则返回一段错误消息给客户端。
当然若要运行该程序,则还需要在该工程对应的目录下创建一个webroot目录,其中可以存放一个aaa.htm文件。
1、启动该java应用程序,通过netstat可查看该程序占用了8080端口。
2、通过浏览器访问url地址:。
3、若访问index1.htm由于不存在则直接返回404 File Not Found信息。
4、&可以直接输入 即可关闭服务器。
& & & & 至此一个简单的web服务器就实现完了,它本身的功能不太完整,但对于初学者了解http请求的处理、响应及web服务器的大致工作流是有帮助的。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:501473次
积分:4528
积分:4528
排名:第5438名
原创:76篇
转载:18篇
评论:136条
(1)(7)(1)(6)(2)(1)(6)(4)(2)(6)(17)(1)(3)(3)(5)(1)(2)(8)(9)(1)(1)(2)(2)(2)(4)子非鱼,安知鱼之乐、
http-server是一个简单的、零配置的命令行http服务器。它在生产环境是非常有用的,但是它只能简单的在本地环境进行开发、使用和学习。
全局安装:
&npm install http-server -g&
使用npm命令安装,如果没有npm环境,请先现在配置npm命令。NPM下载:/
本次操作会通过命令行把http-server全局安装。
http-server使用方法:
&http-server [path] [options]&
【path】参数,默认路径是./public如果这个文件存在,否则就是当前目录!
好了,现在你可以打开 http://localhost.8080,观看你的网站了。
http-server默认是在当前路径下开始http服务器。
有效的配置项目:-p 指定端口号,默认8080-a 地址使用(默认为0.0.0.0)-d 显示目录列表(默认为&True&)-i 显示自动索引 (defaults to 'True')-e or --ext 如果没有提供默认的扩展名(defaults to 'html')-s or --silent 打印输出日志--cors Enable CORS via the Access-Control-Allow-Origin header-o Open browser window after starting the server-c Set cache time (in seconds) for cache-control max-age header, e.g. -c10 for 10 seconds (defaults to '3600'). To disable caching, use -c-1.-U or --utc Use UTC time format in log messages.-P or --proxy Proxies all requests which can't be resolved locally to the given url. e.g.: -P -S or --ssl Enable https.-C or --cert Path to ssl cert file (default: cert.pem).-K or --key Path to ssl key file (default: key.pem).-r or --robots Provide a /robots.txt (whose content defaults to 'User-agent: *\nDisallow: /')-h or --help Print this list and exit.
附录:npm管理包地址。
/package/http-server
阅读(...) 评论()通常地我们要在不同平台间共享文件,samba,ftp,cifs,ntfs的设置都是有点复杂的, 我们可以使用python提供的httpserver来提供基于http方式跨平台的文件共享。
一 命令行启动简单的httpserver
进入到web或要共享文件的根目录,然后执行(貌似在python32中此module不存在了):python -m SimpleHTTPServer 8000然后你就可以使用http://你的IP地址:8000/来访问web页面或共享文件了。
二 &代码启动httpserver
simplehttpservertest.py&&
import&sysimport&localeimport&http.serverimport&socketserveraddr&=&len(sys.argv)&&&2&and&"localhost"&or&sys.argv[1]port&=&len(sys.argv)&&&3&and&80&or&locale.atoi(sys.argv[2])handler&=&http.server.SimpleHTTPRequestHandlerhttpd&=&socketserver.TCPServer((addr,&port),&handler)print&("HTTP&server&is&at:&http://%s:%d/"&%&(addr,&port))httpd.serve_forever()
需要进入web或要共享的目录,执行下列:&
simplehttpservertest.py localhost 8008&
三 第三方的python库Droopy
且支持可以上传文件到共享服务器
四 支持上传的httpserver
#!/usr/bin/env&python#coding=utf-8#&modifyDate:&&~&#&原作者为:bones7456,&/#&修改者为:#&v1.2,changeLog:#&+:&文件日期/时间/颜色显示、多线程支持、主页跳转#&-:&解决不同浏览器下上传文件名乱码问题:仅IE,其它浏览器暂时没处理。#&-:&一些路径显示的bug,主要是&cgi.escape()&转义问题#&?:&notepad++&下直接编译的server路径问题&"""&&&&简介:这是一个&python&写的轻量级的文件共享服务器(基于内置的SimpleHTTPServer模块),&&&&支持文件上传下载,只要你安装了python(建议版本2.6~2.7,不支持3.x),&&&&然后去到想要共享的目录下,执行:&&&&&&&&python&SimpleHTTPServerWithUpload.py&1234&&&&&&&&&&&其中1234为你指定的端口号,如不写,默认为&8080&&&&然后访问&http://localhost:1234&即可,localhost&或者&1234&请酌情替换。"""&"""Simple&HTTP&Server&With&Upload.&This&module&builds&on&BaseHTTPServer&by&implementing&the&standard&GETand&HEAD&requests&in&a&fairly&straightforward&manner.&"""&&__version__&=&"0.1"__all__&=&["SimpleHTTPRequestHandler"]__author__&=&"bones7456"__home_page__&=&""&import&os,&sys,&platformimport&posixpathimport&BaseHTTPServerfrom&SocketServer&import&ThreadingMixInimport&threadingimport&urllibimport&cgiimport&shutilimport&mimetypesimport&reimport&time&&try:&&&&from&cStringIO&import&StringIOexcept&ImportError:&&&&from&StringIO&import&StringIO&&&&&&print&""print&'-----------------------------------------------------------------------&&&'try:&&&port&=&int(sys.argv[1])except&Exception,&e:&&&print&'--------&&&Warning:&Port&is&not&given,&will&use&deafult&port:&8080&'&&&print&'--------&&&if&you&want&to&use&other&port,&please&execute:&'&&&print&'--------&&&python&SimpleHTTPServerWithUpload.py&port&'&&&print&"--------&&&port&is&a&integer&and&it's&range:&1024&&&port&&&65535&"&&&port&=&8080&&&&if&not&1024&&&port&&&65535:&&port&=&8080serveraddr&=&('',&port)print&'--------&&&Now,&listening&at&port&'&+&str(port)&+&'&...'print&'--------&&&You&can&visit&the&URL:&&&http://localhost:'&+&str(port)print&'-----------------------------------------------------------------------&&&'print&""&&&&&&def&sizeof_fmt(num):&&&&for&x&in&['bytes','KB','MB','GB']:&&&&&&&&if&num&&&1024.0:&&&&&&&&&&&&return&"%3.1f%s"&%&(num,&x)&&&&&&&&num&/=&1024.0&&&&return&"%3.1f%s"&%&(num,&'TB')&def&modification_date(filename):&&&&#&t&=&os.path.getmtime(filename)&&&&#&return&datetime.datetime.fromtimestamp(t)&&&&return&time.strftime("%Y-%m-%d&%H:%M:%S",time.localtime(os.path.getmtime(filename)))&class&SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):&&&&&"""Simple&HTTP&request&handler&with&GET/HEAD/POST&commands.&&&&&This&serves&files&from&the&current&directory&and&any&of&its&&&&subdirectories.&&The&MIME&type&for&files&is&determined&by&&&&calling&the&.guess_type()&method.&And&can&reveive&file&uploaded&&&&by&client.&&&&&The&GET/HEAD/POST&requests&are&identical&except&that&the&HEAD&&&&request&omits&the&actual&contents&of&the&file.&&&&&"""&&&&&server_version&=&"SimpleHTTPWithUpload/"&+&__version__&&&&&def&do_GET(self):&&&&&&&&"""Serve&a&GET&request."""&&&&&&&&#&print&"....................",&threading.currentThread().getName()&&&&&&&&f&=&self.send_head()&&&&&&&&if&f:&&&&&&&&&&&&self.copyfile(f,&self.wfile)&&&&&&&&&&&&f.close()&&&&&def&do_HEAD(self):&&&&&&&&"""Serve&a&HEAD&request."""&&&&&&&&f&=&self.send_head()&&&&&&&&if&f:&&&&&&&&&&&&f.close()&&&&&def&do_POST(self):&&&&&&&&"""Serve&a&POST&request."""&&&&&&&&r,&info&=&self.deal_post_data()&&&&&&&&print&r,&info,&"by:&",&self.client_address&&&&&&&&f&=&StringIO()&&&&&&&&f.write('&!DOCTYPE&html&PUBLIC&"-//W3C//DTD&HTML&3.2&Final//EN"&')&&&&&&&&f.write("&html&\n&title&Upload&Result&Page&/title&\n")&&&&&&&&f.write("&body&\n&h2&Upload&Result&Page&/h2&\n")&&&&&&&&f.write("&hr&\n")&&&&&&&&if&r:&&&&&&&&&&&&f.write("&strong&Success:&/strong&")&&&&&&&&else:&&&&&&&&&&&&f.write("&strong&Failed:&/strong&")&&&&&&&&f.write(info)&&&&&&&&f.write("&br&&a&href=\"%s\"&back&/a&"&%&self.headers['referer'])&&&&&&&&f.write("&hr&&small&Powered&By:&bones7456,&check&new&version&at&")&&&&&&&&f.write("&a&href=\"/?s=SimpleHTTPServerWithUpload\"&")&&&&&&&&f.write("here&/a&.&/small&&/body&\n&/html&\n")&&&&&&&&length&=&f.tell()&&&&&&&&f.seek(0)&&&&&&&&self.send_response(200)&&&&&&&&self.send_header("Content-type",&"text/html")&&&&&&&&self.send_header("Content-Length",&str(length))&&&&&&&&self.end_headers()&&&&&&&&if&f:&&&&&&&&&&&&self.copyfile(f,&self.wfile)&&&&&&&&&&&&f.close()&&&&&&&&&&&&&def&deal_post_data(self):&&&&&&&&boundary&=&self.headers.plisttext.split("=")[1]&&&&&&&&remainbytes&=&int(self.headers['content-length'])&&&&&&&&line&=&self.rfile.readline()&&&&&&&&remainbytes&-=&len(line)&&&&&&&&if&not&boundary&in&line:&&&&&&&&&&&&return&(False,&"Content&NOT&begin&with&boundary")&&&&&&&&line&=&self.rfile.readline()&&&&&&&&remainbytes&-=&len(line)&&&&&&&&fn&=&re.findall(r'Content-Disposition.*name="file";&filename="(.*)"',&line)&&&&&&&&if&not&fn:&&&&&&&&&&&&return&(False,&"Can't&find&out&file&name...")&&&&&&&&path&=&self.translate_path(self.path)&&&&&&&&osType&=&platform.system()&&&&&&&&try:&&&&&&&&&&&&if&osType&==&"Linux":&&&&&&&&&&&&&&&&fn&=&os.path.join(path,&fn[0].decode('gbk').encode('utf-8'))&&&&&&&&&&&&else:&&&&&&&&&&&&&&&&fn&=&os.path.join(path,&fn[0])&&&&&&&&except&Exception,&e:&&&&&&&&&&&&return&(False,&"文件名请不要用中文,或者使用IE上传中文名的文件。")&&&&&&&&while&os.path.exists(fn):&&&&&&&&&&&&fn&+=&"_"&&&&&&&&line&=&self.rfile.readline()&&&&&&&&remainbytes&-=&len(line)&&&&&&&&line&=&self.rfile.readline()&&&&&&&&remainbytes&-=&len(line)&&&&&&&&try:&&&&&&&&&&&&out&=&open(fn,&'wb')&&&&&&&&except&IOError:&&&&&&&&&&&&return&(False,&"Can't&create&file&to&write,&do&you&have&permission&to&write?")&&&&&&&&&&&&&&&&&&&&&&&&&preline&=&self.rfile.readline()&&&&&&&&remainbytes&-=&len(preline)&&&&&&&&while&remainbytes&&&0:&&&&&&&&&&&&line&=&self.rfile.readline()&&&&&&&&&&&&remainbytes&-=&len(line)&&&&&&&&&&&&if&boundary&in&line:&&&&&&&&&&&&&&&&preline&=&preline[0:-1]&&&&&&&&&&&&&&&&if&preline.endswith('\r'):&&&&&&&&&&&&&&&&&&&&preline&=&preline[0:-1]&&&&&&&&&&&&&&&&out.write(preline)&&&&&&&&&&&&&&&&out.close()&&&&&&&&&&&&&&&&return&(True,&"File&'%s'&upload&success!"&%&fn)&&&&&&&&&&&&else:&&&&&&&&&&&&&&&&out.write(preline)&&&&&&&&&&&&&&&&preline&=&line&&&&&&&&return&(False,&"Unexpect&Ends&of&data.")&&&&&def&send_head(self):&&&&&&&&"""Common&code&for&GET&and&HEAD&commands.&&&&&&&&&This&sends&the&response&code&and&MIME&headers.&&&&&&&&&Return&value&is&either&a&file&object&(which&has&to&be&copied&&&&&&&&to&the&outputfile&by&the&caller&unless&the&command&was&HEAD,&&&&&&&&and&must&be&closed&by&the&caller&under&all&circumstances),&or&&&&&&&&None,&in&which&case&the&caller&has&nothing&further&to&do.&&&&&&&&&"""&&&&&&&&path&=&self.translate_path(self.path)&&&&&&&&f&=&None&&&&&&&&if&os.path.isdir(path):&&&&&&&&&&&&if&not&self.path.endswith('/'):&&&&&&&&&&&&&&&&#&redirect&browser&-&doing&basically&what&apache&does&&&&&&&&&&&&&&&&self.send_response(301)&&&&&&&&&&&&&&&&self.send_header("Location",&self.path&+&"/")&&&&&&&&&&&&&&&&self.end_headers()&&&&&&&&&&&&&&&&return&None&&&&&&&&&&&&for&index&in&"index.html",&"index.htm":&&&&&&&&&&&&&&&&index&=&os.path.join(path,&index)&&&&&&&&&&&&&&&&if&os.path.exists(index):&&&&&&&&&&&&&&&&&&&&path&=&index&&&&&&&&&&&&&&&&&&&&break&&&&&&&&&&&&else:&&&&&&&&&&&&&&&&return&self.list_directory(path)&&&&&&&&ctype&=&self.guess_type(path)&&&&&&&&try:&&&&&&&&&&&&#&Always&read&in&binary&mode.&Opening&files&in&text&mode&may&cause&&&&&&&&&&&&#&newline&translations,&making&the&actual&size&of&the&content&&&&&&&&&&&&#&transmitted&*less*&than&the&content-length!&&&&&&&&&&&&f&=&open(path,&'rb')&&&&&&&&except&IOError:&&&&&&&&&&&&self.send_error(404,&"File&not&found")&&&&&&&&&&&&return&None&&&&&&&&self.send_response(200)&&&&&&&&self.send_header("Content-type",&ctype)&&&&&&&&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()&&&&&&&&return&f&&&&&def&list_directory(self,&path):&&&&&&&&"""Helper&to&produce&a&directory&listing&(absent&index.html).&&&&&&&&&Return&value&is&either&a&file&object,&or&None&(indicating&an&&&&&&&&error).&&In&either&case,&the&headers&are&sent,&making&the&&&&&&&&interface&the&same&as&for&send_head().&&&&&&&&&"""&&&&&&&&try:&&&&&&&&&&&&list&=&os.listdir(path)&&&&&&&&except&os.error:&&&&&&&&&&&&self.send_error(404,&"No&permission&to&list&directory")&&&&&&&&&&&&return&None&&&&&&&&list.sort(key=lambda&a:&a.lower())&&&&&&&&f&=&StringIO()&&&&&&&&displaypath&=&cgi.escape(urllib.unquote(self.path))&&&&&&&&f.write('&!DOCTYPE&html&PUBLIC&"-//W3C//DTD&HTML&3.2&Final//EN"&')&&&&&&&&f.write("&html&\n&title&Directory&listing&for&%s&/title&\n"&%&displaypath)&&&&&&&&f.write("&body&\n&h2&Directory&listing&for&%s&/h2&\n"&%&displaypath)&&&&&&&&f.write("&hr&\n")&&&&&&&&f.write("&form&ENCTYPE=\"multipart/form-data\"&method=\"post\"&")&&&&&&&&f.write("&input&name=\"file\"&type=\"file\"/&")&&&&&&&&f.write("&input&type=\"submit\"&value=\"upload\"/&")&&&&&&&&f.write("&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp")&&&&&&&&f.write("&input&type=\"button\"&value=\"HomePage\"&onClick=\"location='/'\"&")&&&&&&&&f.write("&/form&\n")&&&&&&&&f.write("&hr&\n&ul&\n")&&&&&&&&for&name&in&list:&&&&&&&&&&&&fullname&=&os.path.join(path,&name)&&&&&&&&&&&&colorName&=&displayname&=&linkname&=&name&&&&&&&&&&&&#&Append&/&for&directories&or&@&for&symbolic&links&&&&&&&&&&&&if&os.path.isdir(fullname):&&&&&&&&&&&&&&&&colorName&=&'&span&style="background-color:&#CEFFCE;"&'&+&name&+&'/&/span&'&&&&&&&&&&&&&&&&displayname&=&name&&&&&&&&&&&&&&&&linkname&=&name&+&"/"&&&&&&&&&&&&if&os.path.islink(fullname):&&&&&&&&&&&&&&&&colorName&=&'&span&style="background-color:&#FFBFFF;"&'&+&name&+&'@&/span&'&&&&&&&&&&&&&&&&displayname&=&name&&&&&&&&&&&&&&&&#&Note:&a&link&to&a&directory&displays&with&@&and&links&with&/&&&&&&&&&&&&filename&=&os.getcwd()&+&'/'&+&displaypath&+&displayname&&&&&&&&&&&&f.write('&table&&tr&&td&width="60%%"&&a&href="%s"&%s&/a&&/td&&td&width="20%%"&%s&/td&&td&width="20%%"&%s&/td&&/tr&\n'&&&&&&&&&&&&&&&&&&&&%&(urllib.quote(linkname),&colorName,&&&&&&&&&&&&&&&&&&&&&&&&sizeof_fmt(os.path.getsize(filename)),&modification_date(filename)))&&&&&&&&f.write("&/table&\n&hr&\n&/body&\n&/html&\n")&&&&&&&&length&=&f.tell()&&&&&&&&f.seek(0)&&&&&&&&self.send_response(200)&&&&&&&&self.send_header("Content-type",&"text/html")&&&&&&&&self.send_header("Content-Length",&str(length))&&&&&&&&self.end_headers()&&&&&&&&return&f&&&&&def&translate_path(self,&path):&&&&&&&&"""Translate&a&/-separated&PATH&to&the&local&filename&syntax.&&&&&&&&&Components&that&mean&special&things&to&the&local&file&system&&&&&&&&(e.g.&drive&or&directory&names)&are&ignored.&&(XXX&They&should&&&&&&&&probably&be&diagnosed.)&&&&&&&&&"""&&&&&&&&#&abandon&query&parameters&&&&&&&&path&=&path.split('?',1)[0]&&&&&&&&path&=&path.split('#',1)[0]&&&&&&&&path&=&posixpath.normpath(urllib.unquote(path))&&&&&&&&words&=&path.split('/')&&&&&&&&words&=&filter(None,&words)&&&&&&&&path&=&os.getcwd()&&&&&&&&for&word&in&words:&&&&&&&&&&&&drive,&word&=&os.path.splitdrive(word)&&&&&&&&&&&&head,&word&=&os.path.split(word)&&&&&&&&&&&&if&word&in&(os.curdir,&os.pardir):&continue&&&&&&&&&&&&path&=&os.path.join(path,&word)&&&&&&&&return&path&&&&&def&copyfile(self,&source,&outputfile):&&&&&&&&"""Copy&all&data&between&two&file&objects.&&&&&&&&&The&SOURCE&argument&is&a&file&object&open&for&reading&&&&&&&&(or&anything&with&a&read()&method)&and&the&DESTINATION&&&&&&&&argument&is&a&file&object&open&for&writing&(or&&&&&&&&anything&with&a&write()&method).&&&&&&&&&The&only&reason&for&overriding&this&would&be&to&change&&&&&&&&the&block&size&or&perhaps&to&replace&newlines&by&CRLF&&&&&&&&--&note&however&that&this&the&default&server&uses&this&&&&&&&&to&copy&binary&data&as&well.&&&&&&&&&"""&&&&&&&&shutil.copyfileobj(source,&outputfile)&&&&&def&guess_type(self,&path):&&&&&&&&"""Guess&the&type&of&a&file.&&&&&&&&&Argument&is&a&PATH&(a&filename).&&&&&&&&&Return&value&is&a&string&of&the&form&type/subtype,&&&&&&&&usable&for&a&MIME&Content-type&header.&&&&&&&&&The&default&implementation&looks&the&file's&extension&&&&&&&&up&in&the&table&self.extensions_map,&using&application/octet-stream&&&&&&&&as&a&&however&it&would&be&permissible&(if&&&&&&&&slow)&to&look&inside&the&data&to&make&a&better&guess.&&&&&&&&&"""&&&&&&&&&base,&ext&=&posixpath.splitext(path)&&&&&&&&if&ext&in&self.extensions_map:&&&&&&&&&&&&return&self.extensions_map[ext]&&&&&&&&ext&=&ext.lower()&&&&&&&&if&ext&in&self.extensions_map:&&&&&&&&&&&&return&self.extensions_map[ext]&&&&&&&&else:&&&&&&&&&&&&return&self.extensions_map['']&&&&&if&not&mimetypes.inited:&&&&&&&&mimetypes.init()&#&try&to&read&system&mime.types&&&&extensions_map&=&mimetypes.types_map.copy()&&&&extensions_map.update({&&&&&&&&'':&'application/octet-stream',&#&Default&&&&&&&&'.py':&'text/plain',&&&&&&&&'.c':&'text/plain',&&&&&&&&'.h':&'text/plain',&&&&&&&&})&class&ThreadingServer(ThreadingMixIn,&BaseHTTPServer.HTTPServer):&&&&pass&&&&&def&test(HandlerClass&=&SimpleHTTPRequestHandler,&&&&&&&ServerClass&=&BaseHTTPServer.HTTPServer):&&&&BaseHTTPServer.test(HandlerClass,&ServerClass)&if&__name__&==&'__main__':&&&&#&test()&&&&&&&&&#单线程&&&&#&srvr&=&BaseHTTPServer.HTTPServer(serveraddr,&SimpleHTTPRequestHandler)&&&&&&&&&#多线程&&&&srvr&=&ThreadingServer(serveraddr,&SimpleHTTPRequestHandler)& & & &srvr.serve_forever()&&& & &
五 本地的httpserver
在本地机器没有联网的时候,需要使用如下:来自
&如果你只想让这个HTTP服务器服务于本地环境,那么,你需要定制一下你的Python的程序,下面是一个示例:
import sys
import BaseHTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler
HandlerClass = SimpleHTTPRequestHandler
ServerClass& = BaseHTTPServer.HTTPServer
Protocol&&&& = "HTTP/1.0"
if sys.argv[1:]:
&&&&port = int(sys.argv[1])
&&&&port = 8000
server_address = ('127.0.0.1', port)
HandlerClass.protocol_version = Protocol
httpd = ServerClass(server_address, HandlerClass)
sa = httpd.socket.getsockname()
print "Serving HTTP on", sa[0], "port", sa[1], "..."
httpd.serve_forever()
阅读(...) 评论()}

我要回帖

更多关于 python 写http server 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信