Nextjs - Autodesk Forge upload to S3 bucket - node.js

I'm trying to upload a file to an s3 bucket as per this guide. https://forge.autodesk.com/en/docs/model-derivative/v2/tutorials/translate-to-obj/about-this-tutorial/ and I'm stuck on step 4 - finalize upload. I'm getting failed with a status code of 400 when calling await finalizeUpload() in the handler.put method.
Here is the api route I am using
const upload = multer({
storage: multer.diskStorage({
destination: './public/uploads',
filename: (req, file, cb) => cb(null, file.originalname),
}),
})
handler.use(upload.single('model'))
handler.put(async (req, res) => {
const { _id: projectId } = req.query
const token = await getInternalToken()
const { access_token } = token
const file = req.file
const objectKey = file.originalname
try {
const projectsCollection = await getProject(projectId)
const bucketKey = projectsCollection.project.bucket.bucketKey
const signeds3upload = await obtainSignedUrl(bucketKey, objectKey, access_token)
const { uploadKey, urls } = signeds3upload
await uploadFile(urls, file.path)
await finalizeUpload(bucketKey, objectKey, uploadKey, access_token)
res.status(201).json({ bucketKey, objectKey, uploadKey })
} catch (error) {
console.log(error)
}
})
Here are the functions for steps 2 - 4
const obtainSignedUrl = async (bucketKey, objectKey, token) => {
const payload = {
ossbucketKey: bucketKey,
ossSourceFileObjectKey: objectKey,
access: 'full',
policyKey: 'transient',
}
const config = {
method: 'get',
url: `https://developer.api.autodesk.com/oss/v2/buckets/${bucketKey}/objects/${objectKey}/signeds3upload?minutesExpiration=30`,
headers: {
ContentType: 'application/json',
Authorization: `Bearer ${token}`,
},
}
try {
let res = await axios(config, payload)
return res.data
} catch (error) {
if (error.response) {
console.log('response Error obtainSignedUrl')
} else if (error.request) {
console.log('Request Error')
} else if (error.message) {
console.log('Message Error')
}
}
}
async function uploadFile(signed_upload_url, path_to_file) {
console.log(path_to_file)
const config = {
method: 'put',
url: signed_upload_url,
headers: {
ContentType: 'application/octet-stream',
},
}
try {
let res = await axios(config, path_to_file)
return res.data
} catch (error) {
if (error.response) {
console.log('response Error Upload File', error.message)
} else if (error.request) {
console.log('Request Error')
} else if (error.message) {
console.log('Message Error')
}
}
}
const finalizeUpload = async (bucketKey, objectKey, uploadKey, token) => {
const config = {
method: 'post',
url: `https://developer.api.autodesk.com/oss/v2/buckets/${bucketKey}/objects/${objectKey}/signeds3upload`,
headers: {
ContentType: 'application/json',
Authorization: `Bearer ${token}`,
},
}
try {
let res = await axios(config, uploadKey)
return res.data
} catch (error) {
if (error.response) {
console.log('response Error Finalize upload', error.message)
} else if (error.request) {
console.log('Request Error')
} else if (error.message) {
console.log('Message Error')
}
}
}

Here same error. Solved with
let res = await axios(config, JSON.stringify({uploadKey}))

Related

how to pass jwt token into the header

I make web application using react js, node, express
when I login the error message appear says "No token attached"
now I need to put a jwt token into header how can I do that
this is my code:
import { webToken } from "../crypto/web_token.js";
import { responses } from "../classes/responses.js";
export const verifyRequest = (req, res, nex) => {
try {
if (!req.headers.authorization) {
throw Error("no token attached");
}
const token = req.headers.authorization.split(" ")[1];
const payload = webToken.verify(token);
req.user = payload;
nex();
} catch (error) {
res.json(new responses.Error(error.message));
}
};
another code: web_token.js
import jsonwebtoken from "jsonwebtoken";
import { errors } from "../classes/errors.js";
const secret = "#########";
export const webToken = Object.freeze({
generate: (data, expiry = "1hr") => {
try {
return jsonwebtoken.sign(data, secret, { expiresIn: expiry });
} catch (error) {
throw new errors.Logic("Internal error from the bcrypt hashing", "jwt");
}
},
verify: (token) => {
try {
const data = jsonwebtoken.verify(token, secret);
return data;
} catch (error) {
throw new errors.Authentication(
error.message.replace("jwt", "Token"),
"jwt"
);
}
},
});
here is the template, take a look
var axios = require('axios');
var data = JSON.stringify({
"value1": "val1"
});
var config = {
method: 'post',
url: 'http://localhost:3000/GetText',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
data : data
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});

