博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于python创建一个简单的HTTP-WEB服务器
阅读量:4881 次
发布时间:2019-06-11

本文共 8647 字,大约阅读时间需要 28 分钟。

  • 背景

大多数情况下主机资源只有开发和测试相关人员可以登录直接操作,且有些特定情况“答辩、演示、远程”等这些场景下是无法直接登录主机的。web是所有终端用户都可以访问了,解决了人员权限与特定场景带来的问题。那么我们就来看看最简单的web服务器是怎么创建的~~

  • 具体实现

首先搭建python环境,涉及问题请移步。python内建模块SimpleHTTPServer,源码如下路径是/usr/lib64/python2.6/SimpleHTTPServer.py,有兴趣可看看

1 """Simple HTTP Server.  2   3 This module builds on BaseHTTPServer by implementing the standard GET  4 and HEAD requests in a fairly straightforward manner.  5   6 """  7   8   9 __version__ = "0.6" 10  11 __all__ = ["SimpleHTTPRequestHandler"] 12  13 import os 14 import posixpath 15 import BaseHTTPServer 16 import urllib 17 import cgi 18 import sys 19 import shutil 20 import mimetypes 21 try: 22     from cStringIO import StringIO 23 except ImportError: 24     from StringIO import StringIO 25  26  27 class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): 28  29     """Simple HTTP request handler with GET and HEAD commands. 30  31     This serves files from the current directory and any of its 32     subdirectories.  The MIME type for files is determined by 33     calling the .guess_type() method. 34  35     The GET and HEAD requests are identical except that the HEAD 36     request omits the actual contents of the file. 37  38     """ 39  40     server_version = "SimpleHTTP/" + __version__ 41  42     def do_GET(self): 43         """Serve a GET request.""" 44         f = self.send_head() 45         if f: 46             self.copyfile(f, self.wfile) 47             f.close() 48  49     def do_HEAD(self): 50         """Serve a HEAD request.""" 51         f = self.send_head() 52         if f: 53             f.close() 54  55     def send_head(self): 56         """Common code for GET and HEAD commands. 57  58         This sends the response code and MIME headers. 59  60         Return value is either a file object (which has to be copied 61         to the outputfile by the caller unless the command was HEAD, 62         and must be closed by the caller under all circumstances), or 63         None, in which case the caller has nothing further to do. 64  65         """ 66         path = self.translate_path(self.path) 67         f = None 68         if os.path.isdir(path): 69             if not self.path.endswith('/'): 70                 # redirect browser - doing basically what apache does 71                 self.send_response(301) 72                 self.send_header("Location", self.path + "/") 73                 self.end_headers() 74                 return None 75             for index in "index.html", "index.htm": 76                 index = os.path.join(path, index) 77                 if os.path.exists(index): 78                     path = index 79                     break 80             else: 81                 return self.list_directory(path) 82         ctype = self.guess_type(path) 83         try: 84             # Always read in binary mode. Opening files in text mode may cause 85             # newline translations, making the actual size of the content 86             # transmitted *less* than the content-length! 87             f = open(path, 'rb') 88         except IOError: 89             self.send_error(404, "File not found") 90             return None 91         self.send_response(200) 92         self.send_header("Content-type", ctype) 93         fs = os.fstat(f.fileno()) 94         self.send_header("Content-Length", str(fs[6])) 95         self.send_header("Last-Modified", self.date_time_string(fs.st_mtime)) 96         self.end_headers() 97         return f 98  99     def list_directory(self, path):100         """Helper to produce a directory listing (absent index.html).101 102         Return value is either a file object, or None (indicating an103         error).  In either case, the headers are sent, making the104         interface the same as for send_head().105 106         """107         try:108             list = os.listdir(path)109         except os.error:110             self.send_error(404, "No permission to list directory")111             return None112         list.sort(key=lambda a: a.lower())113         f = StringIO()114         displaypath = cgi.escape(urllib.unquote(self.path))115         f.write('')116         f.write("\ncreditAutoTest project  %s\n" % displaypath)117         f.write("\n

Directory listing for %s

\n" % displaypath)118 f.write("

\n
    \n")119 for name in list:120 fullname = os.path.join(path, name)121 displayname = linkname = name122 # Append / for directories or @ for symbolic links123 if os.path.isdir(fullname):124 displayname = name + "/"125 linkname = name + "/"126 if os.path.islink(fullname):127 displayname = name + "@"128 # Note: a link to a directory displays with @ and links with /129 f.write('
  • %s\n'130 % (urllib.quote(linkname), cgi.escape(displayname)))131 f.write("
