Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doubled up the filepaths in Windows #125

Closed
UltCombo opened this issue Jul 16, 2014 · 15 comments · Fixed by #126
Closed

Doubled up the filepaths in Windows #125

UltCombo opened this issue Jul 16, 2014 · 15 comments · Fixed by #126

Comments

@UltCombo
Copy link

Test case

Project root is at C:\tests\node-static-test.

Creating a new static.Server() passing './public', 'public' or path.join(process.cwd(), 'public') results in this error when requesting /hello.html:

{ [Error: ENOENT, open 'c:\tests\node-static-test\public\hello.html\c:\tests\node-static-test\public\hello.html']
  errno: -4058,
  code: 'ENOENT',
  path: 'c:\\tests\\node-static-test\\public\\hello.html\\c:\\tests\\node-static-test\\public\\hello.html' }

These tests are against the latest commit (beb25d3) in this repository, by the way.

@phstc
Copy link
Collaborator

phstc commented Jul 16, 2014

@mrfabbri any ideas? #124?

@UltCombo
Copy link
Author

The issue seems to be here:

file = file[0] === '/' ? file : path.join(pathname || '.', file);

Both pathname and file contain the full path to the file. I'll try to check the call stack for how these paths are being obtained, there is most likely a breaking change in the native Node API.

@UltCombo UltCombo changed the title Node 0.11.x on Windows doubles up the filepaths Doubled up the filepaths in Windows Jul 17, 2014
@UltCombo
Copy link
Author

The issue is reproducible using Node 0.10 as well, I've updated the issue report.

Weirdly enough, downgrading to the current stable release (0.7.3), file is undefined and pathname is null, so the control flow does not enter this conditional where the bug resides.

@mrfabbri
Copy link
Contributor

@phstc as @UltCombo mentioned the issue lies in

file = file[0] === '/' ? file : path.join(pathname || '.', file);
and it is triggered by the change from pathname to key (which, if pathname is null, becomes file[0] ) in 3bdf0d7 .

As far as I understand key shouldn't be needed any more (leftover from old caching). Also the line

file = file[0] === '/' ? file : path.join(pathname || '.', file);

checks if file is absolute but the check holds only on UNIXes.

@UltCombo
Copy link
Author

Thanks for the quick bug tracking @mrfabbri!
As I'm not familiar with this project, I've been getting lost easily in the logic flow for some reason while trying to trace this issue.

As for the absolute paths checking, we should be able to use one of the answers in this topic. Peoro's answer seems to be more robust yet still simple.

@phstc
Copy link
Collaborator

phstc commented Jul 17, 2014

@mrfabbri awesome bug tracking. 🍻

As far as I understand key shouldn't be needed any more (leftover from old caching

Isn't the key == pathname?

key = pathname || files[0]

cc/ @IonicaBizau

@IonicaBizau
Copy link
Contributor

I'm not a Windows user, but I can recommend you to check if the issue existed before my change:

$ git clone [email protected]:cloudhead/node-static.git
$ cd node-static 
$ git reset --hard 4858a8212c580fa831b9614825275f38791df579
$ npm install
$ npm test

Also, the tests are passing on Ubuntu 14.04 (using the current release):

ionicabizau@laptop:~/node-static$ npm test

