python之迷你版Httpd服务器

2023-10-26

## miniHttpd.py

import os, sys, platform
import posixpath
import BaseHTTPServer
from SocketServer import ThreadingMixIn
import threading
import urllib, urllib2
import cgi
import shutil
import mimetypes
import re
import time


__version__ = "0.1"
__all__ = ["SimpleHTTPRequestHandler"]
__author__ = "bones7456"
__home_page__ = ""

try:
  from cStringIO import StringIO
except ImportError:
  from StringIO import StringIO
    
def get_ip_address(ifname):
  import socket
  import fcntl
  import struct
  s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  return socket.inet_ntoa(fcntl.ioctl(s.fileno(),0x8915,struct.pack('256s', ifname[:15]))[20:24]) # SIOCGIFADDR

class GetWanIp:
  def getip(self):
    try:
      myip = self.visit("http://ip.taobao.com/service/getIpInfo.php?ip=myip")
    except:
      print "ip.taobao.com is Error"
      try:
        myip = self.visit("http://www.bliao.com/ip.phtml")
      except:
        print "bliao.com is Error"
        try:
          myip = self.visit("http://www.whereismyip.com/")
        except: # 'NoneType' object has no attribute 'group'
          print "whereismyip is Error"
          myip = "127.0.0.1"
    return myip
  def visit(self,url):
    opener = urllib2.urlopen(url, None, 3)
    if url == opener.geturl():
      str = opener.read()
    return re.search('(\d+\.){3}\d+',str).group(0)
  
def showTips():
  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 = 8080
  # serveraddr = ('', port)
  print '-------->> Now, listening at port ' + str(port) + ' ...'
  osType = platform.system()
  if osType == "Linux":
    print '-------->> You can visit the URL:   http://'+ GetWanIp().getip() + ':' +str(port)
  else:
    print '-------->> You can visit the URL:   http://127.0.0.1:' +str(port)
  print '----------------------------------------------------------------------->> '
  print ""
  return ('', port)
  
serveraddr = showTips()  
  
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=\"http://li2z.cn/?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("              ")
    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 default; 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()



## 使用说明

miniHttpd.py

访问:http://localhost:8080/

