I can't get header from backend in vuejs - spring-boot

I have a a spring boot backend that validates user login credentials. After validating the user it sends a login token in its response header. This part definitly works because I have seen it work in postman:
Now I am trying to get the token into my vuejs front end by doing the following:
import axios from 'axios'
const databaseUrl = 'http://localhost:9090/api'
const datbaseUrlBase = 'http://localhost:9090'
async function getSubjects(){
const result = await axios.get(`${databaseUrl}/subject`)
return result.data
}
async function updateSubject(subject){
let body = {
"name": subject.name,
"first_name": subject.first_name,
"date_of_birth": subject.date_of_birth
}
let result = await axios.put(`${databaseUrl}/subject/${subject.subjectid}`, body)
return result.data
}
async function getSubject(id){
let result = await axios.get(`${databaseUrl}/subject/${id}`)
return result.data
}
async function getSimulationsForSubject(id){
let result = await axios.get(`${databaseUrl}/subject/${id}/simulation`)
return result.data
}
async function deleteSubject(id){
await axios.delete(`${databaseUrl}/subject/${id}`)
}
async function makeSubject(subject){
await axios.post(`${databaseUrl}/subject`, subject)
}
async function updateDiagnose(diagnose, id){
await axios.put(`${databaseUrl}/subject/${id}/diagnose/${diagnose.diagnoseid}`, diagnose)
}
async function addSymptomToDiagnose(symptom, diagnoseid, subjectid){
await axios.post(`${databaseUrl}/subject/${subjectid}/diagnose/${diagnoseid}/symptom`, symptom)
}
async function updateSymptom(symptom_id, symptom, subjectid, diagnoseid){
await axios.put(`${databaseUrl}/subject/${subjectid}/diagnose/${diagnoseid}/symptom/${symptom_id}`, symptom)
}
async function getDiagnoseForSubject(diagnoseid, subjectid){
let result = await axios.get(`${databaseUrl}/subject/${subjectid}/diagnose/${diagnoseid}`)
return result.data
}
async function deleteSymptomForDiagnose(subjectid, diagnoseid, symptomid){
await axios.delete(`${databaseUrl}/subject/${subjectid}/diagnose/${diagnoseid}/symptom/${symptomid}`)
}
async function getStatisticsForSimulation(subjectid, simulationid){
let result = await axios.get(`${databaseUrl}/subject/${subjectid}/simulation/${simulationid}/statistics`)
return result.data
}
async function login(login){
let result = await axios.post(`${datbaseUrlBase}/login`, login)
return result.headers
}
export default{
getSubjects,
updateSubject,
getSubject,
getSimulationsForSubject,
deleteSubject,
makeSubject,
updateDiagnose,
addSymptomToDiagnose,
getDiagnoseForSubject,
deleteSymptomForDiagnose,
updateSymptom,
getStatisticsForSimulation,
login
}
Notice the login function above. Whenever I run this code the console.log gives undefined in the browser.
And the console.log(result.headers) gives this:
Is there anyway of accessing this token in my vuejs frontend?

If the server is cross-origin then browser CORS dictates that only a handful of default headers are accessible in a response.
You need to either have a matching origin, or enable the Access-Control-Expose-Headers header by setting it in your response like this:
Access-Control-Expose-Headers: token
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers

Related

Next.js 13 - new fetch approach makes two HTTP requests instead of one

I'm figuring out how data fetching works in Next.js 13 and I noticed that this code, when revalidating a fetching current data, makes two HTTP requests to the server instead of one. The requests go right after each other.
async function getData() {
const url = `${process.env.API_URL}/public/monitoring/websocket/`
const res = await fetch(url, {next: {revalidate: 10}})
if (!res.ok) {
throw new Error('Failed to fetch data')
}
return res.text()
}
export default async function Home() {
const data = await getData()
return (<div>{data}</div>)
}
Q: Is there any reason why there are two HTTP requests to the server?

How to pass RESTDataSource response headers to the ApolloServer response header (express)

