Page not found "/" route - node.js

I'm trying to setup a VueJS app using Nuxt for server side rendering. However after deployment to my server the index.vue is return a 404 Page not found error.
This doesn't happen when run on my development machine, and still happens even if run in Development mode on my server.
All other routes work, and getting to the index route from within the app itself works fine. It just doesn't load when refreshed. Eg:
http://myapp.com/ Doesn't work
http://myapp.com/login Works fine
My pages folder currently looks like this:
- pages
-- index.vue
-- login.vue
I have nothing fancy set up within my nuxt.config file and have pretty much the same setup as is described in the Auth0 example
On my server I'm running nuxt with the command pm2 start npm --name "my-app" -- start Which runs fine without any errors, and I have the following .htaccess config:
RewriteCond %{HTTP_HOST} ^my-app\.com$ [OR]
RewriteRule ^(.*) "http\:\/\/127\.0\.0\.1\:3000\/$1" [P,L]
This is the error screen I get:
The page itself is very basic at the moment, it did have far more on it however I've cut it down to the following trying to debug this issue:
<template>
<v-container grid-list-md>
<v-layout row wrap>
<h1>Test index, trying to fix the 404</h1>
<h2>Hello, {{ loggedUser ? loggedUser : 'friend' }}!</h2>
</v-layout>
</v-container>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
computed: mapGetters([
'isAuthenticated',
'loggedUser'
])
}
</script>

I seem to have managed to fix this. However, I'm not completely sure on the cause the fix involved modifying my .htaccess. I started playing with the settings and ended up with the following which works well (for now at least).
RewriteCond %{HTTP_HOST} ^my-app\.com$
RewriteRule "(.*\.(jpg|gif|png|svg|js|css))$" "http://127.0.0.1:3000/$1" [P,NC]
RewriteRule ^(.*) "http\:\/\/127\.0\.0\.1\:3000\/$2" [P,L]
The rule for jpg|gif etc is required as they don't load when using the second rule.

Related

Next.js Run midddleware only for the homepage

Is there any way to execute middleware function only for the homepage (root page of the website)
I'm using the following execution order:
- /pages
- _middleware.js
- index.jsx
- /about
- index.jsx
The following _middleware.js will run for both / and for /about pages. Is it possible to run middleware only for / page?
P.S. I know that I can just check if current page path is the root of the website in the middleware itself. However, it is still going to be executed in sub-directories just without my custom checks.

React Router v4 URL issue

Ours react app works in dev mode (localhost) perfectly, but when we put it onto the Heroku server we cannot access routes directly. When we do history.push({ }) to our path we get a 404 page.
You can see the page here: placemate.herokuapp.com
Steps to reproduce: go to the above URL, see it load. Then add /login to the URL bar and you will see that a 404 page appears. However, clicking a login from the header will direct you properly.
Here is our router code:
import React from 'react'
import { Switch, Route, Redirect } from 'react-router-dom'
import '../../App.css'
import Home from '../../scenes/general/home/Home'
import Login from '../../scenes/general/login/Login'
import Register from '../../scenes/general/register/Register'
import GuestHeader from '../../components/general/header/Header'
const Main = () => (
<main className='main_app'>
<GuestHeader />
<Switch>
<Route exact path='/' component={Home}/>
<Route path='/login' component={Login}/>
<Route path='/register' component={Register}/>
</Switch>
</main>
);
export default Main;
index.js file:
ReactDOM.render(<BrowserRouter><App /></BrowserRouter>, document.getElementById('root'));
registerServiceWorker();
Why 404 Not Found
This is because when you put up any path in your address bar its request is sent to the web server not react. As you know the react-router we are using is responsible to display the correct component based on the route, but since you pass the route to nginx / apache server not react-router; hence your web server tries to find www.example.com/login which actually does not exist. Hence you get 404 not found.
Solution
Try to create a .htaccess file on your web server public HTML root directory. Create some rules so that the request is always forwarded from the root path. This will let the react come into the picture, hence the react-router can grab the path and render the appropriate component.
For example, you can create something like this
For Apache server
RewriteEngine On
# If an existing asset or directory is requested go to it as it is
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
#RewriteCond %{SERVER_PORT} 80
#RewriteRule ^(.*)$ https://www.example.com/$1 [R,L]
RewriteRule ^ - [L]
# If the requested resource doesn't exist the serve index.html
RewriteRule ^ ./index.html
For Node.js
Sample code for node.js express server can be like this (present in file for server implementation, conventionally named as server.js)
const express = require('express');
const path = require('path');
const app = express();
if(process.env.NODE_ENV!== 'production'){
//do something if you are in development environment
//below lines only if you are using webpack based deployment
const webpackMiddleware = require('webpack-dev-middleware');
const webpack = require('webpack');
const webpackConfig = require('./webpack.config.js');
app.use(webpackMiddleware(webpack(webpackConfig)));
}
else{
// in production env do following thing
app.use(express.static('public_html_folder'));//give user access to public assets
//redirect all request to index.html for compatibality with react router
app.get('*',(req,res)=>{
res.sendFile(path.join(__dirname,'public_html_folder/index.html'));
});
}
app.listen(process.env.PORT || 3050, () => console.log('Listening'));
I hope this solves your problem or at least give you an idea of what to do if there is a different backend server.

