Nuxt.js routing - vue.js

I am migrating from ASP.NET MVC to Nuxt.js and I am trying to keep the same urls so I can keep the SEO ratings
My current URLs are
www.url.com/#computers/#laptops/#dell?page=1
All of the # are dynamic values so URL might also be
www.url.com/#phones/#smartphones/#apple?page=1
What is the easiest way to point all these URLs to one page ITEMS and to be able to get values for every # and also for QueryString values ?
Thanks in advance

You can accomplish this with serverMiddleware in nuxt
Make a file for your middleware:
middleware/server/seoMiddleware.js
Add that to your nuxt.config.js in the serverMiddleware block:
serverMiddleware: [
'~/middleware/server/seoMiddleware.js'
]
Create a file to handle a list of your 301's:
middleware/server/301.js
Add your path mapping using regex in your 301.js:
export default [
{ from: '/(#[\w\d]+)\/(#[\w\d]+)\/(#[\w\d]+)', to: 'items', capture: true }
]
Pop open your seoMiddleware.js
const redirects = require('./301.js').default
export default function (req, res, next) {
const redirect = redirects.find(redirect => req.url.test(redirect.from))
if (redirect) {
const to = redirect.capture ? applyCapturesToUrl(req.url, redirect) : redirect.to
res.writeHead(301, { Location: to })
res.end()
}
// failover
next()
}
const applyCapturesToUrl(url, redirect) {
const matches = url.match(redirect.from)
return `/${redirect.to}/` + matches.map(match => match.replace('#', '')).join('/')
}
We've used some simple regex here to create capture groups based on your URL structure and and serverMiddleware to intercept the request and return a 301 (permanent redirect) if we find a match. We failover with next() and allow the request through if there was no match found. We use a capture flag on the redirect object so we know when we're dealing with capture groups, without it we can just do simple pattern matching.

Related

How to redirect if subdirectory includes hash Nuxt?

At the request of the SEO specialist, I need to implement the following functionality.
I have to redirect if the link contains a capital letter.
For example https//domain.com/#Contacts ==> https//domain.com/#contacts.
In Nuxt I implemented with by creating function on server.js file which located on middleware folder.
But it doesn't work if path contains hash(#)
export default function (req, res, next) {
const url = req.url;
if (url !== url.toLowerCase()) {
res.writeHead(301, { Location: url.toLowerCase() });
res.end()
} else {
next();
}
}
I would be grateful if you answer or help
The part after the hash (fragment identifier) is never going to be sent to the server by your browser, so what you're trying to do is impossible using redirects.
You can access them on the client-side, but I don't think that it would do any good in terms of SEO.

How to protect multiple routes from unauthorized access in Next.js using next-auth

I am using Next.js and I have a folder learning inside my pages folder. Now, this learning folder has about 10 pages.
All these pages need to redirect to the index page if the user is not logged in. The following code does the job, but is there any other way to protect multiple pages, so that I don't need to add this same code again and again to all the pages ?
export async function getServerSideProps(context) {
//redirect to index page if not logged in
const session = await unstable_getServerSession(context.req, context.res, authOptions);
if (!session) {
return {
redirect: {
destination: '/',
permanent: false
}
}
}
}
I believe you are confused between protecting pages and protecting API ROUTES.
If you simply want to protect pages, you can indeed use middleware
However, if you wish to protect API Routes (e.g prevent a user from deleting data using your API endpoint and postman), I believe you need to use this unstable_getServerSession
Except creating reusable function, it's true that I didn't find anywhere in the doc how to set it for multiple paths in one folder only...
you can use middleware. docs: https://next-auth.js.org/configuration/nextjs#middleware
Create a middleware.ts (or .js) file at the root or in the src directory (same level as your pages).
If you only want to secure certain pages, export a config object with a matcher:
export { default } from "next-auth/middleware"
// otherwise your app would require authentication for all
export const config = { matcher: ["/dashboard"] }
Now you will still be able to visit every page, but only /dashboard
will require authentication.
If a user is not logged in, the default behavior is to redirect them
to the sign-in page.
that example is from the docs. You can also write a custom middleware
import { NextResponse } from "next/server";
export function middleware(req) {
const sessionCookie = req.cookies.get("session");
}
// you could add more if logic for other pages
if (req.nextUrl.pathname.startsWith("/admin ")) {
if (!sessionCookie) {
return NextResponse.redirect("/home");
}
}

Wildcard subdomain routing with nuxt