上传图片、文件等

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python之迷你版Httpd服务器 的相关文章

  • 将 numpy float64 稀疏矩阵转换为 pandas 数据框

    我有一个n x n numpy float64 sparse matrix data where n 44 其中行和列是图节点 值是边权重 gt gt gt data lt 44x44 sparse matrix of type
  • Python OpenCV:检测大体运动方向?

    我仍在编写一个书籍扫描脚本 现在 我所需要的只是能够自动检测翻页 这本书占据了 90 的屏幕 我使用一个粗糙的网络摄像头进行运动检测 所以当我翻页时 运动方向基本上是同一个方向 我修改了一个运动跟踪脚本 但导数却无济于事 usr bin e
  • 使用 Peewee 追溯创建索引?

    有没有办法用 Peewee 追溯索引 sql 文件的列 即初始规范未建立索引的情况 询问是因为执行所有插入然后建立索引应该更快 而不是相反 有没有办法用 Peewee 追溯索引 sql 文件的列 Yes Pewee s http docs
  • 形状为 (N,1) 的数组与形状为 (N) 的数组有什么区别?以及两者之间如何转换?

    来自 MATLAB 背景的 Python 新手 我有一个 1 列数组 我想将该列移到 3 列数组的第一列中 如果我有 MATLAB 背景 我会这样做 import numpy as np A np zeros 150 3 three col
  • uWSGI 说:“ImportError:没有名为 wsgi 的模块”

    当uWSGI启动时 它会写入 ImportError No module named wsgi 我的 uwsgi xml
  • 多个 aiohttp Application() 在同一进程中运行?

    Can two aiohttp web Application 对象在同一进程中运行 例如在不同的端口上 我看到了一堆 aiohttp 代码的示例 例如 from aiohttp import web app web Application
  • Django ModelForm 不保存数据

    我已经尝试过以下帖子中的解决方案 从 ModelForm 保存数据 https stackoverflow com questions 13046488 saving data from modelform 没起作用 ModelForm数据
  • 二维高斯函数不能产生正确的结果

    我想写一个返回一个的函数np array尺寸的nx x ny包含具有均值的中心高斯分布mu and sd sig 下面的代码在某些情况下有效 但在许多情况下无效 有什么问题或者我还应该写什么来获得我需要的东西 import matplotl
  • 类型错误:fit_transform() 需要 2 个位置参数,但给出了 3 个

    我有熊猫数据框df 我想对连续和分类特征进行编码df使用不同的编码器 我觉得用起来很舒服make column transformer 但是下面显示的代码失败了LabelEncoder 但可以很好地与OneHotEncoder handle
  • 从多个 csv 文件中提取行和文件名

    我的文件夹中有多个以日期为文件名的 csv 文件 20080101 csv 到 20111031 csv csv 文件具有共同的标题 csv 文件如下所示 20080101 csv X Y Z 1 1 3 1 2 6 1 3 24 2 1
  • python 中的类变量在 __dict__ 中找不到

    有一段代码 class C a 1 def f self print f func a C print a a a f gt gt gt 1 gt gt gt f func 当我试图得到a dict or vars a 它告诉我只是 But
  • 在不同的 PC 之间传输 Python 设置

    我的情况是我有两台笔记本电脑fresh installation of windows 现在我用它们来编程 所以 假设我在一台笔记本电脑上安装了各种 python 模块 包 那么我有什么办法可以clone我的另一台笔记本电脑上的完整 pyt
  • Python 中 iter 函数的第二个参数是什么?

    让我们考虑一个文件 echo e This is a foo bar sentence nAnd this is the first txtfile in the corpus gt test txt cat test txt This i
  • 如何在 Vim 中转置文件中的行和列的内容?

    我知道我可以使用 Awk 但我使用的是 Windows 机器 并且我正在为可能没有 Awk 的其他人创建一个函数 我也知道我可以编写 C 程序 但我不希望我正在制作的 Vim 实用程序需要编译和维护 原始文件可能是 THE DAY WAS
  • 定制 odoo 中的会计和财务模块?

    我正在研究会计和财务模块 我想做一些修改 例如隐藏字段和隐藏税收图表 有人能帮我吗 请告诉我隐藏左侧菜单项 税表 的程序 我也想知道view id隐藏发票表中的税费和底部税费 更新 请让我知道隐藏它们的外部 ID 我无法找到它们 因为它们链
  • python中通过命令查找进程

    在我的 Python 脚本中 我想检查是否otherscript py目前正在 Linux 系统上运行 这psutil http psutil readthedocs io en latest 图书馆看起来是一个很好的解决方案 import
  • ImageDataGenerator 预测类 - 为什么预测未正确从概率转换为预测类?

    我有一个这样设置的目录 images val class1 class2 test all classes train class1 class2 每个目录中都有一组图像 我想预测测试中的每个图像是否属于 1 类或 2 类 我写这个是为了读
  • 使用 OpenCV 进行车牌识别

    我有一个项目 需要使用 OpenCV 识别汽车的车牌 我想加载数字或字母的图像 让 OpenCV 识别它并将其打印到控制台 有一个函数可以做到这一点吗 如果没有 我该怎么办 Note 我正在研究灰度级 请帮忙 我必须在一周后完成 谢谢你的快
  • DateField 未呈现为 type="date"

    class Form Form plan start DateField Plan Start validators Required 这段代码将渲染这个 html
  • 使用 Python 2.7 解析 msg/eml 文件

    有没有可以解析msg或eml文件的库 我编写了一个脚本 一旦将电子邮件转换为 txt 文件 就会对其进行解析 但是我找不到一个电子邮件客户端 可以让我轻松地将电子邮件从 gui 拖放到文件夹中作为 txt 文件 如果有人知道这一点 我会很高