Get project base url that works in XAMPP and on production, considering .htaccess

I have a project that is not in the root of the XAMPP folder:
htdocs/my-folder/projects/my-project
htdocs/my-folder/projects/my-project/index.php
htdocs/my-folder/projects/my-project/js/
htdocs/my-folder/projects/my-project/css/
that folder contains an index.php file from where I try to call stylesheets and scripts. Initially, I'd just do it like this:
<script src="js/myscript.js"></script>
which worked. However, the project has expanded and now a user can "save" the current page (similar to how JSFiddle does it), and the URL will look different. Upon a first save a random string will be appended as a conf parameter, which results in something like this (locally) and should have a public equivalent:
localhost/my-folder/projects/my-project?conf=abcd # locally
http://mywebsite.com/projects/my-project?conf=abcd # publicly
Upon second save, the URL gets an additional parameters, a version number:
localhost/my-folder/projects/my-project?conf=abcd&v=2 # locally
http://mywebsite.com/projects/my-project?conf=abcd&v=2 # publicly
But, to get a nice URL I use this .htaccess:
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (\w+)[/](\d+)$ ?conf=$1&v=$2 [L,NC]
which will result in something like this:
localhost/my-folder/projects/my-project/abcd/2 # locally
http://mywebsite.com/projects/my-project/abcd/2 # publicly
The thing is, when the URL is changed to some structure as above (without the parameters, but with the rewritten URLs, e.g. localhost/my-folder/projects/my-project/abcd/2) then the initial call to the resources (scripts, styles) in my index file won't be correct any longer.
In other words, if this is the url: localhost/my-folder/projects/my-project/abcd/2 then the server will look for a a script file in localhost/my-folder/projects/my-project/abcd/2/js/myscript.js, which is obviously wrong.
The question, thus, is: how can I get the absolute path to the current file, but that also works in XAMPP (so not __FILE__ or __DIR__ which will dig in the file strucure and return file://) and also on production environments.
You'll have to use the base element in your pages. The usage will be something like:
<base href="/projects/my-project/" />
for the public server and
<base href="/my-folder/projects/my-project/" />
locally.
I hackingly figured it out. By checking the end of the url, we determine if we are in root or if we are in a specific instance (ending with a digit e.g. /1.
<?php
// Is connection secure? Do we need https or http?
// See http://stackoverflow.com/a/16076965/1150683
$isSecure = false;
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
$isSecure = true;
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])
&& $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https'
|| !empty($_SERVER['HTTP_X_FORWARDED_SSL'])
&& $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') {
$isSecure = true;
}
$REQUEST_PROTOCOL = $isSecure ? 'https' : 'http';
$REQUEST_PROTOCOL .= '://';
// Create path variable to the root of this project
$path_var = $REQUEST_PROTOCOL.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
// If URL ends in a slash followed by one or more digits (e.g. http://domain.com/abcde/1),
// returns a cleaned version of the URL, e.g. http://domain.com/
if (preg_match("/\/\d+\/?$/", $path_var)) {
$path_var = preg_replace("/\w+\/\d+\/?$/", '', $path_var);
}
?>
Now we can use it in our PHP file!
<link href="<?php echo $path_var; ?>css/styles.css" rel="stylesheet">

