404 when making a request to express route - javascript

I am trying to understand express and how it handles routes.
I have a domain set up with the following structure
/
app.js
/public_html
index.html
In app.js, I set up my express server:
let app = express();
app.post('/list', (request, response) => {
//get data then...
response.send(data)
});
app.use(express.static('public_html'))
app.listen(3000, function(){
console.log('listening');
});
I run the app with node app.js
Then, in index.html in the public_html directory, I am trying to request the data. I just did a simple:
fetch('/list').then(function(response) {
console.log(response)
})
But I get a 404 as the response.
I'm a bit confused about a couple of things:
My web server (Apache / Ubuntu) is set up to serve html out of the public_html directory by default. Does that mean my whole node app structure needs to be moved into the public_html folder and the actual html moved into a static folder or something?
What about the port? The node app listens on port 3000 - but I'm not sure how (or if) to make a request to that port specifically.
Route path - I am posting to /list but should it be ../list?
I haven't yet found a configuration for this app that works yet. Any help would be appreciated.

Use following code. Use ajax instead of fetch and method must be POST. Fetch is not working as it is get request by default.
Option 1
$.ajax({
method: "POST",
url: "/list"
})
.done(function( msg ) {
alert( "Data " + msg );
});
Option 2
Change only following code => POST to GET
app.get('/list', (request, response) => {
//get data then...
response.send(data)
});
Option 3
Use POST in fetch
fetch("/list",
{
method: "POST"
})
.then(function(data){ alert( "Data " + data ); })
Thanks to #vesse for suggesting option 3
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

My web server (Apache / Ubuntu) is set up to serve html out of the public_html directory by default. Does that mean my whole node app structure needs to be moved into the public_html folder and the actual html moved into a static folder or something?
Node.js and Apache can use the same static folder without conflict, but they both cannot listen on the same port. It is likely your Apache server is already running on port 80. If your Node.js server runs on port 3000, requests to port 80 will not match routes you write in your app and thus 404 will return (unless of course you had the same routes in a separate Apache hosted application).
What about the port? The node app listens on port 3000 - but I'm not sure how (or if) to make a request to that port specifically.
Since Apache is probably already listening on port 80, any request you send to http://localhost will hit your Apache server. Instead, you must make requests that include a port number, http://localhost:3000 will hit your Node.js server.
Route path - I am posting to /list but should it be ../list?
No, you should post to /list and also regard all the points Rakesh made in his answer so that you correctly match POST to POST from client to server or switch to GET if that's more appropriate. As in the second point, be sure you are posting to http://localhost:3000 and not just http://localhost. As you pointed out, one is Apache and the other is Node.js
Finally, here's the static server line of code I use when serving from a folder that is adjacent to my app script:
app.use('/', express.static(__dirname + '/public_html'));
With this, all files you put in the public_html folder become navigable in your application, which includes everything Apache related as well. Note __dirname is the always the directory from which the currently executing script is run. To visit this site, simply go to http://localhost:3000 in your browser and you should see your index file.

Related

Issues with linking Javascript files with Node.js and HTML

I am making an application with node.js and I basically want render a canvas with node.js so I can access a json file on the server since you can't change client storage on browsers. To add on when running my files I get this weird syntax error.
Uncaught SyntaxError: Unexpected token '<'
Further examination shows that my javascript files that I am requiring (see internals folder) are being overwritten with html, thus causing the error. My question is why is it overwritting only the files I am requiring from the html I am rendering? To add on I am running on a dynamic port (65535) and on a localhost (client). My code is here
Your node server is not serving your static files, it only serves one html.
You might need to set up a static file server like or programm you server to lookup GET /internals/render.js and scaleCanvas.js
You can use express for that, it has all this out of the box.
https://expressjs.com/en/starter/static-files.html
var app, server,
express = require('express'),
path = require('path'),
host = process.env.HOST || '127.0.0.1',
port = process.env.PORT || 3000,
root = path.resolve(__dirname, '..');
app = express()
app.use(express.static(root + '/public'));
server = app.listen(port, host, serverStarted);
function serverStarted () {
console.log('Server started', host, port);
console.log('Root directory', root);
console.log('Press Ctrl+C to exit...\n');
}
This is because you are sending the index.html file for all requests in your app.js file, ignoring the request URL.
You need to properly serve the JS files. You can take a look here for more details: https://nodejs.org/en/knowledge/HTTP/servers/how-to-serve-static-files/

