FurtiveStranger
FurtiveStranger

Reputation: 125

url parsing in express.js

I am trying to learn express.js on my node server and I try to duplicate this same thing from the http module into express framework.

further explanation: I was using the first code before I started using express in which I have a filetree in a "site" folder with webpages such as

e:
|_node.js
   |_node_modules
   |_site
   | |_abc
   | | |_123.html
   | | |_456.html
   | | |_789.html
   | |_cde
   | | |_123.html
   | | |_456.html
   | | |_789.html
   | |_abc.html
   | |_cde.html
   |_server.js

and I normally access them in the url just by having localhost:8080/abc/123 to get /site/abc/123.html.

var http = require('http');
var url = require('url');
var fs = require('fs');
var port = 8080;

http.createServer(function (req, res) {
  var q = url.parse(req.url, true);
  var filename = "./site" + q.pathname + ".html";
  fs.readFile(filename, function(err, data) {
    if (err) {
      res.writeHead(404, {'Content-Type': 'text/html'});
      return res.end("404 Not Found");
    }  
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.write(data);
    return res.end();
  });
}).listen(port);
console.log('Running on port ' + port);

here, I tried doing this

var url = require('url');
var fs = require('fs');
var express = require('express');
var app = express();
var port = 8080;
var site = "/site"

app.get('*', function (req, res) {
  var q = url.parse(req.url, true);
  var filename = site + q.pathname + ".html";
    fs.readFile(filename, function(err, data) {
    if (err) {
      console.log(err);
      res.writeHead(404, {'Content-Type': 'text/html'});
      return res.end("404 Not Found");
    }  
    res.writeHead(200, {'Content-Type': 'text/html'});
      res.sendFile(filename, { root: __dirname + site } );
    return res.end();
  });
})

var server = app.listen(port, function () {
    console.log('Running on port ' + port);
})

but now with the express framework when I type localhost:8080/abc/123 but it only returns 404 Not Found upon typing http://localhost:8080/abc

apparently the error contains

{[Error: ENOENT: no such file or directory, open 'e:\site\abc.html']
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path: 'e:\\site\\abc.html'}

the full path should be

e:\node.js\site\abc.html

and the server.js is located in e:\node.js

why does it jumps back at e: than at e:\node.js

right now I'm guessing the "root: __dirname" is causing the error, what should i replace it with so that it would start at e:/node.js rather than e:?

Upvotes: 0

Views: 2249

Answers (2)

Geekfish
Geekfish

Reputation: 2314

This may not be the only problem but one thing is that

app.get('/', ... 

will only match the root url, so it'll match localhost:8080/ but not localhost:8080/foo or any other path.

app.get accepts a string, path pattern or regular expression.

To match anything you would need to do:

app.get('/*', ... 

or if you wanted to match only paths that start with a certain segment, you could do:

app.get('/some-path/*', ...

and that would match localhost:8080/some-path/, localhost:8080/some-path/foo, localhost:8080/some-path/bar etc.

Edit:

With regards to why you're getting the wrong file path, if you look carefully you'll see that you're only using __dirname when you are trying to send the file, but not when you're reading it!

so you have:

var filename = site + q.pathname + ".html";
    // This is not reading from the correct path -
    // it's missing __dirname!
    fs.readFile(filename, function(err, data) {

which should probably change to

var filename = __dirname + site + q.pathname + ".html";
    // This is now using __dirname which should be the
    // the directory of your server module
    fs.readFile(filename, function(err, data) {

Then further down you do not need to use sendFile since you already have the data in a variable, you could use similar code to your example:

res.writeHead(200, {'Content-Type': 'text/html'});
res.write(data);
return res.end();

Upvotes: 0

Jaime Blázquez
Jaime Blázquez

Reputation: 328

Change:

var site = "/site"

to:

var site = "site"

The root options only applies to relative file names, but a path starting with '/' is absolute to the root of the file system.

Unless you need to do something more to the files, if you're only serving them, probably is better to serve them with express.static() that can be configured to not expose the .html extensions, as answered here:

https://stackoverflow.com/a/37990843/2106611

Upvotes: 1

Related Questions