Getting Flask to use the desired URL behind mod-rewrite

I have a Flask app running under mod_wsgi on Apache. Due to various parts of the website being static and others being dynamic, the dynamic parts of the website are routed to the Flask app using mod_rewrite as shown below:
.htaccess
RewriteEngine on
RewriteBase /
RewriteRule ^(foo(/.*)?)$ /myapp.wsgi/$1 [L,QSA]
RewriteRule ^(bar(/.*)?)$ /myapp.wsgi/$1 [L,QSA]
# etc.
myapp.wsgi
from flask import Flask, request
application = Flask(__name__)
#application.route("/foo/")
def foo():
return request.url
#application.route("/bar/")
def bar():
return redirect(request.url + "baz/")
When I visit http://www.mywebsite.com/foo/ the page tells me that my URL is http://www.mywebsite.com/myapp.wsgi/foo/.
When I visit http://www.mywebsite.com/bar/ the page redirects me to http://www.mywebsite.com/myapp.wsgi/bar/baz/.
This also happens with Flask's automatic redirects: when I visit http://www.mywebsite.com/foo (no trailing slash), Flask redirects to add the slash, but it redirects to http://www.mywebsite.com/myapp.wsgi/foo/.
Is there an easy way to get the Flask app to not include the /myapp.wsgi in the URLs and instead use just use URLs relative to where the routes are? (e.g. /foo/ and /bar/)
This can be solved by removing the name of the script from the SCRIPT_NAME environment variable using some middleware as in the below example taken from the Flask docs.
from yourapplication import app
class ScriptNameStripper(object):
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
environ['SCRIPT_NAME'] = ''
return self.app(environ, start_response)
app = ScriptNameStripper(app)
I don't know if I understood well but you might want to use url_for function documented here :
http://flask.pocoo.org/docs/0.10/api/#flask.url_for
It allows you to construct URLs by referencing endpoints of you application.
For example url_for('bar') would construct the relative URL pointing the bar endpoint.

Background disappear .htaccess

I just finished my .htaccess file, only rewriting to a nicer URL, but with no reason the background disappeared. If I access with the ugly old URL the background is there.
<html...
...
<style type='text/css'>
body { color:#FFF;background:#444 url(office_1.png); }
body { margin:0;padding:0; }
</style>
</head>
The .htaccess:
RewriteRule download/(.*)/u_id/(.*)/id/(.*)/n/(.*)$ download.php?on=$1&u_id=$2&id=$3&n=$4
RewriteRule download/(.*)/u_id/(.*)/id/(.*)/n/(.*)/$ download.php?on=$1&u_id=$2&id=$3&n=$4
RewriteRule download/(.*)/u/(.*)/id/(.*)/n/(.*)$ download.php?on=$1&u_id=$2&id=$3&n=$4
RewriteRule download/(.*)/u/(.*)/id/(.*)/n/(.*)/$ download.php?on=$1&u_id=$2&id=$3&n=$4
The .htaccess rule is working, but why my background disappeared?
The URI is relative, so it is looking for the image in
/your/nice/uri/office_1.png
Not in
/office_1.png
The usual fix is to start the image path with a / as I have in the above example to make it relative to the root of the site.
url(/office_1.png);

Resources