【问题标题】:Node JS TypeError with `path.join` when serving webpage with Express使用 Express 提供网页时,带有“path.join”的 Node JS TypeError
【发布时间】:2013-03-11 13:12:36
【问题描述】:

我刚刚在运行 Linux Peppermint 3 的上网本上安装了 Node JS (v0.10.0)。我有一个文件要运行,顶部有以下内容:

var app = require('express').createServer(),
    io = require('socket.io').listen(app);

app.listen(8080);

// routing
app.get('/', function (req, res) {
  res.sendfile(__dirname + '/index.html');
});

问题是当我访问localhost:8080 时,我得到以下信息:

TypeError: Arguments to path.join must be strings
    at path.js:360:15
    at Array.filter (native)
    at exports.join (path.js:358:36)
    at exports.send (/home/guy/Dropbox/Node/socket_io echo test/node_modules/express/node_modules/connect/lib/middleware/static.js:129:20)
    at ServerResponse.res.sendfile (/home/guy/Dropbox/Node/socket_io echo test/node_modules/express/lib/response.js:186:3)
    at usernames (/home/guy/Dropbox/Node/socket_io echo test/med.js:11:7)
    at callbacks (/home/guy/Dropbox/Node/socket_io echo test/node_modules/express/lib/router/index.js:272:11)
    at param (/home/guy/Dropbox/Node/socket_io echo test/node_modules/express/lib/router/index.js:246:11)
    at pass (/home/guy/Dropbox/Node/socket_io echo test/node_modules/express/lib/router/index.js:253:5)
    at Router._dispatch (/home/guy/Dropbox/Node/socket_io echo test/node_modules/express/lib/router/index.js:280:5)

完全相同的文件可以在我的 Windows XP 笔记本电脑上运行,但我还没有更新 Node(仍在运行 v0.8.15)。所以我不知道是我在 Linux 上安装 Node (我是新手)的问题还是版本之间的差异。显然我不想在 Windows 上更新 Node,如果它会导致同样的问题。

我已经检查过 Express 是否在它应该在的位置,这似乎没问题。我尝试通过 npm 重新安装它。我查看了错误(通过搜索上面的第一行),发现提到了 hereherehere,似乎都说它已经解决了。

还有什么想法(如果有的话)我可以尝试让我的简单页面服务器正常工作吗?

【问题讨论】:

  • 由于您使用的是require('express').createServer(),您确定您的 Express 是最新的吗? Express 3.x 使用require('express')()。另外,如果您从名称中不包含空格的目录(socket_io test echo)运行它,请尝试查看它是否有效。您的示例在 Node 0.10.1 和 Express 3 中运行良好。
  • npm view 显示的是 NPM 注册表中包的版本,而不是你本地安装的版本;试试npm list express
  • __dirname is a Node global。在您的路由处理程序中尝试 console.log(__dirname + '/index.html') 以查看它是否实际上包含有效路径。
  • 尝试在 SO 中搜索 socket.io.js 找不到,我记得之前看到过这个问题 :)
  • 你可以回答你自己的问题,关于你是如何解决问题的。将来可能会帮助某人:)

标签: linux node.js express socket.io


【解决方案1】:

我在节点 v0.10.2 上也遇到过这种情况,同时尝试从 0.6.14 升级。问题在于连接静态中间件,以及它如何处理路径以及 path.join 如何处理其参数的可能回归。

这是来自 connect 的有问题的代码

  // setup
  var maxAge = options.maxAge || 0
    , ranges = req.headers.range
    , head = 'HEAD' == req.method
    , get = 'GET' == req.method
    , root = options.root ? normalize(options.root) : null //<!-- should be ''
    , redirect = false === options.redirect ? false : true
    , getOnly = options.getOnly
    , fn = options.callback
    , hidden = options.hidden
    , done;

后来,当路径加入时,你最终得到一个null,导致v0.10.2下的错误

  // join / normalize from optional root dir
  path = normalize(join(root, path));

在节点 0.8.21 下,你会得到这个

> require('path').join(null, 'file.txt');
'file.txt'

在节点 0.10.2 下,你会得到这个

> require('path').join(null, 'file.txt');
TypeError: Arguments to path.join must be strings
    at path.js:360:15
    at Array.filter (native)
    at Object.exports.join (path.js:358:36)
    at repl:1:17
    at REPLServer.self.eval (repl.js:110:21)
    at repl.js:249:20
    at REPLServer.self.eval (repl.js:122:7)
    at Interface.<anonymous> (repl.js:239:12)
    at Interface.EventEmitter.emit (events.js:95:17)
    at Interface._onLine (readline.js:202:10)

TL;DR

您可以同时对代码进行猴子补丁以解决该问题。

绝对路径

var filepath = '/some/absolute/path/to/file.ext';
res.sendfile(path.basename(filepath), {root: path.dirname(filepath)}); 

相对路径

res.sendfile('file.ext', {root: __dirname})

设置{root: ''} 将无法通过静态中间件中的真实测试。

【讨论】:

  • +1 用于深入挖掘连接。 @perropicante - 我可以使用下面的 guypursey 答案来解决我的问题,但是你能否提供更多关于你的方法来调试这个问题的详细信息,你是如何发现问题出在连接上的。谢谢..
  • @AnmolSaraf 不幸的是,它没有魔法。我使用了调试器,并逐步完成。我在升级之前(间接)对这个案例进行了测试,发现它们失败了,所以我尝试了一些类似的极端案例,并将其缩小到require('path').join(null, 'file.txt');
【解决方案2】:

问题似乎是与新版本的 Node.js 不兼容。我必须将 Express 更新到 v3.1.0,将 Socket.IO 更新到 v9.1.13。然后,我还必须将我的 Windows 笔记本电脑上的 NodeJS 更新到安装在我的 Linux 上网本上的最新版本 v0.10.1。

随着两台计算机上的所有内容都是最新的,代码(如上所述)需要更改为以下内容:

var app = require('express')(),
    server = require('http').createServer(app),
    io = require('socket.io').listen(server);

server.listen(8080);

// routing
app.get('/', function (req, res) {
    res.sendfile(__dirname + '/index.html');
});

注意这里直接调用 Express 模块,而不是之前使用的方法调用。另请注意,IO 必须侦听围绕 Express 调用创建的 server(即,不是我之前的 app);这解决了让 Socket.IO 脚本在客户端启动的一些问题。在撰写本文时,我仍然don't fully understand how the script is accessed given where the page is being served from。当我知道更多时,我会尝试回来更新。

PS。我很感谢@robertklep,他指导我完成了这件事,正如您在上面的 cmets 中可能看到的那样。谢谢!

【讨论】:

    【解决方案3】:

    快速修复

    sed -i bak -e  's/\/\/.join/if(root\ ==\ null){root="";}\/\//g' node_modules/express/node_modules/connect/lib/middleware/static.js
    

    【讨论】:

      猜你喜欢
      • 2013-07-23
      • 2014-11-18
      • 1970-01-01
      • 2013-09-27
      • 1970-01-01
      • 2013-07-02
      • 2017-07-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多