如何从 Node.js 中的 URL 请求

IT技术 javascript node.js
2021-02-22 08:23:07

是否有一种标准的方法来要求位于某个 URL(不在本地文件系统上)的 Node module?

就像是:

require('http://example.com/nodejsmodules/myModule.js');

目前,我只是将文件提取到一个临时文件中,并要求这样做。

6个回答

您可以使用http.get方法获取module并使用vmmodule方法runInThisContextrunInNewContext在沙箱中执行它

例子

var http = require('http')
  , vm = require('vm')
  , concat = require('concat-stream'); // this is just a helper to receive the
                                       // http payload in a single callback
                                       // see https://www.npmjs.com/package/concat-stream

http.get({
    host: 'example.com', 
    port: 80, 
    path: '/hello.js'
  }, 
  function(res) {
    res.setEncoding('utf8');
    res.pipe(concat({ encoding: 'string' }, function(remoteSrc) {
      vm.runInThisContext(remoteSrc, 'remote_modules/hello.js');
    }));
});

IMO,在没有替代方案的情况下,在服务器应用程序运行时内执行远程代码可能是合理的。并且仅当您信任远程服务和网络之间的关系时。

因此,在生产应用程序中不需要来自“github”的任何内容;)
2021-04-16 08:23:07
1. 可能代码可以通过 HTTPS 在广受信任的 CDN 中或通过可信赖的合作伙伴获得。2. 可能代码可以通过 HTTPS 在远程内部位置获得。3. 可能代码在内部打包和分发的方式是阻止访问最终执行的 FS,因此无法使用 npm。这些只是我的头顶;也许它们不是很好的理由,但它们是理由。无论如何,我的观点只是解释观点的基本原理比将其标记为“不良做法”并仅此而已更有用。你的评论现在做了什么!
2021-04-17 08:23:07
在这个时代,HTTP-GET 应该被认为是一种完全有效的引用/打开文件的方法。暗示文件在某种程度上更安全​​,因为您首先将wget它们传输到本地硬盘驱动器,这非常类似于通过默默无闻的安全性。文件的可信度不应仅通过您是通过 FILE:// 还是 HTTPS?:// 访问来衡量
2021-04-22 08:23:07
我为这些信息点赞,但我确实希望,而不是仅仅说“这是非常糟糕的做法”,您还要费心解释原因
2021-05-04 08:23:07
谢谢你的回答。至于“远程代码的执行”;如今,大多数节点应用程序都是通过npm install从网络中拉取来初始化的。这与 op 寻求在精神上做的事情有什么不同?一般来说,这个想法没有什么不好的做法,但任何事情都可能做得不好;造成安全风险。对于一个人来说,我正在做这件事来管理我的配置脚本(它不仅仅是 json,因为它需要更多的智能)并且我有轮换密钥来保护请求,但无论如何没有人知道但应用程序(更安全)比 npm module)。
2021-05-05 08:23:07

首先安装module:

npm install require-from-url

然后放入您的文件:

var requireFromUrl = require('require-from-url/sync');
requireFromUrl("http://example.com/nodejsmodules/myModule.js");
如果脚本以 gzip 格式提供,这似乎不起作用
2021-04-15 08:23:07
哇,这完全按预期工作。谢谢
2021-04-27 08:23:07

0 依赖版本(需要节点 6+,您可以简单地将其改回 ES5)

const http = require('http'), vm = require('vm');

['http://example.com/nodejsmodules/myModule.js'].forEach(url => {
    http.get(url, res => {
        if (res.statusCode === 200 && /^text\/javascript/.test(res.headers['content-type'])) {
            let rawData = '';
            res.setEncoding('utf8');
            res.on('data', chunk => { rawData += chunk; });
            res.on('end', () => { vm.runInThisContext(rawData, url); });
        }
    });
});

它仍然是异步版本,如果是同步负载,则需要sync http request module 例如

我认为你应该使用 'application/javascript' 而不是 'text/javascript' if (res.statusCode === 200 && /^application\/javascript/.test(res.headers['content-type']))
2021-05-03 08:23:07

如果你想要更像的东西require,你可以这样做:

var http = require('http')
  , vm = require('vm')
  , concat = require('concat-stream') 
  , async = require('async'); 

function http_require(url, callback) {
  http.get(url, function(res) {
    // console.log('fetching: ' + url)
    res.setEncoding('utf8');
    res.pipe(concat({encoding: 'string'}, function(data) {
      callback(null, vm.runInThisContext(data));
    }));
  })
}

urls = [
  'http://example.com/nodejsmodules/myModule1.js',
  'http://example.com/nodejsmodules/myModule2.js',
  'http://example.com/nodejsmodules/myModule3.js',
]

async.map(urls, http_require, function(err, results) {
  // `results` is an array of values returned by `runInThisContext`
  // the rest of your program logic
});

您可以覆盖 .js 文件的默认 require 处理程序:

require.extensions['.js'] = function (module, filename) {
    // ...
}

您可能想要结帐更好-需要,因为它对许多文件格式几乎都这样做。(我写的)

遗憾的是require.extensions已被弃用...
2021-04-17 08:23:07