How do I use this.$http.post wihtout redirect in a method of a Vue component? - vue.js

I request from a method in a Vue component with this.$http (from https://github.com/pagekit/vue-resource) like this:
this.$http.post("/some/url", data).then(response => { ... })
In some cases the response may have status code 302 Found and I want to process it in the callback in then. But instead the this.$http.post follows the location URL provided by the first response that is not desired. How do I force this.$http.post not to redirect?

Related

Vue - check localStorage before initial route (for token)

I have a Vue app which does a little localStorage and server check on app load, to determine where to initially route the user.
This is in the App's main entry component, in the created() hook
My problem is that the default / route's Component visibly loads first, then the server call and everything happens which causes the user the route to their correct location
How can I delay the rendering of the initial component until my app's main component created() method completes, and then purposely navigates the user to the correct route?
I had this problem before and I firmly believe that you must have the initial files for your routes and your router configuration.
In the configuration, you could handle the permission and router before each route and with next() . In the router file, you can set your params and check them in the index.js file(router configuration)
you could also use your localStorage data in Router.beforeeach
EDIT: I just saw you used the created method... like mentioned below use beforeRouteEnter instead with the next() parameter it provides
First of all I wouldn't recommend using a delay but instead a variable that keeps track if the API call is done or not. You can achieve this using the mounted method:
data() {
return {
loaded: false,
}
}
async mounted() {
await yourAPICALL()
if (checkIfTokenIsOkay) {
return this.loaded = true;
}
// do something here when token is false
}
Now in your html only show it when loaded it true:
<div v-if="loaded">
// html
</div>
An better approuch is using the beforeRouteEnter method which allows you to not even load the page instead of not showing it: https://router.vuejs.org/guide/advanced/navigation-guards.html

How to get Stack Overflow SEO friendly URL structure in Nuxt.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 });
}
},

Vue2 $router.replace() does not call mounted hook

I have Nuxt Vue 2 app. There is a redirect in the mounted hook to the same route. The only difference in this route is query string. It looks like
mounted() {
...
if( !isTokenOwner ) {
const result = await this.$api.campaignNewShare.copyNewShare(this.newShareToken);
localStorage.setItem(result.data.token, new Date().getTime());
this.$router.replace({'name': 'campaigns-new', 'query': {token: result.data.token}});
this.loading = false;
return;
}
}
It seems that Vue stays on the same page and only replace the url query string parameter. But I need to redirect to the new location with whole new lifecycle.
Can somebody tell me what really happened there after the replace() call? Why it does not trigger the real redirect? Thnaks.
Ok so as documentation says
One thing to note when using routes with params is that when the user
navigates from /user/foo to /user/bar, the same component instance
will be reused. Since both routes render the same component, this is
more efficient than destroying the old instance and then creating a
new one. However, this also means that the lifecycle hooks of the
component will not be called.

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
}
}

Vue-Routes redirect doesn't work and beforeEnter render App component again

I'm getting some issues when trying to redirect to an external link.
for ex:
{ path: '*', redirect: 'https://google.com'}
when I use "redirect" it doesn't work completely, but when I use something like that
{ path: '/*',
beforeEnter(to, from, next) {
window.location = "https://google.com"
}
}
it works but there is a problem because first, it tries to render App component again but there is no component so be empty and a blank page is being rendered for nearly 1-1.5 second then it redirects to target URL and I don't want it to reload App component, just redirect it to other link. I googled but found nothing noteworthy.
Or maybe is there another way like deactive a component or use v-if or directly rendering a html file?
redirect is meant to redirect to another route defined by your application, not to go to another website directly.
window.location works, but I think the behavior is somewhat browser-dependent.