I have ApolloServer running where the frontend makes a query request and the ApolloService fetches the request and then performs a request with RESTDataSource to a third-party service, I receive a response with a header.
Currently, ApolloServer only parses the body through the resolver and sends it back to the client
I wanted to pass also the header received to the client
I don't know how to do that at the RESTDataSource level since I don't have access to the Apollo response
I hope this was clear enough to explain the problem
export abstract class myClass extends RESTDataSource {
getSomething() {
const endpoint = this.endpointPath;
return this.get(endpoint);
}
async didReceiveResponse<T>(response, request): Promise<T | null> {
// these are the response headers desired to have them sent back to the client
console.log(response.headers);
if (response.ok) {
return this.parseBody(response) as any as Promise<T>;
} else {
throw await this.errorFromResponse(response);
}
}
}
In the appolloService initialization i have
const apolloServer = new ApolloServer({
context: async ({ res, req }) => {
// these headers are not the same as received from the getSomething() response above
console.log(res.getHeaders)
}
)}
I solved the issue by passing the res to the context and accessing the response in the didReceiveResponse, then adding the headers needed.
adding a response to context
const apolloServer = new ApolloServer({
context: async ({ res, req }) => {
return {
res: res,
};}
using the response to append the headers to it
async didReceiveResponse<T>(response, request): Promise<T | null> {
// use this.authHeader value in the class anywhere
this.context.res.setHeader(
"x-is-request-cached",
response.headers.get("x-is-request-cached") ?? false
);
this.context.res.setHeader(
"x-request-cached-time",
response.headers.get("x-request-cached-time")
);
if (response.ok) {
return (await this.parseBody(response)) as any as Promise<T>;
} else {
throw await this.errorFromResponse(response);
}}
by doing this you will achieve the desired outcome of passing the headers to the graphQl client

Nextjs api resolving before form.parse completes so i cant send response back

I am trying to send an image to Next.js api and then use that image to upload to db.
I am using :
const body = new FormData();
body.append("file", prewiedPP);
const response = await fetch("/api/send-pp-to-server", {
method: "POST",
body ,
headers: {
iext: iExt,
name: cCtx.userDetail ,
},
});
Then in the api :
async function handler(req, res) {
if (req.method === "POST") {
console.log("In");
const form = new formidable.IncomingForm();
form.parse(req,
async (err, fields, files) =>
{
// console.log(req.headers.iext);
// console.log(req.headers.name);
const fdata = fs.readFileSync(files.file.filepath);
await delUserPP(req.headers.name , req.headers.iext);
await setUserPP(
fdata ,
req.headers.name ,
req.headers.iext ,
files.file.mimetype
);
fs.unlinkSync(files.file.filepath);
return;
});
console.log("out");
}
}
export default handler;
The callback function in the from.parse happens after the handler already resolved.
Is there anyway to make the api call only resolve after the setUserPP function is done?
I want to send a response back to the client but the api script finishes to "fast" and before the callback in form.parse runs.
Thanks

Logging in and calling normal API Routes does not work with websockets

I have an issue with the authentication process of a websocket route.
I'm using PassportJS with 'local' strategy.
Logging in and calling normal API Routes are perfectly working with #AuthenticatedGuard,
but not on websockets
On the Websocket Route, it is throwing following error:
ERROR [WsExceptionsHandler] request.isAuthenticated is not a function
TypeError: request.isAuthenticated is not a function
This is my setup:
Example normal working API Route
test.controller.ts
#UseGuards(AuthenticatedGuard)
#Get(':id')
async findOne(
#Param('id') id: string,
#Req() req: any,
#Res() res: Response,
) {
return res.json(
await this.testService.findOne(+id),
);
}
Websocket Route
messages.gateway.ts
#UseGuards(AuthenticatedGuard)
#SubscribeMessage('findAllMessages')
async findAll(
#ConnectedSocket() client: Socket,
#MessageBody() findAllMessages: findAllMessages,
#Req() req: any,
) {
console.log(req);
//return this.messagesService.findAll(chatroomid);
const user = await this.messagesService.checkCurrentSessionString(
req.handshake.headers.cookie,
);
if (req.user.userid != undefined) {
return await this.messagesService.findAll(findAllMessages, user.userid);
} else client.disconnect(true);
throw new UnauthorizedException({
statusCode: 401,
message: 'Bitte logge dich erst ein',
});
}
authenticated.guard.ts
#Injectable()
export class AuthenticatedGuard implements CanActivate {
async canActivate(context: ExecutionContext) {
const request = context.switchToHttp().getRequest();
return request.isAuthenticated();
}
}
Seems like the session is not valid for the websocket routes?

AWS.ApiGatewayManagementApi() postToConnection no initial response detected on client

I have a lambda function that returns a message to the client.
function replyToMessage (messageText,connectionId) {
const data = {message:messageText}
const params = {
ConnectionId : connectionId,
Data: Buffer.from(JSON.stringify(data))
}
return api.postToConnection(params).promise()
.then(data => {})
.catch(error => {console.log("error",error)})
}
This code is called once when the connection is made and I get a response to my client. When I call the function again with a different endpoint, it doesn't send a response to my client. However, when I call it a third time, I get the response to my client from the second call. Here's my switch when the Lambda function is called.
switch(route) {
case "$connect":
break
case "$disconnect":
break
case "connectTo":
await connectToService(JSON.parse(event.body).eventId,connectionId)
await replyToMessage("Connected eventId to connId",connectionId)
break
case "disconnectFrom":
await disConnectToService(JSON.parse(event.body).eventId,connectionId)
break
case "project":
responseItems = await getBroadcastIds (JSON.parse(event.body).eventId,JSON.parse(event.body).sourceId,connectionId)
console.log(responseItems)
responseItems.Items.forEach(async function(item) {
await replyToMessage(JSON.parse(event.body).sourceId,item.connectionId)
})
responseItems = []
break
default :
console.log("Unknown route", route)
The issue appears to be the async forEach loop. Switching to the following resolves the issue.
for (const item of responseItems.Items) {
console.log("Sending to:",item.connectionId);
await replyToMessage(JSON.parse(event.body).sourceId,item.connectionId)
}
See this post for the answer that led to this resolution. Using async/await with a forEach loop

Resources