How to get Stack Overflow SEO friendly URL structure in Nuxt.js? - vue.js

Stack Overflow has the following URL structure stackoverflow.com/questions/{question ID}/{question title}, and if you misstype the {question title} you will be permanently redirected 301 to the correct URL as long as you have the correct {question ID}.
Assuming that I have both the id and the slug, how can I make the same URL structure that Stack Overflow has in Nuxt.js with SSR?
Edit: Apprently the URL structure is known as Clean URL.
I have tried using a fully dynamic URLs with pages/x/_.vue, but that gives me a "new" page for each request and does not give a 301 redirect.
This post suggest the following: /questions/8811192/question-title could be rewritten to /mywebsite.php?id=8811192&convention=questions. So if I can interpret /qeustions/{id}/{title} as just /qeustions/{id} I could be halfway there I guess.

The following works for me, but I am not sure if it's the exact same as how the Stack Overflow URL structure works.
I am using async asyncData to get content from the database, and as you can access
context and redirect, req and res as parameters you can perform a 301 redirect.
First I am using unknown dynamic nested routes in my folder like this /pages/folder/_.vue. Which will catch all routes including domain.com/folder/{id} and domain.com/folder/{id}/{title}.
To get the ID of in the requested url you can split the pathMatch and get the first element, like this params.pathMatch.split('/')[0].
Then I use the id to get the content from the database, which is Strapi in my case. Like this await $strapi.findOne('contentType', id).
After that we can create the actual URL we want like this /folder/${data.id}/${data.slug}. Note: the data.slug culd be replaced with the data.title which could be converted to a URL friendly string.
Finally we can match the user requested URL with the actual URL of the content if(route.fullPath !== actualURL), and if the requested url is not the same we can performe a redirect with redirect(301, actualURL).
My entire code:
async asyncData({ redirect, req, route, app, $strapi, error, params }) {
try {
const recipeID = params.pathMatch.split('/')[0];
const matchingRecipe = await $strapi.findOne('recipes', recipeID);
const correctPath = `${app.localePath('recipes')}/${matchingRecipe.id}/${matchingRecipe.slug}`;
if(route.fullPath !== correctPath) {
console.log(`Redirect: ${route.fullPath} => ${correctPath}`);
redirect(301, correctPath);
}
return {
recipe: matchingRecipe
}
} catch(e) {
console.log(e)
error({ statusCode: e.statusCode, message: e.original });
}
},

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 solve 404 error in axios post request in vue?