Why is my Express server responding with 404 for all files except index.html?

I'm learning Node.js with Express to get a little server running for studying. I'm getting response code 404 for all requests to files linked in my index.html file (e.g. the .css, .js, and image files).
The code I used to send index.html:
routes.get('/', (req, res) => {
res.sendFile(path.join(__dirname, "/clientSide/index.html"));
})
If I change the path to the whole folder instead:
routes.get('/', (req, res) => {
res.sendFile(path.join(__dirname, "/clientSide"));
})
I get in my browser the path from my hard drive to the folder, but I still can't view the files that way.
The clientSide folder contains index.html, app.js, style.css, and 2 or 3 images, all in the same folder. I can't view any of them.
I changed the filenames and folder name, and checked for capitalization to no avail.
SOLVED
I was using app.use(express.static(path.join(__dirname, "static/")));
With app = express();
That does not work, but using routes.use instead of app.use, while routes = express.Router();, is what solves that
The end
In your first code snippet, when you write:
routes.get('/', (req, res) => {
res.sendFile(path.join(__dirname, "/clientSide/index.html"));
})
You defined a new middleware function for requests to route /; that's what routes.get('/', ...) does. Assuming your server is running on port 3000, route / maps to http://127.0.0.1:3000/. For exactly that URL, and no other, Express executes your provided function, which replies with the the file clientSide/index.html. Thus, when your browser requests http://127.0.0.1:3000/, Express responds correctly.
But you've said nothing about the other files, such as http://127.0.0.1:3000/style.css, which would be route /style.css. You haven't defined any middleware for that route. So Express, not knowing what to do, by default responds with 404 and an error message. Thus, when your browser tries to load http://127.0.0.1:3000/style.css while fetching the resources referenced in index.html, the stylesheet fails to load.
Your second code snippet doesn't fix anything. It really makes things worse, because res.sendFile() can't send folders (how would that even work?) and that generates errors. You still haven't defined routes other than /, and now all your files are inaccessible.
To actually solve the problem, you could, theoretically, tediously define a route for every file, or more cleverly define one route with a route parameter. But serving a static folder with Express is a solved problem. You can simply offload the work to express.static by replacing all your code with:
routes.use(express.static(path.join(__dirname, "clientSide/")));
To go even further, you don't need Express or Node.js for a static file server. Try nginx. And for simple webpages, you don't need a server at all; just double-click index.html and let your browser open it.

deploying node add on server without using localhost

I have a node app that I am trying to deploy on my server. I have an index.html file in a public folder and an app.js file. If I navigate to the project in the command line and run node app.js it runs the app on localhost:8888 and shows the index.html file.
Now that I have uploaded this to my server I am wondering what I need to do, and change (if anything) in my app.js file so that i can visit the site without visiting localhost:8888, but instead the actual url.
I have tried http://162.xx.xxx.xxx/folderName/app/public:8888, but this doesn't work.
var express = require('express')
var app = express();
app.use(express.static(__dirname + '/public'))
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.listen(8888, function () {
console.log('Example app listening on port 8888!')
});
"Server" is a word with two primary meanings in software development.
It can mean either "A piece of software that listens on a network" or "A computer running that kind of software".
So having uploaded the JavaScript program to the remote computer that is your server you need to do exactly the same as you did on your own computer.
i.e. you need to get a terminal on the server and run node app.js
It will then be available at http://your.example.com:8888/
(More advanced uses would involve using software like forever or system.d to run it automatically as a background process).
If you were using the term server with the other meaning (i.e. you mean "Apache HTTP" or "IIS" or similar), then you are out of luck.
Using Node for server side code means running a server written in JavaScript.
To use this in combination with something like Apache, you would either:
Run the Node server instead of Apache
Run the Node server on a different port and point some services at that port explicitly
Run the Node server on a different port and use something like ProxyPass to have Apache relay requests to it
Change the port number from 8888 to 80 and then use the address of your server in the browser. For example, "mysite.com" for a domain name or "123.45.678" for an IP address.
If there are other sites on that server, you can't run it on port 80. (Port 80 is the default port websites use.) You'd need to use a different port. So, say you kept 8888 -- the address would be yoursite.com:8888