> [email protected] test /home/ionicabizau/node-static
> vows --spec --isolate


  ♢ node-static 

  once an http server is listening with a callback
    ✓ should be listening
  streaming a 404 page
    ✓ should respond with 404
    ✓ should respond with the streamed content
  once an http server is listening without a callback
    ✓ should be listening
  requesting a file not found
    ✓ should respond with 404
  requesting a malformed URI
    ✓ should respond with 400
  serving hello.txt
    ✓ should respond with 200
    ✓ should respond with text/plain
    ✓ should respond with hello world
  serving directory index
    ✓ should respond with 200
    ✓ should respond with text/html
  serving index.html from the cache
    ✓ should respond with 200
    ✓ should respond with text/html
  requesting with If-None-Match
    ✓ should respond with 304
  requesting with If-None-Match and If-Modified-Since
    ✓ should respond with a 200
  requesting POST
    ✓ should respond with 200
    ✓ should not be empty
  requesting HEAD
    ✓ should respond with 200
    ✓ head must has no body
  requesting headers
    ✓ should respond with node-static/0.7.3
  addings custom mime types
    ✓ should add woff
  serving subdirectory index
    ✓ should respond with 200
    ✓ should respond with text/html
  redirecting to subdirectory index
    ✓ should respond with 301
    ✓ should respond with location header
    ✓ should respond with empty string body
  requesting a subdirectory (with trailing slash) not found
    ✓ should respond with 404
  requesting a subdirectory (without trailing slash) not found
    ✓ should respond with 404

✓ OK » 28 honored (0.151s) 

@UltCombo
Copy link
Author

@IonicaBizau the commit 4858a8212c580fa831b9614825275f38791df579 corresponds to the 0.7.3 stable release, right? My test case works as expected with 0.7.3 as I've commented above.

@mrfabbri
Copy link
Contributor

@IonicaBizau tests result on Windows 7 for commit 7f655b1 are not passing (tests on previous commit 4c64f0c are passing, also tests 4858a82 v0.7.3 are passing)

C:\Workspace\node-static>npm test

