I'm using React BrowserHistory for navigation. I want the same files to be served from my Node server regardless of the URL path.
My server code:
const http = require('http');
const path = require('path');
const express = require('express');
const app = express();
const hostname = 'localhost';
app.use(express.static('../public'));
app.get('*', (req, res)=>{
res.sendFile(path.join(__dirname, '../public/index.html'));
});
const port = process.env.PORT || 8007;
app.listen(port, ()=>{
console.log('Production Express server running at localhost:' + port)
});
http://localhost:8007 => works fine
http://localhost:8007/help => works fine
http://localhost:8007/help/faq => Fails
I want all URLs to return the same resources, served from ../public. However, it seems that the express.static doesn't work when the resource isn't requested from the root. So, for instance, when the browser asks for <script src="scripts/main.js"></script>, it thinks I want ../public/help/scripts/main.js, whereas I actually want ../public/scripts/main.js/. So, because express doesn't find such file, it moves on to the app.get('*'..., which returns the ../public/index.html file when the script is requested.
So, the desired behavior is:
return the same index.html for any path (with any number of sub-folders), and let React figure out what to show
return the resources always relative to the path index.html is served from, not relative to the path in the URL
It works when I use absolute paths in my resource requests (I.E. <script src="http://localhost:8007/scripts/main.js"></script>), however writing it like that obviously isn't desirable, because it needs to be changed when it's hosted elsewhere.
What should I do?
you can use that condition for your routing:
app.get('*/**', (req, res) => {
res.sendFile(path.join(__dirname, '../public/index.html'));
});
It's work find for me.
Be carefull with this method, your browser will reload the entire page for each call to a route.
Related
I am trying to serve images from an "images" file in my project depending on the parameters that the user enters.
For example,
https://localhost:3000/images?fileName=burger
should display the image on the browser
does anyone know how i can go about it?
My structure is as follows:
images
---burger.jpg
src
---index.ts
I tried to do it this way but for some reason it won't work
app.use('/images', express.static('images'));
if(req.query.fileName === "burger"){
res.sendFile("burger.jpg" , {root: path.join("./images")});
}
According to your code, if your file structure is following.your code will run perfectly. make sure you set the path to serving static files under express.static() with care and note that your incoming query value exactly matches the file you need to get including the case. this should solve the problem, thank you!
File Structure:
images
--- burger.jpg
index.js
import express from 'express';
import path from 'path'
const app = express();
const PORT = process.env.PORT || 5000;
app.use('/images', express.static('images'));
app.get('/images', (req, res) => {
if(req.query.filename === 'rocket'){
res.sendFile("rocket.jpg" , {root: path.join("./images")});
})
app.listen(PORT, () => {
console.log('Server is up and running on PORT: ${PORT}');
})
you can also avoid all those fuss by removing that middleware and instead provide absolute path while sending file. for eg:
app.get('/images', (req, res) => {
if(req.query.filename === 'rocket'){
res.sendFile(path.join(__dirname, "images/Rocket.jpg"));
}
})
I'm trying to learn nodejs and express and i created a simple server. I want to run some JS code for response.
When I used this method it's works.
const express = require('express');
const path = require('path');
require('dotenv').config();
const app = express();
const port = process.env.PORT || "8000";
app.get('/', (req, res) => {
res.send(`<script>
console.log("Program works!");
</script>`);
});
app.listen(port, () => {
console.log(`Listening to requests on http://localhost:${port}`);
});
But writing JS as String is hard so I tried this:
const express = require('express');
const path = require('path');
require('dotenv').config();
const app = express();
const port = process.env.PORT || "8000";
app.get('/', (req, res) => {
res.send(`<script src="./response.js"></script>`);
});
app.listen(port, () => {
console.log(`Listening to requests on http://localhost:${port}`);
});
And i get this error:
GET http://localhost:8000/response.js net::ERR_ABORTED 404 (Not Found)
When you send this:
<script src="./response.js"></script>
to the browser, the browser will parse that and see the src attribute and will then immediately request ./response.js from your server. But your server doesn't have any route to respond to that request (thus it gets a 404 error back from your server). Remember that a nodejs server serves NO files by default (unlike some other web servers). So, you have to create routes or middleware for anything that you want it to serve.
So, you need to add a route to your server that will response to a request for response.js. First change your <script> tag to this:
<script src="/response.js"></script>
You want the request to be "path absolute" so it does not depend upon the path of the containing page. Then, you need to add a route handler for response.js to your server.
This can be done as a single route:
app.get('/response.js', (req, res) => {
res.sendFile("response.js", {root: __dirname});
});
Or, you can use express.static() to serve a whole directory of publicly available files with one line of code (if you also move all publicly available static files to their own directory away from your server files).
I am building a blog using Node js and Express and hosting it on firebase. When I serve the website locally everything works just fine and the html is served as expected. But, when I deploy the server the routes no longer work and the html files can't be found. I'm sure it has to do with how firebase deploy hold the html files.
I'm not really sure where to go from here. I can't really find great guidance on how to set up something like this on the firebase docs.
const functions = require("firebase-functions")
const cors = require("cors")
const express = require("express")
const path = require("path")
/* Express with CORS */
const app = express()
app.use(cors({ origin: true }))
app.get("/", (request, response) => {
response.send("Hello from Express on Firebase with CORS!")
})
//File path consts
const publicDir = "/Users/wilson/wildman-talks-fb/public";
const blogDir = "/Users/wilson/wildman-talks-fb/public/blogs";
app.get("/about/", (req, res) =>{
res.sendFile(path.join(publicDir, "/about.html"));
});
app.get("/contact/", (req, res) =>{
res.sendFile(path.join(publicDir, "/contact.html"));
});
app.get("/tools/", (req, res) =>{
res.sendFile(path.join(publicDir, "/tools.html"));
});
app.get("/five-steps-july-20/", (req, res) =>{
//res.send(path.join(publicDir, "/five-steps-july-20.html"));
res.sendFile(path.join(publicDir, "/five-steps-july-20.html"));
})
exports.app = functions.https.onRequest(app)
So what is happening is when I deploy the site locally all of the links in my webpage work to other html webpages for my site. When I deploy it on firebase I get 404 errors. I was able to use path.join(__dirname, "../public") and print out all of the files contained there. When i did that these were the files that were there on my local host: [".DS_Store","404.html","about.html","blogs","contact.html","css","five-steps-july-20.html","img","index.html","js","mail","tools.html","vendor"]. After deploying it just returns me a 500 error so I guess that won't help.
Your directories contain absolute paths to your filesystem. Try to use dynamic absolute paths.
Change the paths from
const publicDir = "/Users/wilson/wildman-talks-fb/public";
const blogDir = "/Users/wilson/wildman-talks-fb/public/blogs";
To
const path = require("path");
const publicDir = path.join(__dirname, "/public";)
const blogDir = path.join( __dirname, "/public/blogs");
When the user goes to mydomain.com/game, I want the user to see what is displayed in my public folder. This works completely fine when I do this:
app.use('/game', express.static('public'))
The problem is that I want to extract some information from the URL, but as I do not know how to continue the routing when using a static site, I can't extract any information. For example, if the user inputs mydomain.com/game/123, I want to retrieve 123, but still route the person to my public folder, like mydomain.com/game does.
Any ideas on how to handle this problems?
This has worked for me in a similar situation
app.use('/game/:id', (req, res) => {
// do something with id
res.redirect(302, '/game');
}
Try to use two middlewares: first is your static middleware, the secont is the fallback, with id (123)
app.use('/game', express.static('public'));
app.use('/game/:id', function(req, res) { // when static not found, it passed to this middleware, this process it
console.log('your id', req.params.id);
res.send('ok');
});
If you are using react static files and you want to serve all react routes using express then you have to do thing like below-
1.First of all you have to run command in your react folder
npm run build
this will create your build folder in react app having one index.html file which you have to serve through express.
Now come to your server.js file and write there
const express = require('express');
var path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, 'client/build')));
app.get('*', (req,res) => {
res.sendFile(path.join(__dirname+'/client/build/index.html'));
});
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server up and running on port ${port} !`));
I'm making some frontend experiments and I'd like to have a very basic webserver to quickly start a project and serve the files (one index.html file + some css/js/img files). So I'm trying to make something with node.js and express, I played with both already, but I don't want to use a render engine this time since I'll have only a single static file, with this code I get the html file but not the assets (error 404):
var express = require('express'),
app = express.createServer();
app.configure(function(){
app.use(express.static(__dirname + '/static'));
});
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
app.listen(3000);
Is there a simple way to do it (in one file if possible) or Express requires the use of a view and render engine ?
I came across this because I have a similar situation. I don't need or like templates. Anything you put in the public/ directory under express gets served as static content (Just like Apache). So I placed my index.html there and used sendfile to handle requests with no file (eg: GET http://mysite/):
app.get('/', function(req,res) {
res.sendfile('public/index.html');
});
Following code worked for me.
var express = require('express'),
app = express(),
http = require('http'),
httpServer = http.Server(app);
app.use(express.static(__dirname + '/folder_containing_assets_OR_scripts'));
app.get('/', function(req, res) {
res.sendfile(__dirname + '/index.html');
});
app.listen(3000);
this loads page with assets
You could use a solution like this in node.js (link no longer works), as I've blogged about before.
The summarise, install connect with npm install connect.
Then paste this code into a file called server.js in the same folder as your HTML/CSS/JS files.
var util = require('util'),
connect = require('connect'),
port = 1337;
connect.createServer(connect.static(__dirname)).listen(port);
util.puts('Listening on ' + port + '...');
util.puts('Press Ctrl + C to stop.');
Now navigate to that folder in your terminal and run node server.js, this will give you a temporary web server at http://localhost:1337
Thank you to original posters, but their answers are a bit outdated now. It's very, very simple to do. A basic setup looks like this:
const express = require("express");
const app = express();
const dir = `${__dirname}/public/`;
app.get("/", (req, res) => {
res.sendFile(dir + "index.html");
});
app.get("/contact", (req, res) => {
res.sendFile(dir + "contact.html");
});
// Serve a 404 page on all other accessed routes, or redirect to specific page
app.get("*", (req, res) => {
// res.sendFile(dir + "404.html");
// res.redirect("/");
});
app.listen(3000);
The above example is if you want to serve individual HTML files. If you were serving a single page JS app, this would work.
const express = require("express");
const app = express();
const dir = `${__dirname}/public/`;
app.get("*", (req, res) => {
res.sendFile(dir + "index.html");
});
app.listen(3000);
If you need to serve other static assets from within a folder, you can add something like this before you start defining the routes:
app.use(express.static('public'))
Let's say you have a js folder inside public like: public/js. You could include any of those files inside of your html files using relative paths. For example, let's say /contact needs a contact.js file. In your contact.html file, you can include the script as easy as:
<script src="./js/contact.js"></script>
Building off of that example, you can do the same with css, images etc.
<img src="./images/rofl-waffle.png" />
<link rel="stylesheet" href="./css/o-rly-owl.css" />
Hope this helps everyone from the future out.