您好,欢迎访问一九零五行业门户网

使用nodejs、Python写的一个简易HTTP静态文件服务器_node.js

日常开发过程中,我们经常需要修改一些放在 cdn 上的静态文件(如 javascript、css、html 文件等),这个过程中,我们希望能有一种方式将线上 cdn 的目录映射为本地硬盘上的某个目录,这样,当我们在本地修改了某个文件时,不需要发布,刷新后马上能看到效果。
比如,我们的 cdn 域名是:http://a.mycdn.com,本地对应的目录是:d:\workassets,我们希望所有对 http://a.mycdn.com/* 的访问被映射到本地的 d:\workassets\* 下。如访问 http://a.mycdn.com/s/atp.js 时,实际上是读取的是本地的 d:\workassetss\atp.js,而不需要从网上下载线上的文件。
实现这个功能很简单,关键点如下:
1、在本地开启一个 http 服务,监听 80 端口;
2、修改系统 hosts 文件,添加“127.0.0.1 a.mycdn.com”,将 cdn 域名绑定为本地服务器地址;
3、配置本地 http 服务,接收到一个 get 请求后,先检查本地硬盘上是否存在对应的文件,如存在,则返回这个文件的内容,如不存在,则返回线上对应的内容。
可以看到,关键部分是需要搭建一个本地的 http 服务。这方面有很多教程,比如在本地安装 apache 或 ngnix 等服务器软件,再配置相应的转发规则等。不过个人觉得这类方法还是有点复杂,本文要介绍的,是另外的不需要安装服务器软件的方法。
因为我们是在本地开发调试,对性能、并发性的要求并不高,因此我们其实并不需要一个像 apache/ngnix 这样的专业的 http 软件,我们只需要一段能提供 http 服务的脚本即可。比如用 nodejs 来实现。
复制代码 代码如下:
/**
 * author: oldj
 *
 **/var http = require(http),
 url = require(url),
 path = require(path),
 fs = require(fs),
 local_folders,
 base_url;
local_folders = [ // 本地路径,代理将在这个列表中的目录下寻找文件,如果没有找到则转到线上地址
 d:/work/assets
];
base_url = http://10.232.133.214; // 线上路径,如果找不到文件,则转向到这个地址
function loadfile(pathname, response) {
 var i, l = local_folders.length,
  fn;
 console.log(try to load + pathname);
 for (i = 0; i
  fn = local_folders[i] + pathname;
  if (path.existssync(fn) && fs.statsync(fn).isfile()) {
   fs.readfile(fn, function (err, data) {
    response.writehead(200);
    response.write(data);
    response.end();
   });
   return;
  }
 }
 response.writehead(302, {
  location:base_url + pathname
 });
 response.end();
}
http.createserver(
 function (request, response) {
  var req_url = request.url,
   pathname;
  // 处理类似 http://a.tbcdn.cn/p/global/1.0/global-min.css,tbsp/tbsp.css?t=20110920172000.css 的请求
  pathname = req_url.indexof() == -1 ? url.parse(request.url).pathname : req_url;
  console.log(request for ' + pathname + ' received.);
  loadfile(pathname, response);
 }).listen(80);
注意将上面的 local_folders 和 base_url 两个变量的值修改为你需要的值。将这个文件保存下来,比如保存为 local-cdn-proxy.js,然后在命令行里执行“node local-cdn-proxy.js”,本地服务器就运行起来了,当然,别忘了绑定 hosts 。
当通过 http 访问一个路径时,上面的脚本会先在本地对应的目录下查找,找到则返回对应文件的内容,找不到则直接 302 跳转到线上对应的地址。对于找不到的情况,还有一种处理办法是由本地服务器从线上下载对应的内容并返回,不过对这个需求来说,302 跳转就足够了。
除了 nodejs 版本,我也写了一个 python 的版本:
复制代码 代码如下:
# -*- coding: utf-8 -*-
#
# author: oldj
#import os
import basehttpserver
local_folders = [
    d:/work/assets
]
base_url = http://10.232.133.214
class webrequesthandler(basehttpserver.basehttprequesthandler):
    def do_get(self):
        print request for '%s' received. % self.path
        for folder in local_folders:
            fn = os.path.join(folder, self.path.replace(/, os.sep)[1:])
            if os.path.isfile(fn):
                self.send_response(200)
                self.wfile.write(open(fn, rb).read())
                break
        else:
            self.send_response(302)
            self.send_header(location, %s%s % (base_url, self.path))
server = basehttpserver.httpserver((0.0.0.0, 80), webrequesthandler)
server.serve_forever()
可以看到,python 版本的代码比 nodejs 版本的精简了很多。
上面的两段代码的功能还相对比较简单,比如没有输出内容的 mime-type、content-length 等头信息,对可能的阻塞操作(如读取文件超时等)也没有做特别的处理。对于本地开发环境来说,它们已经是可以工作的版本了,你也可以继续扩展这两个脚本,以便满足更多的需求。
其它类似信息

推荐信息