Nuxt - Axios requests on server side not sending referer - node.js

The story
My backend app provides SEO information for my sites pages. One of this informations are OpenGraph meta tags, such as og:type and og:url.
og:url value is given by the API through the HTTP "Referer" header.
What I'm doing now
I'm using Axios module to make my requests.
Through asyncData function in my pages I can get the req variable and it's headers.referer property, which is what I want, like this:
// page.vue
async asyncData({ app, req }) {
app.$axios.setHeader('Referer', req.headers.referer);
}
The problem
If I am at the index page, let's say, then I click in a link to a dynamic page I got an error, for req is not available on asyncData function while navigating, I suppose.
The question
How can I dynamically get my requests referers to send it with Axios request for both client-side and server-side requests?
Info about the versions:
nuxt: 1.4.2
#nuxtjs/axios: 5.3.1

You can do something like this:
async asyncData({ app, req }) {
const referrer = process.client ? window.document.referrer : req.headers.referer
app.$axios.setHeader('Referer', referrer)
}

Related

Page not changing onClick using useNavigate in React?

I have a very basic UI for a login page:
Upon clicking the LOGIN button, the following methods gets called:
async function loginPatient(){
let item ={username:userName, password};
let result = await fetch("http://localhost:8000/users/login",{
method:'POST',
headers:{
"Content-Type":"application/json",
"Accept":"application/json"
},
body: JSON.stringify(item)
});
alert(result);
alert("breakpoint")
result = await result.json();
localStorage.setItem("user-info",JSON.stringify(result));
nav('/patient')
}
At this point I simply want it to change the page when the button is clicked. My API returns the following information from the database:
To test I did console.log("hello world") in the first line of the function and it works
However, If I run console.log("hello world") after the let result = await fetch(...) part it does not work. How can I test this to see why it's not working ?
Here are the errors from the console:
I did not write the API and do not know how Node works yet, I am just doing the front end for this
The issue is code is never reaching after fetch line, basically request is failing, the error on console is saying the due to CORS issue, the request failed, and in your loginPatient function, you have not handled the failed case, if you just wrap your fetch call inside try/catch block, you will see your code will fall into fail block, as api failed.
You need to enable CORS on your server or backend, Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading resources.
You can read more about cors at:
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
Looks like your client is on some other domain or port(if your are developing locally) than your server. You need to enable CORS permission for your client url.
And if you are using express for your backend, you can check the following url to enable cors.
https://expressjs.com/en/resources/middleware/cors.html
And last thing why Postman is getting success response, because it is by passing this cors check, as Postman is making request from it's server to your direct server instead of browser.
First initialize you navigation variable as follows
const navigate =useNavigate()
then navigate to you specific route by returning you navigation variable as follows.
return navigation("/");
Happy Coding!

Create cookies on other domains via javascript

I'm working on a project where I need to create a cookie in another domain of my application, I know that doing it directly is not possible because that would be a security flaw.
Example scenario:
Frontend: epictv.cf
Streaming Backend: ipv4-epictv001.infra-imm.epictv.cf
Reason: I need a <video> tag to be pre-authenticated in the streaming domain, since you can't pass any type of header in the tag.
For that I thought of making the frontend make a request to the backend and pass in the "body" of this request (GET) the value of the cookie I want to create, but for some reason when axios makes this request the cookie is not created, in however, if i open the route manually works fine!
How could I get the frontend to place a cookie on the backend?
My attempt code:
async createCookie(req, res){
const session = req.params.session;
res.cookie("sessao", session, { maxAge: 1000000 });
res.status(200).json({
"status": "ok"
});
},
PS: I know that in the video tag I could pass the url with the authentication in the src itself, but I would rather not do it.

Post a simple react form - node, axios, nodemailer, backend, postman