随机推荐

  • 【数据结构】 实现 堆 结构 ---超细致解析

    目录 二叉树的性质 二叉树的存储结构 顺序存储 链式存储 堆的概念和性质 堆的实现 堆的初始化 堆的插入 向上调整函数 堆的删除 向下调整函数 向上建堆 向下建堆 TopK问题 二叉树的性质 在我们实现堆之前我们要知道堆的实现是依靠的是二叉
  • C# Thread启动线程时传递参数

    目录 1 不带参数 使用ThreadStart 2 带一个参数 使用ParameterizedThreadStart 3 带多个参数 1 不带参数 使用ThreadStart private void funcName public voi
  • Java反射学习记录

    一 反射概述 反射允许程序在运行中获取类的内部信息 例如构造器 成员变量 成员方法等 类加载之后 在堆中生成一个Class类的对象 一个类只有一个Class对象 这个对象包含类的完整结构信息 二 入门案例 通过配置文件中的内容生成指定类的对
  • 创建完整团队的艺术:敏捷如何改变我们与客户的工作方式

    来源 Ackarlix博客 http www ackarlix com 十年前 敏捷宣言 的作者们希望我们重新思考 我们作为程序员与客户协作的方式 我和我的博士学位顾问Robert Biddle以及James Noble都深受启发 充满希望
  • python --- multiprocessing实现多进程

    文章目录 进程理论知识 multiprocessing模块实现多进程 进程池 进程理论知识 进程就是正在运行的程序 是计算机进行资源分配的最小单位 各个进程都有独立的数据 相互隔离 Linux里进程的状态 R 运行状态runable S 中
  • 各种网络协议的类型、优缺点、作用

    一 网络协议的定义 网络协议是一种特殊的软件 是计算机网络实现其功能的基本机制 网络协议的本质是规则 即各种硬件和软件必须遵循的共同规则 网络协议并不是一套单独的软件 他融合于其他所有软件系统中 协议在网络中无所 不在 二 常用的网络协议
  • 24

    以下内容出自 MySQL 实战 45 讲 https time geekbang org column article 76446 24 MySQL是怎么保证主备一致的 MySQL 主备的基本原理 如图所示就是基本的主备切换流程 M S结构
  • socket可读,可写的条件

    socket可读可写条件 经常做为面试题被问 因为它考察被面试者对网络编程的基础了解的是不是够深入 要了解socket可读可写条件 我们先了解几个概念 1 接收缓存区低水位标记 用于读 和发送缓存区低水位标记 用于写 每个套接字有一个接收低
  • Oracle数据库运维、备份常用指令

    Oracle数据库运维 备份常用指令 1 Oracle数据泵备份导出 1 1 准备工作 在linux系统下创建导出结果存放的文件夹 切记要切换到oracle用户创建 否则会出现权限问题 su oracle mkdir home oracle
  • keepalived高可用服务的VIP地址无法访问

    环境 keepalived nginx实现高可用 VIP地址可以正常生成 也可正常漂移 可以实现故障切换 VIP地址只能在本地服务器ping通 其他内网服务器上无法ping通VIP地址 防火墙和selinux都已关闭 原因一 服务器启动了i
  • day37 445 数字反转 (字符串处理、模拟)

    445 数字反转 给定一个整数 请将该数各个位上数字反转得到一个新数 新数也应满足整数的常见形式 即除非给定的原数为零 否则反转后得到的新数的最高位数字不应为零 输入格式 输入共1行 1个整数N 输出格式 输出共1行 1个整数表示反转后的新
  • 集群基础7——keepalived脑裂

    文章目录 一 脑裂概念 二 脑裂产生原因 三 解决方案 四 脑裂监控 一 脑裂概念 在高可用 HA 系统中 当联系2个节点的 心跳线 断开时 本来为一整体 动作协调的HA系统 就分裂成为2个独立的个体 由于相互失去了联系 都以为是对方出了故
  • 常用 Git 命令行操作

    本文记录了一些常用 Git 命令行操作的具体使用方式 git clone git clone REPOSITORY URL 拉取仓库 并使用仓库名作为本地文件名 git clone REPOSITORY URL FOLDER 拉取仓库 并使
  • android new intent(),Android:关于onNewIntent()触发机制及注意事项

    在阅读该篇日志前 先熟悉一下Android的四种启动模式 因为onNewIntent并不是在所有启动模式下都会执行的 一 onNewIntent 在IntentActivity中重写下列方法 onCreate onStart onResta
  • Flink水位线不触发问题

    窗口计算时遇到好几次水位线不触发的情况 简单总结下 首先 介绍下Flink的事件时间 EventTime 和水位线 Watermarks 的概念 一 处理时间 如果要构造一个实时的流式应用 或早或晚都会接触到EventTime这个概念 现实
  • 用vscode写markdown的正确姿势

    写markdown一直没找到特别顺手的工具 这两天试了试vscode 被惊艳到到了 特此记录一下 1 安装vscode 之所以罗嗦一下安装 是因为安装版明显不如解压绿色版好用 特此标记一下 2 安装markdown插件 vscode默认是支
  • 机器学习——模型评估

    在学习得到的模型投放使用之前 通常需要对其进行性能评估 为此 需使用一个 测试集 testing set 来测试模型对新样本的泛化能力 然后以测试集上的 测试误差 tootino error 作为泛化误差的近似 我们假设测试集是从样本真实分
  • Shiro

    文章目录 资料 概念 基本功能 架构原理 登录认证 概念 流程 角色授权 概念 流程 代码 大致流程 shiro配置解读 ShiroConfig 登录 认证 授权 详细代码 pom login html index html UserCon
  • 表面缺陷检测的几种方法

    1 location blob feature 2 location differ feature 3 frequency domain spatial domain 4 photometric stereo 5 calibration f
  • python之迷你版Httpd服务器

    miniHttpd py import os sys platform import posixpath import BaseHTTPServer from SocketServer import ThreadingMixIn impor