0
点赞
收藏
分享

微信扫一扫

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


日常开发过程中,我们经常需要修改一些放在 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


 * blog: http://oldj.net


 *


 **/


                  


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         <         l         ;         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


# blog: http://oldj.net


#


                  


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 等头信息,对可能的阻塞操作(如读取文件超时等)也没有做特别的处理。对于本地开发环境来说,它们已经是可以工作的版本了,你也可以继续扩展这两个脚本,以便满足更多的需求。

举报

相关推荐

0 条评论