开发环境中将线上路径映射到本地路径的方法

本文介绍了一种在本地开发环境中将线上CDN资源映射到本地目录的方法,通过简单的Node.js或Python脚本实现HTTP服务,使得修改本地文件后无需发布即可立即生效。

  日常开发过程中,我们经常需要修改一些放在 CDN 上的静态文件(如 JavaScript、CSS、HTML 文件等),这个过程中,我们希望能有一种方式将线上 CDN 的目录映射为本地硬盘上的某个目录,这样,当我们在本地修改了某个文件时,不需要发布,刷新后马上能看到效果。

  比如,我们的 CDN 域名是:http://a.mycdn.com,本地对应的目录是:D:\work\assets,我们希望所有对 http://a.mycdn.com/* 的访问被映射到本地的 D:\work\assets\* 下。如访问 http://a.mycdn.com/s/atp.js 时,实际上是读取的是本地的 D:\work\assets\s\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 来实现。

01/**
02 * author: oldj
03 * blog: http://oldj.net
04 *
05 **/
06 
07var http = require("http"),
08    url = require("url"),
09    path = require("path"),
10    fs = require("fs"),
11    local_folders,
12    base_url;
13 
14local_folders = [ // 本地路径,代理将在这个列表中的目录下寻找文件,如果没有找到则转到线上地址
15    "D:/work/assets"
16];
17base_url = "http://10.232.133.214"; // 线上路径,如果找不到文件,则转向到这个地址
18 
19 
20function loadFile(pathname, response) {
21    var i, l = local_folders.length,
22        fn;
23 
24    console.log("try to load " + pathname);
25 
26    for (i = 0; i < l; i++) {
27 
28        fn = local_folders[i] + pathname;
29        if (path.existsSync(fn) && fs.statSync(fn).isFile()) {
30            fs.readFile(fn, function (err, data) {
31                response.writeHead(200);
32                response.write(data);
33                response.end();
34            });
35 
36            return;
37        }
38 
39    }
40 
41    response.writeHead(302, {
42        "Location":base_url + pathname
43    });
44    response.end();
45}
46 
47http.createServer(
48    function (request, response) {
49 
50        var req_url = request.url,
51            pathname;
52 
53        // 处理类似 http://a.tbcdn.cn/??p/global/1.0/global-min.css,tbsp/tbsp.css?t=20110920172000.css 的请求
54        pathname = req_url.indexOf("??") == -1 ? url.parse(request.url).pathname : req_url;
55        console.log("Request for '" + pathname + "' received.");
56        loadFile(pathname, response);
57 
58    }).listen(80);

  注意将上面的 local_folders 和 base_url 两个变量的值修改为你需要的值。将这个文件保存下来,比如保存为 local-cdn-proxy.js,然后在命令行里执行“node local-cdn-proxy.js”,本地服务器就运行起来了,当然,别忘了绑定 hosts 。

  当通过 http 访问一个路径时,上面的脚本会先在本地对应的目录下查找,找到则返回对应文件的内容,找不到则直接 302 跳转到线上对应的地址。对于找不到的情况,还有一种处理办法是由本地服务器从线上下载对应的内容并返回,不过对这个需求来说,302 跳转就足够了。

  除了 nodejs 版本,我也写了一个 Python 的版本:

01# -*- coding: utf-8 -*-
02#
03# author: oldj
04# blog: http://oldj.net
05#
06 
07import os
08import BaseHTTPServer
09 
10LOCAL_FOLDERS = [
11    "D:/work/assets"
12]
13BASE_URL = "http://10.232.133.214"
14 
15class WebRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
16 
17    def do_GET(self):
18        print "Request for '%s' received." % self.path
19        for folder in LOCAL_FOLDERS:
20            fn = os.path.join(folder, self.path.replace("/", os.sep)[1:])
21            if os.path.isfile(fn):
22                self.send_response(200)
23                self.wfile.write(open(fn, "rb").read())
24                break
25 
26        else:
27            self.send_response(302)
28            self.send_header("Location""%s%s" % (BASE_URL, self.path))
29 
30server = BaseHTTPServer.HTTPServer(("0.0.0.0"80), WebRequestHandler)
31server.serve_forever()

  可以看到,Python 版本的代码比 nodejs 版本的精简了很多。

  上面的两段代码的功能还相对比较简单,比如没有输出内容的 MIME-Type、Content-Length 等头信息,对可能的阻塞操作(如读取文件超时等)也没有做特别的处理。对于本地开发环境来说,它们已经是可以工作的版本了,你也可以继续扩展这两个脚本,以便满足更多的需求。

转载于:https://my.oschina.net/shootercn/blog/58986

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值