Send multiple files from express server to rest api

I am trying to send multiple files from react to express server and then to microservice. The problem is that my express server is getting crashed whenever I try to upload multiple files.
Here is my express.js side code:
router.post("/upload-files", upload.array("file[]"), async function (req, res) {
let check = new FormData();
// check = req.files;
const file = req.files;
// console.log("DATA------------------------>", file);
// check.append("file", file.buffer, file.originalname);
await axios.post(
constants.URL2 +":9095/upload-files", check,
{
headers: {
...check.getHeaders(),
},
})
.then((res) => {
return res;
})
.then((result) => {
res.send(result.data);
});
});
Here is my React.js side code:
update = () => {
if (this.isValidForm()) {
$(".loader").css({ display: "block" });
$(".overlay").css({ display: "block" });
// const obj = {
// fullName: this.state.fullName,
// };
var formData = new FormData();
const size = this.state.fileData;
for (let i = 0; i < size.length; i++) {
console.log(this.state.fileData[i]);
formData.append("file[]", this.state.fileData[i]);
}
// formData.append("files", this.state.fileData);
const updateRequest = {
method: "POST",
headers: {
// "Content-Type": "application/json",
Authorization:
},
// body: JSON.stringify(obj),
body: formData
};
fetch(URL.BASE_URL + "upload-file", updateRequest)
.then((res) => {
if (res.status == 401) {
this.props.GETLOGGEDINUSER(null);
this.props.history.push("/");
} else {
return res.json();
}
})
.then((res) => {
if (res.statusCode == 0) {
this.props.history.push({
pathname: "/newScreen",
state: { notification: "File uploaded Successfully" },
});
toast.success("File uploaded Successfully");
$(".loader").css({ display: "none" });
$(".overlay").css({ display: "none" });
} else {
toast.error(res.message);
$(".loader").css({ display: "none" });
$(".overlay").css({ display: "none" });
}
});
} else {
}
};
I tried many ways to solve this but none of them works.

Why is react not posting res.json() to console?