How to make a redirect (301) in Node.js / Express?

I have a static site, a simple single page layout that I deploy in Dokku. I need to make a redirect (301) from www to non www and from *.website1.com to website2.com, but I don't know how. I was trying to use express-force-domain in npm but it makes my URL's crazy and having some redirect loops, I was trying other methods that I find on the web but none succeeds.
my server.js is:
var express = require('express')
var app = express();
app.set('port', (process.env.PORT || 80))
app.use(express.static(__dirname + '/public'))
app.get('/', function(request, response) {
response.send('Hello World!')
})
app.listen(app.get('port'), function() {
console.log("Node app is running at localhost:" + app.get('port'))
})
That is the version that works, but without redirects.
res.redirect(301, 'http://yourotherdomain.com' + req.path)
See Express documentation.
To anyone arriving here from Google, while #frederic's answer is still what is recommended by the express docs, the response.send(status, body) style has been deprecated and will generate a warning (I am on express 4.13.4 at time of writing), and more importantly I found that it no longer produced the desired result when redirecting.
As #Markasoftware mentioned, to achieve an automatically followed 301, you need to set the location header to the url you want. The request body can be empty:
response.set('location', 'https://my.redirect.location');
response.status(301).send()
As far as I understand it, to set an HTTP 301 code, you would set the response code to be 301 and then set the Location header to whatever url you want it to redirect to. I don't think this is the preferred way to do www to non-www urls though

socket.io.js not loading

I know there are a bunch of questions on this already, but none have answered it for me, and plus mine is slightly different.
I'm starting the socket.io server in node using this:
var io = require('socket.io').listen(8000);
My terminal says everything is ok:
info - socket.io started
Now I am trying to load the .js file in my clientside browser using this url:
http://<hostname>:8000/socket.io/socket.io.js
I dont get a 404, it just hangs forever. I've also used a network utility to ping port 8000, and it seems to be open fine.
I installed node and socket.io just yesterday, so they should be the latest versions. Can anyone shed any light on this? Thanks!
Turns out the reason I could never request the .js file was because my company network blocks all ports except the usual ones (80, 21, etc), so `I would never be able to communicate with port 8000.
Use express.js. Place the socket.io file in public/javascripts folder and add this line to your html
<script src="/javascripts/socket.io.js"></script>
I think this is the best way. When you're writing http://<hostname>:8000/socket.io/socket.io.js
node tries to find a folder named socket.io in your project's public folder. And the file socket.io.js in it.
If you don't want to use express.js you should catch the request and try to load a file if no routes were found for your request (what actually express does) because node doesn't know what to do for requests which don't match any routes in your server.
And I recommend to use the socket.io.min.js file (it's smaller and it's in folder node_modules\socket.io\node_modules\socket.io-client\dist)
You have to start an http/https server to access it via http/https. Simply starting an socket.io server won't do. Do the following:
var http = require('http');
var app = http.createServer(),
io = require('socket.io').listen(app);
app.listen(7000, "0.0.0.0");
Then I can access the file http://localhost:7000/socket.io/socket.io.js
sockets.io uses websocket protocol (ws://). See the wikipedia page.
You need to get at least 3 pieces working together.
Serve some HTML (/index.html will do just fine) so there's a web page. This file should contain the socket.io client <script> tag. For this you need the http server portion of the starter examples. You are missing this and that's why browsing to your server just hangs.
Serve the socket.io client. Socket.io will do this for you automatically when you pass in your http server function to it. You don't need full express as this can be done with just node's http module as per the first example on the socket.io docs.
Some javascript to actually do something with the socket. This can be the content of a <script> tag in index.html or a separate file. If it's a separate file, you need to set up your http server to actually serve it.

Categories