I'm relatively new to Nuxt and I'm trying to implement subdomain routing in my Nuxt app, so that a request to:-
mysubdomain.myapp.com is routed to myapp.com/groups/:slug
mysubdomain.myapp.com/<anything else>/ is routed to myapp.com/groups/:slug/<anything else>
where slug is the subdomain.
From what I can see, there are two possible ways to do this. Either extendRoutes in the nuxt config or by using my own router.js file. But I can't work out how get the subdomain into the route.
I've got something like this in my router.js:-
import Router from 'vue-router'
export function createRouter(ssrContext, createDefaultRouter, routerOptions) {
const options = routerOptions || createDefaultRouter(ssrContext).options
const hostname = ssrContext ? ssrContext.req.headers.host : location.host
return new Router({
...options,
routes: fixRoutes(options.routes, hostname.match(/[^.]*/)[0]),
})
}
function fixRoutes(defaultRoutes, subdomain) {
return (
defaultRoutes
.map((route) => {
// TODO use the subdomain in here to route to /groups/:slug route
return route
})
)
}
It feels like I'm close but I can't figure out this last bit. Is this even possible?!

hapi single page application using inert plugin doesn't serve up api route

I am trying to build a single page application using hapi and inert.
my example code is here: https://github.com/7seven7lst/hapi-inert-test
and the base of the project is built from the answer here nodejs hapi single page
Basically I would like to both server static file and api json data to front end. I know how to do this in express, but haven't figure out how with hapi. the delimma is : if I use hapi only, it doesn't serve up static file, and if i use hapi+inert, it wont' serve up api route.
solutions????
The documentation says that the route handler chooses the route from most specific to least specific. So you can pre-fix your api routes with something like /api/v1/ and then everything else that doesn't begin with /api/v1/ will get routed to static files dished up by inert.
Hapi.js Routing Documentation:
When determining what handler to use for a particular request, hapi searches paths in order from most specific to least specific. That means if you have two routes, one with the path /filename.jpg and a second route /filename.{ext} a request to /filename.jpg will match the first route, and not the second. This also means that a route with the path /{files*} will be the last route tested, and will only match if all other routes fail.
'use strict'
const Hapi= require('Hapi')
// Config
var config= {
connection: {port: 3000, host: 'localhost'}
}
const server= new Hapi.Server()
server.connection(config.connection)
const plugins= [
// https://github.com/hapijs/inert
{ register: require('inert'), options: {} },
]
function setupRoutes() {
// Sample API Route
server.route({
method: 'GET',
path: '/api/v1/Person/{name}',
handler: function (req, reply) {
reply('Hello, '+ encodeURIComponent(req.params.name)+ '!')
}
})
// Web Server Route
server.route({
method: 'GET',
path: '/{files*}',
// https://github.com/hapijs/inert#the-directory-handler
handler: {directory: {path: '../html_root', listing: false, index: true } }
})
}
server.register(plugins, (err)=> {
if (err) {throw err}
// Initialize all routes
setupRoutes()
// Start the Server
server.start((err)=> {
if (err) {throw err}
server.log('info', `Server running at: ${server.info.uri}`)
})
})

How to setup Sails.js routes to support pushstate with a SPA on the frontend

How to setup SailsJS routes to support pushstate, but still be able to serve requests prefixed with /api along with serving static assets as well?
Using:
Backbone 1.x with pushState: true
Sails 0.10.x
Suggested solution from this thread is to use the /* wildcard and redirect all to the index view.
/path/to/app/config/routes.js
'/*': {
view: 'index'
}
The problem is that this will redirect everything to index. including static file assets, the express.static middleware doesn't seem to have an effect, this route is somehow taking precedence.
Also, this prefix below doesn't have any effect, since the route above takes precedence, however the prefix works if I just remove the wildcard i.e '/': { view: 'index' }
/path/to/app/config/blueprint.js
module.exports.blueprints = {
...
prefix: '/api',
...
}
Obviously, this does not seem as a core SailsJS issue, but rather my minimal knowledge the expressjs router, since that's what sailsjs is using.
Theoretically, I could explicitly just list out all the assets prefixed routes and have a controller to serve all, since they are well known and static i.e. '/js*': { controller: 'AssetsController', action: 'serve', and so on for '/styles*', '/images*', '/templates*', '/fonts*', but I'm really hesitant on doing so, I'm hoping for a better practice solution.
Also that won't solve this routes /api problem with the wildcard '/*'
If you're willing to use the development version of Sails from GitHub, you can use the skipRegex route option to let your wildcard route ignore API requests, and the skipAssets option to have it ignore asset URLs:
'/*' : {view: 'index', skipAssets: true, skipRegex: /^\/api\/.*$/}
Otherwise, you can create a controller to serve your view, and add the code to skip unintentionally-matched URLs in the action code:
// api/controllers/StaticController.js
module.exports = {
index: function(req, res, next) {
if (req.path.match(/\..*/g) || req.path.match(/^\/api\/.*$/)) {
return next();
}
return res.view('index');
}
}
Then in /config/routes.js:
'/*': 'StaticController.index'
......
Try updating your config/404.js file.
Remove the following:
res.status(result.status);
res.render(viewFilePath, function (err) {
// If the view doesn't exist, or an error occured, send json
if (err) { return res.json(result, result.status); }
// Otherwise, serve the `views/404.*` page
res.render(viewFilePath);
});
Add this: res.redirect("/");
Cheers