I have tried so many thing but my react app is not recieving jsonData variable or res as a return from the node app. The app is working and printing to console on the node side but I can't get it to print onto the react side.
const submitForm = async (event) => {
event.preventDefault(); // Prevent default submission
const data2 = document.getElementById("miles").value;
const data =
"passenger_vehicle-vehicle_type_" +
carType +
"-fuel_source_" +
vehicleType +
"-engine_size_na-vehicle_age_na-vehicle_weight_na";
axios
.post(`http://localhost:8000/api/vehicle/`, { data, data2 })
.then((res) => {
const returnText = res.json();
console.log(returnText);
return res.json();
})
.then((jsonData) => {
console.log(jsonData);
return;
})
.catch((error) => {
console.log("got errr while posting data", error);
});
};
I edited out the api and api key.
var fetch = require('node-fetch');
exports.vehicle = (req, res) =>{
let status;
const { data, data2 } = res.body;
const values = {
"emission_factor": data,
"parameters": {
"distance": parseInt(data2),
"distance_unit": "mi",
},
};
fetch('https://AAAAAAAAAAAAAAAA', {
method: 'POST',
headers: {
'Authorization': 'Bearer MYAPIKEY',
'Content-Type': 'application/json'
},
body: JSON.stringify(values)
})
.then((res) => {
status = res.status;
return res.json()
})
.then((jsonData) => {
console.log(jsonData);
console.log(status);
return jsonData
})
.catch((err) => {
// handle error
console.error(err);
});
res.send(req.body);
}
Working code thanks for the help:
const submitForm = async (event) => {
event.preventDefault(); // Prevent default submission
const data2 = document.getElementById("miles").value;
const data =
"passenger_vehicle-vehicle_type_" +
carType +
"-fuel_source_" +
vehicleType +
"-engine_size_na-vehicle_age_na-vehicle_weight_na";
axios
.post(`http://localhost:8000/api/vehicle/`, { data, data2 })
.then((res) => {
console.log(res.data);
return;
})
.catch((error) => {
console.log("got err while posting data", error);
});
};
Node solution in comments.
The functions inside your then() statements need to return data e.g. then((res) => {return res.json()})
You have two problems here...
Client-side, you seem to be mixing up an Axios response with a fetch() Response. You want res.data, not res.json(). Since you've tagged this with reactjs, here is where you would set the data to a state value, eg
axios.post(...).then(res => {
setSomeState(res.data)
})
Server-side, you aren't waiting for your fetch request to complete. I'd recommend using an async function
exports.vehicle = async (req, res) => {
try {
const { data, data2 } = req.body
const values = {
"emission_factor": data,
"parameters": {
"distance": parseInt(data2),
"distance_unit": "mi",
},
}
// don't mix up the Express "res" with the fetch "response"
const response = await fetch('https://AAAAAAAAAAAAAAAA', {
method: 'POST',
headers: {
'Authorization': 'Bearer MYAPIKEY',
'Content-Type': 'application/json'
},
body: JSON.stringify(values)
})
if (!response.ok) {
throw new Error(`${response.status}: ${await response.text()}`)
}
res.json(await response.json()) // respond with the data
} catch (err) {
console.error(err)
res.status(500).send(err)
}
}

How to receive re-requested data when data requested by mounted() is re-requested by aixos interceptor

the code below is the first request for get list data
mounted() {
this.getList()
},
methods: {
handleClick(row) {
console.log(row.id)
console.log(row.url)
this.$router.push({ name: 'Main', query: { id: row.id } })
},
getList() {
axios
.get('/api/v1/requests/all', {
params: {
userId: this.$store.state.userInfo.id,
},
})
.then(response => {
let moment = require('moment')
for (var item of response.data.data) {
item.createdAt = moment(item.createdAt).format(
'YYYY-MM-DD HH:mm:ss',
)
}
this.items = response.data.data
})
.catch(error => {
console.log(error)
})
}
my interceptor
axios.interceptors.response.use(
function (response) {
return response
},
async function (error) {
const originalRequest = error.config
if (error.response.status === 401 && !originalRequest._retry) {
error.response.config._retry = true
sessionStorage.removeItem('access-token')
let headers = {
grant_type: 'refresh_token',
Authorization: sessionStorage.getItem('refresh-token'),
}
axios
.post('/api/v1/users/refresh_token', {}, { headers: headers })
.then(response => {
let token = response.data.data
sessionStorage.setItem('access-token', token)
originalRequest.headers['Authorization'] = token
originalRequest.headers['grant_type'] = 'grant_type'
return axios.request(originalRequest)
})
.catch(error => {
console.log(error)
alert('blablabla.')
})
}
return Promise.reject(error)
},
)
the flow is i understand
1.token expired
2.move to list page
3.mounted hook is request data
4.getList -> axios get('~~request/all')
5.interceptor->axios post('~~~refresh_token')
6.re request with new token(request/all)
7.re request is 200, but not update list page
i'd really appreciate your help :)
Seems like you need to return the second request (await for result and return). Right now the result of second request seems to be ignored
axios.interceptors.response.use(
function (response) {
return response;
},
async function (error) {
const originalRequest = error.config;
if (error.response.status === 401 && !originalRequest._retry) {
error.response.config._retry = true;
sessionStorage.removeItem("access-token");
let headers = {
grant_type: "refresh_token",
Authorization: sessionStorage.getItem("refresh-token"),
};
const [secondError, res] = await axios // await here
.post("/api/v1/users/refresh_token", {}, { headers: headers })
.then(async (response) => {
let token = response.data.data;
sessionStorage.setItem("access-token", token);
originalRequest.headers["Authorization"] = token;
originalRequest.headers["grant_type"] = "grant_type";
return [null, await axios.request(originalRequest)];
})
.catch((err) => {
console.log(err);
alert("blablabla.");
return [err, null];
});
// Handle here
if(secondError) {
return Promise.reject(secondError);
}
return Promise.resolve(res)
}
return Promise.reject(error);
}
);
The above solution worked for me perfectly. here's the modified code that I used for my requirement.
export default function axiosInterceptor() {
//Add a response interceptor
axios.interceptors.response.use(
(res) => {
// Add configurations here
return res;
},
async function (error) {
const originalRequest = error.config;
let secondError, res
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
[secondError, res] = await axios({
method: "POST",
url: `${baseURL}/account/token/refreshtoken`,
withCredentials: true,
headers: { "Content-Type": "application/json" },
})
.then(async (response) => {
//handle success
return [null, await axios.request(originalRequest)];
}).catch(function (error) {
console.error(error)
});
}
if (secondError) {
return Promise.reject(secondError);
}
return Promise.resolve(res)
}
);
}

Set Mock Response for JWT Module NodeJS

I am writing Test case using JEST in NodeJs inside AzureFunction.
Im trying to mock JWT module outcome inside my index.test.js , however its not working and getting timedout. I wonder is it the return datatype mismatch? How to set response similar to cb of jwt verify method?
Here is my sample code. Please suggest!
Index.js
const JWT = require('./jwtDecoder')
module.exports = function(context, req) {
try {
JWT(req.body, process.env.jwtsecret, function(err, decoded) {
if (err) {
context.log("Invalid JWT::" + req.body);
context.res = {
headers: {
'Content-Type': 'application/json'
},
status: 400,
body: {
"error": err
}
};
context.done();
} else {
context.log("JWT Authentication Successful:");
context.res = {
headers: {
'Content-Type': 'application/json'
},
status: 200,
body: {
"message": "success"
}
};
context.done();
}
});
} catch (err) {
context.log("Exception in main function, PushHttpFunction:" + err);
context.res = {
headers: {
'Content-Type': 'application/json'
},
status: 500,
body: {
"error": err
}
};
context.done();
}
}
jwtDecoder.js
'use strict';
module.exports = (body, secret, cb) => {
console.log('inside jwtDecoder');
if (!body) {
return cb(new Error('invalid jwt data'));
}
require('jsonwebtoken').verify(body.toString('utf8'), secret, { algorithm: 'HS256' }, cb);
};
index.test.js
let indexTest = require('../index')
const { runStubFunctionFromBindings } = require('stub-azure-function-context')
let JWT = require('../jwtDecoder')
jest.mock("../jwtDecoder.js")
/* verify.mockImplementation(() => () => ({
err: new Error('invalid jwt data'),
decoded: 'ok'
})); */
JWT.mockImplementation(() => new Promise(function(resolve, reject) {
resolve('ok');
}));
beforeAll(() => {
process.env = Object.assign(process.env, {
NODE_ENV: "test",
});
});
describe('Simple Testing', () => {
test('return 200 by mocking simpleFunc response" ', async() => {
let request = {
body: "dummy.jwt.zT5p"
};
const context = await runStubFunctionFromBindings(indexTest, [
{ type: 'httpTrigger', name: 'req', direction: 'in', data: request },
{ type: 'http', name: 'res', direction: 'out' },
], new Date());
console.log('mockedResp::', context);
expect(context.res.status).toEqual(200);
}, 30000);
});
Basically you are mocking wrong, you can keep only this line:
jest.mock('./jwtDecoder.js', () => (res, req, cb) => cb(null, 'ok'))
as you need to mock callback
and remove all this part:
jest.mock("../jwtDecoder.js")
JWT.mockImplementation(() => new Promise(function(resolve, reject) {
resolve('ok');
}));

Resources