\n

\n\n\n")132 length = f.tell()133 f.seek(0)134 self.send_response(200)135 encoding = sys.getfilesystemencoding()136 self.send_header("Content-type", "text/html; charset=%s" % encoding)137 self.send_header("Content-Length", str(length))138 self.end_headers()139 return f140 141 def translate_path(self, path):142 """Translate a /-separated PATH to the local filename syntax.143 144 Components that mean special things to the local file system145 (e.g. drive or directory names) are ignored. (XXX They should146 probably be diagnosed.)147 148 """149 # abandon query parameters150 path = path.split('?',1)[0]151 path = path.split('#',1)[0]152 path = posixpath.normpath(urllib.unquote(path))153 words = path.split('/')154 words = filter(None, words)155 path = os.getcwd()156 for word in words:157 drive, word = os.path.splitdrive(word)158 head, word = os.path.split(word)159 if word in (os.curdir, os.pardir): continue160 path = os.path.join(path, word)161 return path162 163 def copyfile(self, source, outputfile):164 """Copy all data between two file objects.165 166 The SOURCE argument is a file object open for reading167 (or anything with a read() method) and the DESTINATION168 argument is a file object open for writing (or169 anything with a write() method).170 171 The only reason for overriding this would be to change172 the block size or perhaps to replace newlines by CRLF173 -- note however that this the default server uses this174 to copy binary data as well.175 176 """177 shutil.copyfileobj(source, outputfile)178 179 def guess_type(self, path):180 """Guess the type of a file.181 182 Argument is a PATH (a filename).183 184 Return value is a string of the form type/subtype,185 usable for a MIME Content-type header.186 187 The default implementation looks the file's extension188 up in the table self.extensions_map, using application/octet-stream189 as a default; however it would be permissible (if190 slow) to look inside the data to make a better guess.191 192 """193 194 base, ext = posixpath.splitext(path)195 if ext in self.extensions_map:196 return self.extensions_map[ext]197 ext = ext.lower()198 if ext in self.extensions_map:199 return self.extensions_map[ext]200 else:201 return self.extensions_map['']202 203 if not mimetypes.inited:204 mimetypes.init() # try to read system mime.types205 extensions_map = mimetypes.types_map.copy()206 extensions_map.update({207 '': 'application/octet-stream', # Default208 '.py': 'text/plain',209 '.c': 'text/plain',210 '.h': 'text/plain',211 '.log':'text/plain',212 '.out':'text/plain',213 '.sql':'text/plain',214 '.conf':'text/plain'215 })216 217 218 def test(HandlerClass = SimpleHTTPRequestHandler,219 ServerClass = BaseHTTPServer.HTTPServer):220 BaseHTTPServer.test(HandlerClass, ServerClass)221 222 223 if __name__ == '__main__':224 test()
View Code

使用方式如下:

  1. 明确需要展示web的根目录,比如/user/src
  2. 了解SimpleHTTPServer模块的几个关键参数,只说一下web服务的启动端口port。比如python -m SimpleHTTPServer port
  3. 修改一下源码web说明和支撑多种文件格式等等:

 

最后,启动web服务器:

python -m SimpleHTTPServer 8009

 小建议,一般web服务都是常驻进程,这里建议也设置为常驻进程或者添加为linux系统服务。

  • 结果展示:

 

 

 

 

转载于:https://www.cnblogs.com/xnchll/p/8472760.html

你可能感兴趣的文章
C++不完整的类型
查看>>
memcached(十三)注意事项
查看>>
ITerms2在mac系统下的安装和配色,并和go2shell关联
查看>>
nginx常见面试题1
查看>>
小白用shiro(1)
查看>>
微服务化之无状态化与容器化
查看>>
动态规划LeetCode174地下城游戏
查看>>
Sublime Text 报“Pylinter could not automatically determined the path to lint.py
查看>>
自动化测试用例getText()获取某一个元素的值返回null或空
查看>>
大数智能未来
查看>>
virtualenv和virtualenvwrapper 的安装和使用
查看>>
MAC sublime text 无法自动补齐标签
查看>>
NgBook留言本开发全过程(1)
查看>>
LeetCode-指针法
查看>>
Python之路,Day12 - 那就做个堡垒机吧
查看>>
linux之shell之if、while、for语句介绍
查看>>
Mysql phpStudy升级Mysql版本,流产了怎么办?
查看>>
SQLServer之数据库行锁
查看>>
OFDM仿真
查看>>
浅谈linux内核中内存分配函数
查看>>