I am writing a web application using react for client side and express for server side.
I am using react-router (link) routing the client pages.
Working with the hashHistory it was simple and worked fine, but now I want to use browserHistory.
As mentioned in the react-router tutorial, I need to tell my server to expect the client request, so when we render a client page it will server the index.html.
I can't find a way to handle both requests from the client for pages and requests for server processing.
For example, I have a page in the path /product, but I also have an endpoint for the server processing /authenticate.
In the react-router tutorial it says to use the following:
// server.js
// ...
// add path.join here
app.use(express.static(path.join(__dirname, 'public')))
// ...
app.get('*', function (req, res) {
// and drop 'public' in the middle of here
res.sendFile(path.join(__dirname, 'public', 'index.html'))
})
But this way will result every request (including /authenticate) to send it back to the index.html. How can I merge those two?
You have to define the /authenticate before the * (which is basically a Catch-All and has to come last)
app.use(express.static(path.join(__dirname, 'public')))
ap.get('/authenticate', function (req, res) {
res.sendStatus(200)
});
// ...
app.get('*', function (req, res) {
// and drop 'public' in the middle of here
res.sendFile(path.join(__dirname, 'public', 'index.html'))
})
Related
I'm trying to follow Crowdbotics' Messenger bot tutorial, however. I did exactly as he mentioned but i am getting this.
My folder:
Okay so, first of all i run node index.js and get the following:
Right after that. We initialize our ngrok server by ngrok http 5000 and get the following:
But on EVERY http request i get the classic Cannot GET /.
On the hindsight, my index.js only contain:
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.listen(5000, () => console.log('Webhook server is listening, port 5000'));
I can't really point out what i am doing wrong, your help is truly appreciated.
Based on your express js code, I think you haven't define the routes to '/'
add this before the app.listen on the index.js file
app.get('/', (req, res) => res.send('Hello World!'))
Your index.js has started a server that listens and respond to the HTTP protocol - but it does not "serve files" the same way a web server such as Apache does.
As #Yana notes, you need to explicitly set a route to do something, such as send a text response back.
If you want the favicon.ico file to be sent when requested, then you need to setup a static route for that as part of your index.js code.
Currently I'm trying to get $locationProvider.html5Mode(true) working with AngularJS, ui-router, and ExpressJS. Given an abstract state parent with URL /parent and a nested state parent.child with URL /child, navigating to localhost:3000/parent/child within the webpage itself works just fine. However, when refreshing the page on the same URL (or typing the URL directly into the address bar), the browser returns a message "Cannot GET /parent/child".
We've been trying a few different configurations and such with ExpressJS and middleware. These setups do not solve our problem:
app.use(express.static(__dirname + "/public"));
app.get("/", function(req, res, next) {
console.log(req.url);
res.sendFile(__dirname + "/public/index.html");
});
returns the "Cannot GET" error.
app.use(express.static(__dirname + "/public"));
app.get("*", function(req, res, next) {
console.log(req.url);
res.sendFile(__dirname + "/public/index.html");
});
floods the (Chrome) Developer console with the error Uncaught SyntaxError: Unexpected token < for every js file, since Express is sending index.html for requests for js files within index.html using the <script> tag.
When navigating to a URL like localhost:3000/parent, the webpage displays just fine without any errors.
Update: I should mention that the request URLs for .js files are turning out to be /parent/js/someJsFile.js, for example, when refreshing localhost:3000/parent/child.
It is common practice to keep your static resources in a location that can be isolated and served with the static middleware (for this very reason).
Recommend
Move your static assets (i.e. js files) into a location specified for static resources.
Then, the second configuration above is the fix:
app.use(express.static(__dirname + "/public/static")); //<-- JavaScript here
app.get("*", function(req, res, next) {
console.log(req.url);
res.sendFile(__dirname + "/public/index.html");
});
Alternatively
You could employ the urlrewrite middleware to accomplish your goal: https://github.com/kapouer/express-urlrewrite
EDIT ------------
so I figured out the issue, restarting and reloading nginx didn't have any effect, but if I stoped the nginx instance, then restarted it, any changes I made to the server files took effect. It's great that I figured it out, but could anyone give me some insight into why this is? It's better if I understand why this was happening. Any changes I made to the client side files such as the html files took affect immediately, it was only the server files that I had to stop then restart the nginx instance for it to take affect.
ORIGINAL POST BELOW----------------------
Any changes I make to the server side files of my deployed Node.js app with express.js isn't being seen by ubuntu. Basically, I have a mean app deployed on ubunut, it is a multipage page app, with only one of those pages having partials, so i use my routes.js
to catch the routes and send them to my main.js file to tell express and node which html or ejs file to load.
I made changes to the version on my computer so that all other routes would go to a certain html, it works great. But I pushed my changes to github, then pulled them in my ubuntu instance, and it's not working. All other changes I made to the project during this time that were pushed with it have taken affect. But, it's like ubuntu isn't letting node see any changes to the routes.js file, the code is there, I've even altered it with 'vim' from my terminal, but any changes I make, even ones that should break it, aren't seen by node. And going to an unexpected route displays the 'cannot GET...' page.
I've wracked my brain, but i'm stumped, the code is there and I can change it, I've altered html pages via vim to test it. But both, the routes.js file that handles my routing and my server.js file aren't reflecting my changes, even when I change things that should break it. Any ideas? Let me know if you need anymore info, i've included my files below. Also, I use nodemon so that it restarts automatically anytime changes are made
SERVER.JS FILE -------------------------------
var express = require('express'),
app = express(),
path = require('path'),
bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({extended: true}))
app.use(bodyParser.json())
app.use(express.static(path.join(__dirname, './client')))
app.use(express.static(path.join(__dirname, './client/views')))
app.use(express.static(path.join(__dirname, './bower_components')))
app.set('views', path.join(__dirname, './client'));
app.set('view engine', 'ejs');
require('./server/config/routes.js')(app)
var port = 8000
app.listen(port, function(){
console.log('Server on port: ' + port)
})
ROUTES.JS FILE -----------------------------
var Main = require('../serverControllers/main.js')
module.exports = function(app){
app.get('/', Main.main)
app.get('/contact', Main.contact)
app.get('/algorithms', Main.algorithms)
app.get('/projects', Main.projects)
app.get('*', Main.other)
app.use(Main.other)
}
MAIN.JS FILE ----------------------
module.exports = {
main: function(req, res){
res.render('index')
},
contact: function(req, res){
res.render('contact')
},
algorithms: function(req, res){
res.render('algorithms')
},
projects: function(req, res){
res.render('projects')
},
other: function(req, res){
res.render('default')
},
}
I'm using Node/Express as an API proxy server and want to know if it's possible to render HTML (index.html) page for all GET routes as well as expose API endpoints on the same port. I'm using client side routing (react-router).
For example:
// Always return the main index.html, so react-router render the route in the client
app.get('*', (req, res) => {
const html = renderHTML(req, res);
res.send(html)
});
// Expose API
app.all('/api/*', (req, res, next) => {
proxyRequest(...)
});
The problem is that doing when doing a GET request, the first app.get() catches it (for example: fetch('/api/accounts')).
I need to be able to make any request to any API endpoint route (besides /) and have the client send any method (GET, PUT, POST...).
Can I serve index.html to all client routes and have GET endpoints on the same port? Can I serve html to all routes except ones prefixed with /api/?
If you expose your endpoints first and then serve your html, it should do the job.
// Expose API
api.all('/api/*', cb);
// Serve HTML
api.get('*', cb);
Make a directory called public.
Put your HTML and supporting files in it.
app.use(express.static(path.resolve('./public')));
//Your API routes here
The express.static will serve the static HTML files and then you can add your route statements. This will work on the same port.
I'm using passport and some static .html files. I want to include them as express views or static files. Now I want SOME .html files like login.html to be available for everyone, but the other view files like secret.html should need passport.
I know, that you can use
app.get('somePath', ensureAuthenticated, function (req, res, next) {} for routes, but I want it for static files.
How to do it on a non-hacky way?
If all "secure" files share a distinct URL prefix, such as /public/secure, you can use() ensureAuthenticated with this path:
app.use('/public/secure', ensureAuthenticated);
app.use('/public', express.static(__dirname + '/public'));
Otherwise, the express.static() middleware doesn't offer many options for controlling access. For the most part, it assumes all available files from the path given to it are meant to be "public."
Though, it does normally refuse to send hidden files, following the *nix standard of a . prefix:
~/path/to/.secret.html
Then, to actual serve it, you can send the file yourself in the route you suggested with the middlware attached:
app.get('/path/to/secret.html', ensureAuthenticated, function (req, res) {
res.sendfile(__dirname + '/path/to/.secret.html');
});
And, you may want to consider moving it out of your static() directory,