> [email protected] test C:\Workspace\node-static
> vows --spec --isolate


  ♢ node-static

  once an http server is listening with a callback
    ✓ should be listening
  streaming a 404 page
    ✓ should respond with 404
    ✓ should respond with the streamed content
  once an http server is listening without a callback
    ✓ should be listening
  requesting a file not found
    ✓ should respond with 404
  requesting a malformed URI
    ✓ should respond with 400
{ [Error: ENOENT, open 'c:\Workspace\node-static\test\fixtures\hello.txt\c:\Work
space\node-static\test\fixtures\hello.txt']
  errno: -4058,
  code: 'ENOENT',
  path: 'c:\\Workspace\\node-static\\test\\fixtures\\hello.txt\\c:\\Workspace\\n
ode-static\\test\\fixtures\\hello.txt' }
  serving hello.txt
    ✗ should respond with 200
        » expected 200,
        got      500 (==) // node-static-test.js:104
    ✗ should respond with text/plain
        » expected 'text/plain',
        got      undefined (==) // node-static-test.js:107
    ✗ should respond with hello world
        »
        actual expected

        hello world
         // node-static-test.js:110
{ [Error: ENOENT, open 'c:\Workspace\node-static\test\fixtures\index.html\c:\Wor
kspace\node-static\test\fixtures\index.html']
  errno: -4058,
  code: 'ENOENT',
  path: 'c:\\Workspace\\node-static\\test\\fixtures\\index.html\\c:\\Workspace\\
node-static\\test\\fixtures\\index.html' }
  serving directory index
    ✗ should respond with 200
        » expected 200,
        got      500 (==) // node-static-test.js:119
    ✗ should respond with text/html
        » expected 'text/html',
        got      undefined (==) // node-static-test.js:122
{ [Error: ENOENT, open 'c:\Workspace\node-static\test\fixtures\index.html\c:\Wor
kspace\node-static\test\fixtures\index.html']
  errno: -4058,
  code: 'ENOENT',
  path: 'c:\\Workspace\\node-static\\test\\fixtures\\index.html\\c:\\Workspace\\
node-static\\test\\fixtures\\index.html' }
  serving index.html from the cache
    ✗ should respond with 200
        » expected 200,
        got      500 (==) // node-static-test.js:131
    ✗ should respond with text/html
        » expected 'text/html',
        got      undefined (==) // node-static-test.js:134
{ [Error: ENOENT, open 'c:\Workspace\node-static\test\fixtures\index.html\c:\Wor
kspace\node-static\test\fixtures\index.html']
  errno: -4058,
  code: 'ENOENT',
  path: 'c:\\Workspace\\node-static\\test\\fixtures\\index.html\\c:\\Workspace\\
node-static\\test\\fixtures\\index.html' }
{ [Error: ENOENT, open 'c:\Workspace\node-static\test\fixtures\index.html\c:\Wor
kspace\node-static\test\fixtures\index.html']
  errno: -4058,
  code: 'ENOENT',
  path: 'c:\\Workspace\\node-static\\test\\fixtures\\index.html\\c:\\Workspace\\
node-static\\test\\fixtures\\index.html' }
{ [Error: ENOENT, open 'c:\Workspace\node-static\test\fixtures\index.html\c:\Wor
kspace\node-static\test\fixtures\index.html']
  errno: -4058,
  code: 'ENOENT',
  path: 'c:\\Workspace\\node-static\\test\\fixtures\\index.html\\c:\\Workspace\\
node-static\\test\\fixtures\\index.html' }
{ [Error: ENOENT, open 'c:\Workspace\node-static\test\fixtures\index.html\c:\Wor
kspace\node-static\test\fixtures\index.html']
  errno: -4058,
  code: 'ENOENT',
  path: 'c:\\Workspace\\node-static\\test\\fixtures\\index.html\\c:\\Workspace\\
node-static\\test\\fixtures\\index.html' }
  requesting with If-None-Match
    ✗ should respond with 304
        » expected 304,
        got      500 (==) // node-static-test.js:151
  requesting with If-None-Match and If-Modified-Since
    ✗ should respond with a 200
        » expected 200,
        got      500 (==) // node-static-test.js:173
{ [Error: ENOENT, open 'c:\Workspace\node-static\test\fixtures\index.html\c:\Wor
kspace\node-static\test\fixtures\index.html']
  errno: -4058,
  code: 'ENOENT',
  path: 'c:\\Workspace\\node-static\\test\\fixtures\\index.html\\c:\\Workspace\\
node-static\\test\\fixtures\\index.html' }
  requesting POST
    ✗ should respond with 200
        » expected 200,
        got      500 (==) // node-static-test.js:183
    ✗ should not be empty
        » expected '' to be not empty // node-static-test.js:186
{ [Error: ENOENT, open 'c:\Workspace\node-static\test\fixtures\index.html\c:\Wor
kspace\node-static\test\fixtures\index.html']
  errno: -4058,
  code: 'ENOENT',
  path: 'c:\\Workspace\\node-static\\test\\fixtures\\index.html\\c:\\Workspace\\
node-static\\test\\fixtures\\index.html' }
  requesting HEAD
    ✗ should respond with 200
        » expected 200,
        got      500 (==) // node-static-test.js:196
    ✓ head must has no body
{ [Error: ENOENT, open 'c:\Workspace\node-static\test\fixtures\index.html\c:\Wor
kspace\node-static\test\fixtures\index.html']
  errno: -4058,
  code: 'ENOENT',
  path: 'c:\\Workspace\\node-static\\test\\fixtures\\index.html\\c:\\Workspace\\
node-static\\test\\fixtures\\index.html' }
  requesting headers
    ✓ should respond with node-static/0.7.3
  addings custom mime types
    ✓ should add woff
{ [Error: ENOENT, open 'c:\Workspace\node-static\test\fixtures\there\index.html\
c:\Workspace\node-static\test\fixtures\there\index.html']
  errno: -4058,
  code: 'ENOENT',
  path: 'c:\\Workspace\\node-static\\test\\fixtures\\there\\index.html\\c:\\Work
space\\node-static\\test\\fixtures\\there\\index.html' }
  serving subdirectory index
    ✗ should respond with 200
        » expected 200,
        got      500 (==) // node-static-test.js:221
    ✗ should respond with text/html
        » expected 'text/html',
        got      undefined (==) // node-static-test.js:224
  redirecting to subdirectory index
    ✓ should respond with 301
    ✓ should respond with location header
    ✓ should respond with empty string body
  requesting a subdirectory (with trailing slash) not found
    ✓ should respond with 404
  requesting a subdirectory (without trailing slash) not found
    ✓ should respond with 404
util.print: Use console.log instead

✗ Broken » 14 honored ∙ 14 broken (0.308s)

npm ERR! Test failed.  See above for more details.
npm ERR! not ok code 0

C:\Workspace\node-static>

@IonicaBizau
Copy link
Contributor

I installed Windows 7 in my VBox. The tests fail when using key instead of filepath and there is one error when filepath is used.


Cannot reproduce the issue with serving hello.html:

var static = require('node-static');
// var Path = require("path");
// var file = new static.Server(Path.join(process.cwd(), 'public'), { cache: 7200, headers: {'X-Hello':'World!'} });
var file = new static.Server('./public', { cache: 7200, headers: {'X-Hello':'World!'} });
require('http').createServer(function (request, response) {
    file.serve(request, response, function (err, res) {
        if (err) {
       console.error("> Error serving " + request.url + " - " + err.message);
           response.writeHead(err.status, err.headers);
           response.end();
        } else {
           console.log("> " + request.url + " - " + res.message);
        }
    });
}).listen(8080);
console.log("> node-static is listening on http://127.0.0.1:8080");

The file is correctly served in both cases.

Relevant output:

C:\Users\John\Documents\node-static [master +1 ~1 -0 !]> npm test



> [email protected] test C:\Users\John\Documents\node-static
> vows --spec --isolate


  ? node-static

  once an http server is listening with a callback
    √ should be listening
  streaming a 404 page
    √ should respond with 404
    √ should respond with the streamed content
  once an http server is listening without a callback
    √ should be listening
  requesting a file not found
    √ should respond with 404
  requesting a malformed URI
    √ should respond with 400
  serving hello.txt
    √ should respond with 200
    √ should respond with text/plain
    √ should respond with hello world
  serving directory index
    √ should respond with 200
    √ should respond with text/html
  serving index.html from the cache
    √ should respond with 200
    √ should respond with text/html
  requesting with If-None-Match
    √ should respond with 304
  requesting with If-None-Match and If-Modified-Since
    √ -should respond with a 200
  requesting POST
    √ should respond with 200
    √ should not be empty
  requesting HEAD
    √ should respond with 200
    √ head must has no body
  requesting headers
    √ should respond with node-static/0.7.3
  addings custom mime types
    √ should add woff
  serving subdirectory index
    √ should respond with 200
    √ should respond with text/html
  redirecting to subdirectory index
    √ should respond with 301
    √ should respond with location header
    √ should respond with empty string body
  requesting a subdirectory (with trailing slash) not found
    √ should respond with 404

? Errored » 1 errored (0.000s)

npm ERR! Test failed.  See above for more details.
npm ERR! not ok code 0
C:\Users\John\Documents\node-static [master +1 ~1 -0 !]>
C:\Users\John\Documents\node-static [master +1 ~1 -0 !]> git diff
diff --git a/lib/node-static.js b/lib/node-static.js
index ebb748b..d40eac5 100644
--- a/lib/node-static.js
+++ b/lib/node-static.js
@@ -269,8 +269,8 @@ Server.prototype.respondNoGzip = function (pathname, status,
         finish(304, headers);
     } else {
         res.writeHead(status, headers);
-
-        this.stream(key, files, new(buffer.Buffer)(stat.size), res, function (e
+        debugger
+        this.stream(pathname, files, new(buffer.Buffer)(stat.size), res, functi
             if (e) { return finish(500, {}) }
             finish(status, headers);
         });
C:\Users\John\Documents\node-static [master +1 ~1 -0 !]> git checkout .
C:\Users\John\Documents\node-static [master +1 ~0 -0 !]> npm test

> [email protected] test C:\Users\John\Documents\node-static
> vows --spec --isolate

  ? node-static

  once an http server is listening with a callback
    √ should be listening
  streaming a 404 page
    √ should respond with 404
    √ should respond with the streamed content
  once an http server is listening without a callback
    √ should be listening
  requesting a file not found
    √ should respond with 404
{ [Error: ENOENT, open 'C:\Users\John\Documents\node-static\test\fixtures\hello.
txt\C:\Users\John\Documents\node-static\test\fixtures\hello.txt']
  errno: 34,
  code: 'ENOENT',
  path: 'C:\\Users\\John\\Documents\\node-static\\test\\fixtures\\hello.txt\\C:\
\Users\\John\\Documents\\node-static\\test\\fixtures\\hello.txt' }
  requesting a malformed URI
    √ should respond with 400
{ [Error: ENOENT, open 'C:\Users\John\Documents\node-static\test\fixtures\index.
html\C:\Users\John\Documents\node-static\test\fixtures\index.html']
  errno: 34,
  code: 'ENOENT',
  path: 'C:\\Users\\John\\Documents\\node-static\\test\\fixtures\\index.html\\C:
\\Users\\John\\Documents\\node-static\\test\\fixtures\\index.html' }
  serving hello.txt
    ? should respond with 200
        » expected 200,
        got      500 (==) // node-static-test.js:104
    ? should respond with text/plain
        » expected .,
        got      undefined (==) // node-static-test.js:107
    ? should respond with hello world
        »
        actual expected

        hello world
         // node-static-test.js:110
{ [Error: ENOENT, open 'C:\Users\John\Documents\node-static\test\fixtures\index.
html\C:\Users\John\Documents\node-static\test\fixtures\index.html']
  errno: 34,
  code: 'ENOENT',
  path: 'C:\\Users\\John\\Documents\\node-static\\test\\fixtures\\index.html\\C:
\\Users\\John\\Documents\\node-static\\test\\fixtures\\index.html' }
  serving directory index
    ? should respond with 200
        » expected 200,
        got      500 (==) // node-static-test.js:119
    ? should respond with text/html
        » expected .,
        got      undefined (==) // node-static-test.js:122
  serving index.html from the cache
{ [Error: ENOENT, open 'C:\Users\John\Documents\node-static\test\fixtures\index.
html\C:\Users\John\Documents\node-static\test\fixtures\index.html']
  errno: 34,
  code: 'ENOENT',
  path: 'C:\\Users\\John\\Documents\\node-static\\test\\fixtures\\index.html\\C:
\\Users\\John\\Documents\\node-static\\test\\fixtures\\index.html' }
    ? should respond with 200
        » expected 200,
        got      500 (==) // node-static-test.js:131
    ? should respond with text/html
        » expected .,
        got      undefined (==) // node-static-test.js:134
{ [Error: ENOENT, open 'C:\Users\John\Documents\node-static\test\fixtures\index.
html\C:\Users\John\Documents\node-static\test\fixtures\index.html']
  errno: 34,
  code: 'ENOENT',
  path: 'C:\\Users\\John\\Documents\\node-static\\test\\fixtures\\index.html\\C:
\\Users\\John\\Documents\\node-static\\test\\fixtures\\index.html' }
{ [Error: ENOENT, open 'C:\Users\John\Documents\node-static\test\fixtures\index.
html\C:\Users\John\Documents\node-static\test\fixtures\index.html']
  errno: 34,
  code: 'ENOENT',
  path: 'C:\\Users\\John\\Documents\\node-static\\test\\fixtures\\index.html\\C:
\\Users\\John\\Documents\\node-static\\test\\fixtures\\index.html' }
  requesting with If-None-Match
{ [Error: ENOENT, open 'C:\Users\John\Documents\node-static\test\fixtures\index.
html\C:\Users\John\Documents\node-static\test\fixtures\index.html']
  errno: 34,
  code: 'ENOENT',
  path: 'C:\\Users\\John\\Documents\\node-static\\test\\fixtures\\index.html\\C:
\\Users\\John\\Documents\\node-static\\test\\fixtures\\index.html' }
    ? should respond with 304
        » expected 304,
        got      500 (==) // node-static-test.js:151
{ [Error: ENOENT, open 'C:\Users\John\Documents\node-static\test\fixtures\index.
html\C:\Users\John\Documents\node-static\test\fixtures\index.html']
  errno: 34,
  code: 'ENOENT',
  path: 'C:\\Users\\John\\Documents\\node-static\\test\\fixtures\\index.html\\C:
\\Users\\John\\Documents\\node-static\\test\\fixtures\\index.html' }
  requesting with If-None-Match and If-Modified-Since
    ? should respond with a 200
        » expected 200,
        got      500 (==) // node-static-test.js:173
|  requesting POST
    ? should respond with 200
        » expected 200,
        got      500 (==) // node-static-test.js:183
{ [Error: ENOENT, open 'C:\Users\John\Documents\node-static\test\fixtures\index.
html\C:\Users\John\Documents\node-static\test\fixtures\index.html']
  errno: 34,
  code: 'ENOENT',
  path: 'C:\\Users\\John\\Documents\\node-static\\test\\fixtures\\index.html\\C:
\\Users\\John\\Documents\\node-static\\test\\fixtures\\index.html' }
    ? should not be empty
        » expected . to be not empty // node-static-test.js:186
  requesting HEAD
    ? should respond with 200
        » expected 200,
        got      500 (==) // node-static-test.js:196
{ [Error: ENOENT, open 'C:\Users\John\Documents\node-static\test\fixtures\index.
html\C:\Users\John\Documents\node-static\test\fixtures\index.html']
  errno: 34,
  code: 'ENOENT',
  path: 'C:\\Users\\John\\Documents\\node-static\\test\\fixtures\\index.html\\C:
\\Users\\John\\Documents\\node-static\\test\\fixtures\\index.html' }
    √ head must has no body
  requesting headers
    √ should respond with node-static/0.7.3
  addings custom mime types
    √ should add woff
{ [Error: ENOENT, open 'C:\Users\John\Documents\node-static\test\fixtures\there\
index.html\C:\Users\John\Documents\node-static\test\fixtures\there\index.html']
  errno: 34,
  code: 'ENOENT',
  path: 'C:\\Users\\John\\Documents\\node-static\\test\\fixtures\\there\\index.h
tml\\C:\\Users\\John\\Documents\\node-static\\test\\fixtures\\there\\index.html'
 }
  serving subdirectory index
    ? should respond with 200
        » expected 200,
        got      500 (==) // node-static-test.js:221
    ? should respond with text/html
        » expected ..,
        got      undefined (==) // node-static-test.js:224
  redirecting to subdirectory index
    √ should respond with 301
    √ should respond with location header
    √ should respond with empty string body
  requesting a subdirectory (with trailing slash) not found
    √ should respond with 404

? Errored » 1 errored (0.000s)

npm ERR! Test failed.  See above for more details.
npm ERR! not ok code 0

@IonicaBizau
Copy link
Contributor

@UltCombo Can you provide a zip file containing the project that reproduces the issue?

@UltCombo
Copy link
Author

@IonicaBizau

git clone https://github.com/UltCombo/node-static-test-125.git
cd node-static-test-125
npm install
node index.js

Then open http://localhost:8080/hello.html and hard refresh (Ctrl+F5). Issue happens when running node-static in Windows with the latest commit.

@UltCombo
Copy link
Author

Note that although I'm using an absolute path -- path.join(process.cwd(), 'public') -- in the test case above, './public' would also throw the same error.

@IonicaBizau
Copy link
Contributor

Yes, seems that pathname is null and key becomes files[0].

@IonicaBizau
Copy link
Contributor

I added a little fix for checking if path is absolute. Is it enough? See pull request #126.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants