Node.jsローカルHTTPサーバを構築し、node-http-proxyを適用してajaxドメイン間問題を解決する


起因:会社の製品はフロントエンドフレームを交換し、インタフェースのアクセスはもともとnginx配置の逆エージェントによって実現され、ローカルにnginxがインストールされていない場合はnodeを使用する.jsを1つ作ります.
  • node.jsがローカルhttpサーバを構築するにはshawnを参照した.xieの「nodejsローカルhttpサーバの構築」
  • node.jsはnode-http-proxyを使用して転送し、公式ドキュメント:https://github.com/nodejitsu/node-http-proxy#using-https

  • httpサーバとproxy転送の構成
    var http = require('http');
    var httpProxy = require('http-proxy');
    var fs = require('fs');
    var mine = require('./mime').types;
    var path = require('path');
    var url = require('url');
    
    var proxy = httpProxy.createProxyServer({
        target: 'https://192.168.101.166:8088',//    
        ssl: {
            key: fs.readFileSync('server_decrypt.key', 'utf8'),
            cert: fs.readFileSync('server.crt', 'utf8')
        },
        secure: false
    });
    
    proxy.on('error', function(err, req, res){
        res.writeHead(500, {
            'content-type': 'text/plain'
        });
        console.log(err);
        res.end('Something went wrong. And we are reporting a custom error message.');
    });
    
    var server = http.createServer(function(req, res){
        var pathName = url.parse(req.url).pathname;
        var realPath = req.url.substring(1);
    
        var extName = realPath;
        var indexOfQuestionMark = extName.indexOf('?');
        if(indexOfQuestionMark >= 0){
            extName = extName.substring(0, indexOfQuestionMark);
            realPath = realPath.substring(0, indexOfQuestionMark);
        }
        extName = path.extname(extName);
        extName = extName ? extName.slice(1) : 'unknown';
    
    
        //         ,   proxy  
        if(/\/svr\/.*$/.test(pathName)){
            proxy.web(req, res);
            return;
        }
    
        fs.exists(realPath, function(exists){
            if(!exists){
                res.writeHead(404, {'content-type': 'text/plain'});
                res.write('The request URL:' + realPath + ' could not be found.');
                res.end();
                return;
            }
    
            fs.readFile(realPath, 'binary', function(err, file){
                if(err){
                    res.writeHead(500, {'content-type': 'text/plain'});
                    res.end(err);
                    return;
                }
    
                var contentType = mine[extName] || 'text/plain';
                res.writeHead(200, {'content-type': contentType});
                res.write(file, 'binary');
                res.end();
            });
        });
    });
    
    server.listen(8088);

    mime.js
    ここではshawn.xieのソースコードは、いくつかのフォントファイルのmimeを補充しています.
    exports.types = {
      "css": "text/css",
      "gif": "image/gif",
      "html": "text/html",
      "ico": "image/x-icon",
      "jpeg": "image/jpeg",
      "jpg": "image/jpeg",
      "js": "text/javascript",
      "json": "application/json",
      "pdf": "application/pdf",
      "png": "image/png",
      "svg": "image/svg+xml",
      "swf": "application/x-shockwave-flash",
      "tiff": "image/tiff",
      "txt": "text/plain",
      "wav": "audio/x-wav",
      "wma": "audio/x-ms-wma",
      "wmv": "video/x-ms-wmv",
      "xml": "text/xml",
      "woff": "application/x-woff",
      "woff2": "application/x-woff2",
      "tff": "application/x-font-truetype",
      "otf": "application/x-font-opentype",
      "eot": "application/vnd.ms-fontobject"
    };

    以上はすべてのソースコードで、構成中にいくつかの問題が発生したことを説明します.
    1、インタフェースはhttpsを採用しているので、http-proxyは証明書を構成する必要があり、公式の構成によって以下の通りである.
    var proxy = httpProxy.createProxyServer({
        target: 'https://192.168.101.166:8088',
        ssl: {
            key: fs.readFileSync('server_decrypt.key', 'utf8'),
            cert: fs.readFileSync('server.crt', 'utf8')
        },
        secure: true
    });

    ここでtargetはインタフェースのIPアドレスであり、sslはkeyと証明書を構成し、secureはデフォルトでtrueであり、アクセスインタフェースを実行した後、nodeコンソールのヒント:
    { [Error: unable to verify the first certificate] code: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE' }
    Googleの後、この意味は大体証明書が検証に合格していないということで、通常nodeで検証しない証明書を構成すればいいです.
    rejectUnauthorized: false

    しかし、私はhttp-proxyを使っています.rejectUnauthorizedというパラメータはありません.ドキュメントをもう一度読みます.
    //
    // Create the proxy server listening on port 443
    //
    httpProxy.createServer({
      ssl: {
        key: fs.readFileSync('valid-ssl-key.pem', 'utf8'),
        cert: fs.readFileSync('valid-ssl-cert.pem', 'utf8')
      },
      target: 'https://localhost:9010',
      secure: true // Depends on your needs, could be false.
    }).listen(443);

    ここでsecureというパラメータの説明が曖昧で、falseに設定してみて、通過!
    2、shawn.xieのソースコードではurl中の拡張子の識別にバグがあり,例えばこのようなURL識別は最後の点の位置に取られ,本来はwoff 2であるべきであり,結果は0である.http://localhost:8000/ab/resources/fonts/font.woff2?v=4.5.0
    本来は正則で処理しようとしたが、後方引用はjsではサポートされず、おとなしくindexOfで解決した.
    var realPath = req.url.substring(1);
    var extName = realPath;
    var indexOfQuestionMark = extName.indexOf('?');
    if(indexOfQuestionMark >= 0){
        extName = extName.substring(0, indexOfQuestionMark);
        realPath = realPath.substring(0, indexOfQuestionMark);
        //realPath        ,           ?     
    }
    extName = path.extname(extName);
    extName = extName ? extName.slice(1) : 'unknown';