i want send request to an api but i have 404 erro and i have nothing in network
can you help me?
my code:
loginMethod() {
const config = {
userName: "test#gmail.com",
password: "1234test",
};
return new Promise((resolve) => {
ApiService.post("api/authentication/login", config)
.then(({ data }) => {
console.log(data);
resolve(data);
})
.catch(({ response }) => {
console.log(response);
});
});
},
and ApiService function:
post(resource, params) {
console.log(params);
const headers = {
"E-Access-Key": "bb08ce8",
};
return Vue.axios.post(`${resource}`, params, { headers: headers });
},
Based only on what I can see in your code, you are not telling axios the complete URL if I'm right about it, and you didn't declare it somewhere else do this:
axios.post('yourdomain.com/api/authentication/login',params)
or
axios({
url:'yourdomain.com/api/authentication/login',
method:post,
data:{}
})
or
in your main js file or any other file that you import axios (if you are sharing an instance of it globali):
axios({baseurl:'yourdomain.com'})
and then you don't need to write the complete url everywhere and just insert the part you need like you are doing now and axios will join that address with the baseurl,I hope it helps
I guess the URL "api/authentication/login" might be wrong and the correct one would be "/api/authentication/login" that starts with /.
404 error means the resource referred by the URL does not exist. It happens when the server has deleted the resource, or you requested a wrong URL accidentally, or any wrong ways (e.g. GET vs POST)
To make sure if you were requesting to the correct URL (and to find where you're requesting actually), open Google Chrome DevTools > Network panel. You might need reload.
The url api/xxx is relatively solved from the URL currently you are at. If you were at the page http://example.com/foo/bar, the requested URL becomes http://example.com/foo/bar/api/xxx. Starting with / means root so http://example.com/api/xxx.
This answer might help to understand the URL system: https://stackoverflow.com/a/21828923/3990900
"404" means your API Endpoint is not found. You need to declare the location of your API Endpoint exactly. For example: http://localhost:8080/api/authentication/login.

Nuxtjs/Vuejs with axios trying to access URL results in Access to XMLHttpRequest at has been blocked by CORS policy

I am aware there are many answers related to this question but since nothing seems to work I am posting here.
I have NuxtJS/Vuejs application within which users can provide the GitHub URL (mostly the URL will contain the XML/JSON files). After getting the URL, I want to make a request to the URL using the axios and obtain the data present within the URL.
When I try to make a request i get the following error:
Access to XMLHttpRequest at 'GitHub URL' from origin 'http://localhost:3000' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values 'Some GITHUB URL', but only one is allowed.
When I provide the same URL in the browser then I get the 302 status and obtain the raw JSON/XML data after redirection. I want to implement the same in my code.
If data is not found in the URL then obtain the redirection URL from the response and make another request with the new URL. But due to the CORS error and other error GET GIT HUB URL net::ERR_FAILED I am unable to get the response.
I tried many things mentioned on the website such as:
Adding proxy as mentioned here: https://stackoverflow.com/a/55481649/7584240
Adding a prefix to URL as mentioned here: https://stackoverflow.com/a/56781665/7584240
Adding the condition to axios as mentioned here: https://stackoverflow.com/a/48293817/7584240
And many other things but nothing seems to work for me and getting the same error. Can someone please help me with this issue?
Following is the sample code I have (The code is part of VUEX Store actions):
export const actions = {
obtainURLData ({ commit, state, dispatch, rootState }, inputURL) {
axios
.get(inputURL)
.then((response) => {
console.log('INSIDE RESPONSE')
console.log(response)
console.log(response.data)
if (response.status === 200) {
}
})
.catch((error) => {
console.log('INSIDE ERROR')
console.log(error)
console.log(error.response)
console.log(error.response.data.detail)
console.log(error.response.status)
})
}
}

Handling GET 301/302 responses with JavaScript in Vue.js

I need to print some 301/302 response headers with JavaScript: I saw lots of answers for Angular, but I’m using Vue.js to get the results. Well, it doesn’t really matter since it’s mainly a JavaScript issue… I mean, I’m not just interested in a Vue.js-only solution, it could and should work everywhere. As a front-end developer, I can’t manually create a scenario in which my project returns a redirect in its own server and finding a random remote page that does it without CORS limitations is hard. To be even more clear, I need to get status code and statusText of 301/302 responses (as well as the Location of the new page) before the redirection, then the full headers of the redirected page. Now I can retrieve only these last, because the default this.$http.get(); request created by vue-resource doesn’t seem to store the first in an object. What I’m asking here is if there’s a way to store the redirection response in a variable too, then to show both. I don’t know if switching to axios could be preferrable — since I’m pretty new to Vue.js. My component’s method is as follow:
getRequest: function() {
this.$http.get(this.url)
.then(function(response) {
if (response.ok) {
if (response.status === 301 || response.status === 302) {
// show the redirecting response
}
// show the redirected response
}
}
EDIT: the sources for this project are on GitHub; when you send a GET request and the response says 301/302, you should be able to see three columns instead of two where the second shows details of the redirecting response headers.
You are not able no handle 301 or 302 status because those are inside the
if(response.ok)
block, which means that the status is 200. Try this instead:
getRequest: function() {
this.$http.get(this.url)
.then(function(response) {
if (response.ok) {
// show the redirected response
}
if (response.status === 301 || response.status === 302) {
// show the redirecting response
}
}

Nuxt 404 error page should redirect to homepage

I am looking for a way to always redirect to homepage when a page doesn't exist using Nuxt.Js.
Our sitemap generation had some problems a few days back and we submitted wrong urls that do not exist. Google Search Console shows a big number of 404 and we want to fix them with 301 redirect to homepage.
I tried this
created() {
this.$router.push(
this.localePath({
name: 'index',
query: {
e: 'er'
}
})
)
}
and although the page redirects to homepage successfully I think Google will have problems with this since the pages initially renders with 404.
I also tried this
async asyncData({ redirect }) {
return redirect(301, '/el?e=rnf')
},
but didn't work (same with fetch)
Any ideas on a solution to this?
Never redirect to home if page is not found as you can see in this Google's article: Create custom 404 pages
instead, redirect to 404 error page
Just use error
async asyncData({ params, $content, error }) {
try {
const post = await $content('blog', params.slug).fetch()
return { post }
} catch (e) {
error({ statusCode: 404, message: 'Post not found' })
}
}
do not forget to creat an error page in layout folder error.vue
You are able to create a default 404-page in nuxt - just put a file with a name _.vue in your ~/pages/ dir. This is your 404-page :)
or you can use another method to create such page: https://github.com/nuxt/nuxt.js/issues/1614 but I have not tried it
Then add a simple 404-redirect-middleware to this page:
// !!! not tested this code !!!
middleware: [
function({ redirect }) {
return redirect(301, '/el?e=rnf')
},
],
Personally I would advise to create a 404 page which provides a better user experience in comparison to being redirected to a homepage and potentially being confused about what happened.
In order to create a custom error page, just create error.vue file in the layouts folder and treat it as a page. See the official documentation. We've implemented this plenty of times and Google has never complained about it.
Still, gleam's solution is clever and if it serves the purpose, very well. Just wanted to point out another solution.
If you need to provide custom routes to your users like domain.com/<userID>
then putting a file with a name _.vue in your ~/pages/ directory will not work, because you'll need it for your custom user routes.
For maximum flexibility use the layouts folder as mentioned by Dan
Create a file called _.vue at pages directory with content:
<script>
export default {
asyncData ({ redirect }) {
return redirect('/')
}
}
</script>