During the daily development process, we often need to modify some static files placed on the CDN (such as JavaScript, CSS, HTML files, etc.). In this process, we hope to have a way to map the online CDN directory to a directory on the local hard disk. In this way, when we modify a file locally, we do not need to publish it, and we can see the effect immediately after refreshing.
For example, our CDN domain name is: http://a.mycdn.com, and the local corresponding directory is: D:/workassets. We hope that all accesses to http://a.mycdn.com/* will be mapped to the local D:/workassets/*. For example, when visiting http://a.mycdn.com/s/atp.js, you actually read the local D:/workassetss/atp.js without downloading online files from the Internet.
It is very simple to implement this function, the key points are as follows:
1. Open an HTTP service locally and listen to port 80;
2. Modify the system hosts file, add "127.0.0.1 a.mycdn.com", and bind the CDN domain name to the local server address;
3. Configure the local HTTP service. After receiving a GET request, check whether the corresponding file exists on the local hard disk. If it exists, return the content of the file. If it does not exist, return the corresponding content on the line.
As you can see, the key part is to build a local HTTP service. There are many tutorials in this regard, such as installing server software such as Apache or Ngnix locally, and then configuring corresponding forwarding rules. However, I personally think this method is still a bit complicated. What I want to introduce in this article is another method that does not require the installation of server software.
Because we are developing and debugging locally, we do not have high requirements for performance and concurrency, so we actually do not need a professional HTTP software like Apache/Ngnix. We only need a script that can provide HTTP services. For example, use nodejs to implement it.
The code copy is as follows:
/**
* author: oldj
*
**/
var http = require("http"),
url = require("url"),
path = require("path"),
fs = require("fs"),
local_folders,
base_url;
local_folders = [ // Local path, the agent will look for the file in the directory in this list, if not found, go to the online address
"D:/work/assets"
];
base_url = "http://10.232.133.214"; // Online path, if the file cannot be found, then turn to this address
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;
// Handle requests similar to 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);
Note that you change the values of the local_folders and base_url variables above to the values you need. Save this file, for example, save it as local-cdn-proxy.js, and then execute "node local-cdn-proxy.js" on the command line, and the local server will run. Of course, don't forget to bind hosts.
When accessing a path through http, the above script will first search in the corresponding local directory. If it is found, it will return the content of the corresponding file. If it is not found, it will jump directly to the corresponding address on the line. For situations where it cannot be found, there is another way to deal with it. The local server downloads the corresponding content from the online and returns it. However, for this requirement, a 302 jump is enough.
In addition to the nodejs version, I also wrote a Python version:
The code copy is as follows:
# -*- 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()
As you can see, the code in the Python version is much simpler than that in the nodejs version.
The functions of the above two codes are relatively simple, such as MIME-Type, Content-Length and other header information without output content, and no special processing is done for possible blocking operations (such as reading file timeout, etc.). For local development environments, they are already working versions, and you can continue to extend these two scripts to meet more needs.