Am able to fetch html page properly using postman GET But getting error while fetching html page using POST using postman
Error details :
404 Not Found404 Not Found
We have frontend code on html/JS and backend code on nodeJS
This can happen for so many reasons. Check your imports, routes and request url.
Though it is not the way to get your html through POST method. Using GET method is the right way.
const express = require("express");
const router = express.Router();
router.post("/", (req, res, next) => {
res.render("index", { title: "Express" });
console.log(req);
});
module.exports = router;
It is good if fetch data using GET method only and if it is giving 404 Error then it means you might have not created any route with POST method. Same route with different method treat as different route like
1) GET http://example.com/fetch
2) POST http://example.com/fetch
are 2 different routes. You need to define each separately
I believe that for fetching data, GET is the preferred method and POST should be used to update server-side resources, not to retrieve them. If POST is returning 404, You may not have a POST route configured, or POST access may be disabled by itself through your server's configuration.
Usually the "GET" method is used when requesting the an html page, for example all the browsers, uses "GET" for requesting the landing page of any url.
Post usually is used to send data and logging in.
You need to create a route for POST requests to get the HTML.
I'm assuming that you must be using some kinda framework router like express-router to route your pages. In your router code, you would be having something like
app.get('/myHtmlPage', function(req, res) {
// some code
})
so you're getting your page back for making GET requests. You need to create a similar route like
app.post('/myHtmlPage', function(req, res) {
// some code
})
to get the same page for POST requests.
Related
I've followed this 7 hour tutorial on creating a blog almost to. There is one step that I skipped, because I did not want to use the separate client/server hosting that the tutorial suggests. Instead, I have a single heroku server that serves the client out of the public server:
const app = express();
app.use(express.static('public'))
app.use('/posts', postRoutes);
app.use('/user', userRoutes)
You can see that the app also serves some rest requests to the /posts and /user paths. However, the tutorial also led me to add these paths into the url client-side.
For example, you can access my app at (https://blog-tutorial-888.herokuapp.com), but you will be immediately "redirected" to (https://blog-tutorial-888.herokuapp.com/posts).
I say "redirected" because on the client side, it appears that you are at that site, and the purpose is so that you can do things like navigate to the next page, which will be at (https://blog-tutorial-888.herokuapp.com/posts?page=2).
But if you were to actually go to these links, or refresh the page, you will be hit with the result of the rest request, which is a giant block of text (and this is obviously because I have app.use('/posts', postRoutes)).
Is there a way to get around this somehow? Somehow serve both the html and the rest request at this endpoint?
To have a single server that severs the front and data trough a REST API, you would need to differentiate the paths, for example by adding an /api to urls for getting data, like so:
app.use('/api/posts', postRoutes);
app.use('/api/user', userRoutes);
And then below all your /api handlers add following lines so that for every other request you send that HTML that would load React bundle:
app.get("/*", (req, res) => {
// Make sure it's the correct path to the build folder
res.sendFile(path.join(__dirname, "../client/build/index.html"));
});
Of course don't forgot to add /api in your front end query urls as well, not the routes setup:
fetch("/api/posts")
// or
axios.get("/api/posts")
I am curious and really willing to learn and understand the whole concept behind the request and response circle of all backend
my question is I have a node js express framework
app is started
app.use('/api',router)
require('./routers/user')(router)
require('./routers/uretim')(router)
require('./routers/durus')(router)
require('./routers/rapor')(router)```
all my functions are called and executed and waiting for a request
since the order of this app is first use
app.use('/api',router)
then the router is called at this particular point router function has nothing attached to it,
so does it mean as we started our application we have created the routes with the executed functions below the app.use
main question
user enter ..../api
our back end was hit
what is the first process, or function that happens within our backend?
So the USE is used to load middleware, what you have is to use the router middleware on the /get url..
A better example of what is happening here is to define some action middleware on that url :
app.use("/api", (req, res, next) => {
// For example, a GET request to `/api` will print "GET /api"
console.log(`${req.method} ${req.url}`);
next();
});
When you start your server, if you hit your /api url, it will log the request info in the console and continue.
However the other URL's will not.. So you can tailor specific middleware for certain endpoints.
As for your routing itself, you will need to define the routes and their controller logic. Something like :
// HTTP GET Request Definition
app.get('/api',(req, res) => {
res.send("Hey, you hit API");
} );
This will happen after the middleware has been actioned.
Express
I am using a res.redirect('page.ejs'); and on my browser I get the message:
Cannot GET /page.ejs
I have not declared this in my routes file in the style of :
app.get('/page', function(req, res) {
res.render('page.ejs');
});
Should this be included in order for the res.redirect() to work?
When I do not use res.redirect() but res.render(), even if I have not the app.get() code, it still works.
so to understand this, let's look at what each of these methods do.
res.redirect('page.ejs');
// or, more correctly, you're redirecting to an *endpoint*
// (not a page. the endpoint will render a *page*) so it should be:
res.redirect('/page');
this will tell express to redirect your request to the GET /page.ejs endpoint. An endpoint is the express method you described above:
app.get('/page', function(req, res) {
res.render('page.ejs');
});
since you don't have that endpoint defined it will not work. If you do have it defined, it will execute the function, and the res.render('page.ejs') line will run, which will return the page.ejs file. You could return whatever you want though, it can be someOtherPage.ejs or you can even return json res.json({ message: 'hi' });
res.render('page.ejs');
this will just respond to the client (the front-end / js / whatever you want to call it) with the page.ejs template, it doesn't need to know whether the other endpoint is present or not, it's returning the page.ejs template itself.
so then, it's really up to you what you want to use depending on the scenario. Sometimes, one endpoint can't handle the request so it defers the request to another endpoint, which theoretically, knows how to handle the request. In that case redirect is used.
hope that makes sense and clarifies your confusion
(I'm not an expert on the inner-workings of express, but this is a high-level idea of what it's doing)
You should do res.redirect('/page')
app.use("*", topUsers) is called multiple times..
topUsers is being called multiple times
function topUsers(req, res, next){
console.log("req.url", req.url)
findMostUsefullReviewsAggregate(6)
.then(function(aggregationResult){
// console.log("aggregationResult", aggregationResult)
// console.log("***aggregationResult::", aggregationResult)
return populateMostUseful(aggregationResult)
})
.then(function(populated){
console.log("<<<<<<<<<<<<<<<<<<TOPUSER CALLED >>>>>>>>>>>>")
// console.log("POPULATED: ", populated);
console.log(">>>populateMostUseful.length");
populated = populated.map(function(e){
e.momented = moment(e.createdAt.getTime()).fromNow();
return e;
})
req.session.mostUsefulReviews = populated;
// res.end()
})
.catch(function(err){
console.log("HEADERERR", err);
});
next();
}
( some info for later: main.ejs is for ("/"))
when I change it to app.get("/", topUsers) and go to "/"it is only called once (which is what I want).
the console.log for req.url shows "/" for all 3
In my main.ejs I include a header.ejs. I thought that might be a problem. Maybe the request to the header for the include was a problem but I don't think so.
Quick question : If I do app.get("/") would that work on all subroutes like /users/idofuser? I think If I do that the function doesn't get called.
I think app.get("*") also gives me the same problem with the multiple calls.
Edit: when I put next in the .then() it still gets called multiple times.
my real goal it to have something happen on all routes. I already have routes set up. I don't want to go to each route and do something like app.get("/", onemiddleware, topUsers, ). I don't want to put topUSers on each one physically. Do I have to.
If you are doing this from a browser loading a web page, the browser is probably requesting multiple resources from the website.
For starters, it often requests the favicon and if there are any other resources in the web page (other scripts, stylesheets, images, etc...) each of those will be a separate request to your web page. You can see exactly what URL is being requested by logging req.url for each request. From a single page load, there should be no reason you would get three requests for /, but you very well could get a request for / follow by other requests for some other resource (and consequently some other URL) from the same server.
Show us the web page you are loading and we can better point out what's going on.
If what you're really trying to do is to share a middleware on a set of routes, then you can create a router, put the middleware on the router with router.use(), define all the routes that you want to have that middleware on that specific router and then hook the router into your app. This will execute the middleware only for routes that match that router and you only have to specify the middleware once for the router and all routes defined on that router will use that middleware. Other routes defined directly on the app object or on other routers will not use the middleware. You will have to define the router as some unique path root or wildcard that helps express know which routes should be passed into your router. We'd have to see the whole universe of paths you plan to use that both do and don't use that middleware for us to know more specifically what to suggest.
I have a single page application that uses jquery to load html chunks in the page. There are routes setup for these chunks on my server. However if one of my routes (for example: /signIn) were typed directly after my url then that html chunk gets loaded onto the page (mySite.com/signIn).
How can I send a 404 error code for any path entered after the url but still allow the route to be called using jquery (the way it was intended)?
Thanks!
Edit:
Thank you for the answers! This is the code I wrote in case anyone would like to use it. It redirects any request, not made from a jquery load, to the home page. However it allows any paths with extensions to be loaded (like js and css) except if they are entered in the url, hiding your stylesheets, javascripts and images.
//Prevent url path entry
app.get('*', function (req, res, next) {
//Check for extension
if (/\.\w*$/.test(req.url)) {
//headers['accept'] is comma separated, get the first value
var splitPath = req.headers['accept'].split(',');
//If first entry is text/html then it was requested in the url, Redirect!
if ( splitPath[0] == 'text/html' ) {
res.redirect('/');
}
else {
next();
}
}
//If headers['x-requested-with'] is null then it wasn’t requested by jQuery, Redirect!
else if (req.headers['x-requested-with'] == null) {
res.redirect('/');
}
else {
next();
}
});
You want to block any non-AJAX requests. JQuery and other libraries add the following HTTP header to ajax requests:
X-Requested-With: XMLHttpRequest
You should check for this on the server side. If it does not exist, then you can return whatever status you wish.
For data-only routes, you could add a short token to the data field in $.ajax or whatever tool you are using to make the call.
On the server side, on data routes you would check req.body (if using express) for the token and then send a response based upon the presence or absence.
The easiest method may simply to check for any token value, saving the need to validate it.
The hardest method would be for the server to generate and issue a session token to the client that would be used to grab the html template parts (or return the 404).
If you're using a typical connect- or express-based middleware, why not just handle GET and POST requests differently? Requests from the URL bar will always be GET requests, so make those return a 404 for the path specified. Then handle POST requests properly and make sure the jQuery requests are calling using POST.