I've set up a react form running on http://localhost:3000/about and I've the backend running on port 5000 (localhost:5000). On react's package.json I set up "proxy":"localhost:5000:.
When I use postman and I send the post to localhost:5000/api/contact, the email is sent correctly (I send the data as JSON - name, email and message). Status 200
When I use the react form, the data is well prepared as json but I can't figure out the baseURL to send correctly the method post. status 404. I tried:
localhost:3000/about/api/contact;
localhost:3000/api/contact;
localhost:3000/api.... None works...
FYI
the server is set up with the following middleware and is working ok:
app.use('/api',contactRoute)
the controller is imported and coded as following:
router.post('/contact', (req, res)=>{
const data = req.body;
The React part is not posting correctly with axios and is coded as following:
onSubmit: async (values) => {
//values.preventDefault();
try {
const data = (JSON.stringify(values, null, 2))
setLoader(true);
console.log(data)
await axios.post('/contact', data);
The method post in react is never completed, when I check the console.log of data, is correctly structured as JSON...status 404
use the post parameter in your axois request {port: 5000} then It will use your actual backend port.
By default, axios uses the base path from the URL. So, here when an API request is made.
await axios.post('/contact', data);
It is actually making the post request on localhost:3000 rather than your backend server at localhost:5000. Also, "api" should also be prepended.
One simple way is to use absolute URL which should work.
await axios.post('http://localhost:5000/api/contact', data);

Making an http request using NodeJS and access the returned cookies

I am querying a remote API using NodeJS. I am currently using Axios to make the request, but I am willing to use another package if required.
Using NodeJS, I make a request to a remote API.
Axios.post("http://remote.api/getCookie")
.then(value => {
console.log(value);
});
The API returns a number of cookies (this can be seen in the spec, and when I test it in a browser). How can I access these cookies from the value returned by Axios.
Just get them from the Set-Cookie header:
Axios.post("http://<url>").then(response => {
const cookies = response.headers["set-cookie"];
// do whatever you want
}
You can then parse the header by yourself or use a library like cookie or set-cookie-parser

How can I redirect a page from an external Node/Express server

I have a React/Node/Express web app up and running with two separate servers. React is running on localhost:8080 and proxying API requests to my node server running on localhost:3000. This will be my setup for production, so if possible, I would like to leave this structure intact.
The problem I'm running into is part of my API needs to redirect the user to a page to grab a token from the Spotify API, and then redirect back to my correct page upon successful authentication.
The API call proxy is being done like this:
const axios = require('axios');
const axiosInstance = axios.create({
baseURL: process.env.NODE === 'production' ? '' : 'http://localhost:3000'
});
module.exports = axiosInstance;
Up to this point, this works great, as I can keep my React and Node server completely separate.
As I mentioned above, I need to redirect my React front-end through an API call on my back-end, to a different page (Spotify authentication) to authenticate users, which then Spotify redirects back to my site after a user allows or disallows access to their Spotify accounts.
On my front-end - localhost:8080, the user clicks a button which calls this function.
authenticate = () => {
axios.get('/login')
.then(data => console.log(data));
}
Which calls this endpoint on localhost:3000.
router.get('/', (req, res) => {
let scopes = 'user-read-private user-read-email';
let client = process.env.SPOTIFY_CLIENT;
let redirect = 'http://localhost:3000/login/redirect';
res.redirect(`https://accounts.spotify.com/authorize?response_type=code'
&client_id=${client}${scopes ? `&scope=${encodeURIComponent(scopes)}` : ''}
&redirect_uri=${encodeURIComponent(redirect)}&state=${state}`);
});
When I click the login button on my front-end, I get this response, which I believe to be from Spotify as I can successfully make cross-origin requests to other endpoints in my API.
Failed to load... No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
However, when I manually navigate to localhost:3000/login, the redirect works and I'm sent to the Spotify authentication page.
In addition, I tested trying to redirect my front-end to any url, and it doesn't work.
So my question is, how can I redirect my front-end through an API call from a server that doesn't also serve my static front-end content?
The reason this isn't working is because your axios.get('/login') is an AJAX request to your server which your server is then telling the AJAX request to be redirected to Spotify, but Spotify doesn't have your front-end server registered so you get the CORS error, since your request was initiated while on the front-end server URL.
Your AJAX request is following that redirect that was given, not trying to load your browser on http://localhost:3000, which would then redirect it to the Spotify authorization page.
Now, rather than doing:
authenticate = () => {
axios.get('/login')
.then(data => console.log(data));
}
You could do:
authenticate = () => {
window.location.href = "http://localhost:3000"
}
This would direct your front-end application to visit the URL of your API server and follow the redirect immediately to Spotify and then you could authorize and be redirected back to your API server, which could then redirect back to your front-end application.
Truthfully, this is a bit overkill, since presumably your React application and node application look like they would be running on the same domain outside of development, given the relative URL's you're using. If you're using create-react-app, you should follow their instructions on configuring your proxy via this or manually via this.
tl;dr you need to tinker with how your proxy is configured or change from doing an AJAX request there to actually going directly to /login (not doing an AJAX request).

Resources