I'm working on a Node.js app. When a user hits the main url, a database call will be made. This database call returns a URL path. I'm trying to understand how to send the user to that new URL from my Node app. That URL is local to the app itself. Everything I see involves a 301. I'm not sure if that what I really want though. Currently, my code looks like this:
getUserUrl: function (req, res) {
var url = getNewUrl();
res.status(200).send();
}
This only confirms the request to getUserUrl was ok. However, it doesn't actually send the user to url. How do I redirect the user to url?
THank you!
I don't know why you say a 301 isn't what you want, because that is definitely one of the options you have available to you.
Typically, a 301 status code is used for a permanent redirect. That is, a request for a certain URL will be considered to always redirect to where you send that user, and browsers and proxies can cache this redirection indefinitely.
A 302 status code is a temporary redirect. Subsequent requests for the same URL will come to your server (as long as you don't enable caching for it), allowing you to continue to redirect or not.
In either case, you need the status code along with a Location: header to tell the user agent where to go.
res.setHeader('Location', 'http://example.com');
res.statusCode = 302;
res.end();
These days you can also use 307 and 308 status codes for redirection. They are more explicitly defined in the RFCs and provide roughly the same functionality as 301 and 302.
Related
I have a single page application I am working on. The goal is to have the main root route be something other than www.website.com. Something like www.website.com/cool-page This is for SEO purposes. I am not sure if it is best practice or even possible.
Thus far I've been able to change the URL on load using this:
// root route
router.get('*', function(req, res) {
res.redirect('/cool-page');
});
This gives me an error that the page redirected you too many times.
Any advice on this?
Your routing definition looks like it would redirect every request to URLs within the root URL, not just those going to the root URL itself. So it will redirect even the redirected requests going to /cool-page, forming an infinite loop. Try using router.get('/', ... ) instead, I think that would redirect only requests made to the root url,
So I have a landing page ('/'). On this page is a login form for a username and password with a submit button. I have the app.get that loads the page and an app.post to receive the parameters of the form. However, my intention is to have an app.post('/login', function (req, res){ //logic}); There is no /login route or page to load, this would simply house the logic for the login itself (validation of the username, etc.) Is there an easy way to get the post from '/' to redirect into the post for /login without it trying to load the /login page, which does not exist?
I'm not sure if I understand your question correctly. As I understand you want your POST request to / get redirected to POST requests to /login which can be tricky.
Usually you do redirects by sending either 301 Moved Permanently or 302 Found HTTP status code. Both of them usually work in practice as if it was 303 See Other and a GET request is made. See List of HTTP status codes on Wikipedia:
This is an example of industry practice contradicting the standard.
The HTTP/1.0 specification (RFC 1945) required the client to perform a
temporary redirect (the original describing phrase was "Moved
Temporarily"), but popular browsers implemented 302 with the
functionality of a 303 See Other. Therefore, HTTP/1.1 added status
codes 303 and 307 to distinguish between the two behaviours.
However, some Web applications and frameworks use the 302 status code
as if it were the 303.
There is a 307 Temporary Redirect (since HTTP/1.1) created to address this issue that is not allowed to change the HTTP method - so a redirect from POST should still be POST - see Wikipedia:
In this case, the request should be repeated with another URI;
however, future requests should still use the original URI. In
contrast to how 302 was historically implemented, the request method
is not allowed to be changed when reissuing the original request. For
example, a POST request should be repeated using another POST
request.
As far as I know browsers should warn users before following such redirects. I don't know how that works in practice. I wouldn't rely on that since it can be annoying to users at best or even not work at all.
My suggestion would be to either change this:
app.post('/login', function (req, res) {
// logic
});
to this:
function loginHandler(req, res) {
// logic
}
app.post('/login', loginHandler);
app.post('/', loginHandler);
or something like this, using regular expressions:
app.post(/^\/(?:login)?$/, function (req, res) {
// logic
});
That way instead of a redirect the same handler will be used for both of those routes. It would be both faster and more robust because that way you don't rely on the redirect working as you want - there is no redirect at all.
my .htaccess works fine when I type manually a wrong url it redirects to my custom 404 page. Here is my .htaccess (this the hole content (no other redirects)):
RewriteEngine on
ErrorDocument 404 http://codeexample.local/404.shtml
Now in my Silex based application I return a 404 status code if the client tries to edit a non existent client. Even though the status code is indeed 404 as i can see with curl -v. But for some reason it is not redirected to 404 error page.
Here is how I access the url:
http://codeexample.local/index.php/2/edit
Here is my index.php edit route section:
$app->match('/{id}/edit', function (Request $request, $id) use ($app) {
try {
$clientController = new ClientController($request, $id);
return $clientController->editAction($app);
}
catch(\Exception $e){
return $e->getMessage();
}
})
->assert('id', '\d+')
->method('GET|POST');
in my editAction method I am checking if the client exists in the database otherwhise I am returning a response like this:
$response = new Response(
'',
Response::HTTP_NOT_FOUND,
array('content-type' => 'text/html')
);
$response->prepare($request);
$response->send();
return $response;
Thanks
you should redirect to the error page.
$app->redirect( '/404.shtml' );
In your code you are creating a new Response with a statuscode. This is too late for the apacheserver to react.
And other idea is to call the function which creates the errorpage, but i would say don't do that to keep the code clean.
Your expectations are a bit off here, possibly. The web server will handle requests for addresses it has no knowledge of with a 404 response, and you can also provide it with some HTML to send along with the 404 response. But it's the 404 response that is really the important bit.
Telling the web server that 404.shtml is the mark-up to send back to the browser is not like a redirect to that page, it simply uses the contents of that file for the HTML to send back with the 404 response.
Silex knows nothing about that, as the web server's 404-handling is long since fallen out of the picture by the time Silex gets anywhere near the request. When there's a 404 condition at the Silex end of things you need to do two things: return a 404 code in the response (you're doing that now), and you can optionally send some content back too (like the markup in that 404.shtml file). If you want to have the same 404 mark-up as the 404.shtml that the web server uses... read that file and return it as the content with your 404 response.
You could try to go a different route and rejig your web server 404 to return the result of a Silex-routed URL, and then use that same route internally for the content of 404s from Silex too, but I think it's the wrong approach for the web server to be bugging PHP/Silex for a response to a request which has already been identified as invalid.
What you really really do not want to do is redirect from Silex to a doc containing mark-up for a 404. What that will do is tell the user agent that the URL it tried was incorrect, and it should try another one (as provided by the redirect header), which will then return a 404 message to the human in the mark-up, but will be returning 200-OK to the user agent. So in effect when a user agent browses to /someBadPage.html you'd be telling them the correct document for that URL is /404.html. Not that /someBadPage.html does not exist.
I am trying to implement login feature in Express.js version 4 app. I need to determine whether an user is logged in before he can do certain actions. So I have a middleware called as isLoggedIn which solely checks if user object is in session, if not, the user is redirected to login page. After the user successfully logs in, he must be redirected to the original URL.
app.get('/someaction', isLoggedIn, 'actual function to be executed');
Now inside isLoggedIn method, I see that req.url and req.originalUrl contains the requested action. However if the user is not logged in, when redirected to /login page, both req.url and req.originalUrl has /login as the contents. From what I read here, I can override req.url for internal routing purposes. But in my case both req.url and req.originalUrl gets overridden by /login action.
What am I doing wrong?
From the Express.js documentation:
req.url is not a native Express property, it is inherited from
Node’s http
module.
This property is much like req.url; however, it retains the original
request URL, allowing you to rewrite req.url freely for internal
routing purposes. For example, the “mounting” feature of app.use()
will rewrite req.url to strip the mount point.
In other words, req.url might be overwritten during the internal routing, while req.originalUrl will remain untouched.
The problem is that there are actually two entirely separate requests coming in to your server. The request for the /login page doesn't know anything about the page that the client requested before that. So when you redirect to the /login page, you need to save information about the originally-requested URL somewhere. I know of 2 solutions:
Some fancy work with session states allowing you to save the original URL as a variable, probably using promises.
Add the original URL as a query parameter to the /login request.
Check out this answer:
How do I find original request path before redirect Express 4
You could achieve user redirection post login to the originally requested Url by using expression-session.
Steps:
At the time when isLoggedIn middleware is run you should capture req.originalUrl to req.session variable e.g. req.session.returnToUrl = req.originalUrl.
Upon authentication you can check if returnToUrl is set and otherwise set redirection Url to any default value you prefer.
const redirectUrl = req.session.returnToUrl || "/anyOtherUrl";
After login redirect user to the Url using res.redirect(redirectUrl)
Credit to DevSprout and Colt Steele. A more detailed answer is available here
I want to redirect user from one page to another page in Node.js (plain node.js)
Real life scenario: Afer signup (example.com/sigup), after successful signup I want to redirect users to login page(example.com/login).
if (signUpSuccessful(request, response)) {
// I want to redirect to "/login" using request / response parameters.
}
It's simple:
if (signUpSuccessful(request, response)) {
response.statusCode = 302;
response.setHeader("Location", "/login");
response.end();
}
This will redirect your user to the /login URL with an 302 Found status and finish the response. Be sure that you haven't called response.write() before, otherwise an exception will be thrown.
Simplest way to do it is by using a 302 status code and a location field with the target URL.
The HTTP response status code 302 Found is a common way of performing
a redirection.
An HTTP response with this status code will
additionally provide a URL in the Location header field. The User
Agent (e.g. a web browser) is invited by a response with this code to
make a second, otherwise identical, request, to the new URL specified
in the Location field. The HTTP/1.0 specification (RFC 1945) defines
this code, and gives it the description phrase "Moved Temporarily".
Source: Wikipedia
res.statusCode = 302;
res.setHeader("Location", '/login');
res.end();
A simpler way :
res.redirect(307, '/login');
Find more details in the answer of this post