Cannot send form data as 'Multipart/formdata' - node.js

Cannot send form data as 'Multipart/formdata' Content type in react-native expo app.
when we send formData object in post request in react -native app, we cant get req.body of req.files from node backend
export const saveUserAddVisitor = async data => {
try {
const apiUrl = configConstants.apiUrlWithPort;
const addVisitorData = await axios.post(
`${apiUrl}/api/v1/mobile/apartment/member`,
data,
{
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
},
},
);
return addVisitorData;
} catch (err) {
return err;
}
};

You can try something like this which works without Axios:
export const saveUserAddVisitor = async data => {
var data = new FormData()
data.append('foo', {
...
})
try {
const apiUrl = configConstants.apiUrlWithPort;
const addVisitorData = await fetch(`${apiUrl}/api/v1/mobile/apartment/member`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data'
},
body: data
})
return addVisitorData;
} catch {
return err;
}
}
After I gave you an example of working code for the client, but the problem may be from the server ;)

Your code with axios look like fine, just be sure to send FormData type, like RĂ©mi said here https://stackoverflow.com/a/72454168/16205278
You can construct your FormData before this function and use it directly in your current code with your axios function.
Service :
import axios from "axios";
import configConstants from "./config.js";
/**
* Current function to save User Add Visitor
* #param {*} data
*/
export const saveUserAddVisitor = async (data) => {
try {
const apiUrl = configConstants.apiUrlWithPort;
const addVisitorData = await axios.post(
`${apiUrl}/api/v1/mobile/apartment/member`,
data,
{
headers: {
Accept: 'application/json',
"Content-Type": "multipart/form-data"
}
}
);
return addVisitorData;
} catch (err) {
return err;
}
};
Use :
import {saveUserAddVisitor} from "./index"
const form = new FormData();
form.append("visitor", { firstName: "Jack", lastName: "Doe" });
saveUserAddVisitor(form);
API Express :
Apparently, express can't resolve multipart-form data unless some help, according following ressource : https://codex.so/handling-any-post-data-in-express
You have to use multer middleware :
const multer = require('multer');
app.post('/', multer().none(), function (req, res, next) {
req.body;
//... some code
});

Related

how to set headers in axios patch request in react js

Can someone tell me what mistake I am making or tell me how to set the header in axios patch request. when I am running the API through postman, everything is working fine but when I connect it with the front end, an error comes up saying that the JWT is not provided on the backend
here is the frond end code :
import React, { useEffect } from 'react';
import { useParams } from 'react-router';
import axios from 'axios';
const Loader = () => {
const parmas = useParams();
const { id } = parmas;
console.log(id);
useEffect(() => {
const fetchBags = async () => {
try {
const res = await axios.patch('http://localhost:4001/public/verify', {
headers: {
'Content-Type': 'application/json',
Token: id,
},
});
console.log(res);
console.log('CBM', { res });
} catch (error) {
console.log(error);
}
};
fetchBags();
}, []);
return <div>this is loader</div>;
};
export default Loader;
below is my backend code:
export const verifyUser = async (data) => {
const token1 = data.header("Token");
try {
const verified = jwt.verify(token1, getTokenSecret());
console.log(verified)
await userModel.verifyUser(verified);
return {
message: "success",
};
} catch (error) {
console.log(`Auth Service > verifyUser > ${error.toString()}`);
throw error;
}
};
this error is comming:
Error
From docs
axios.patch(url[, data[, config]])
As you can see you pass config in 3rd argument not 2nd.
const res = await axios.patch(
'http://localhost:4001/public/verify',
{}, // data (2nd argument)
{
headers: {
'Content-Type': 'application/json',
Token: id,
},
} // config (3rd argument)
)

can't receive file with multer (node.js-nuxt3)

I use nuxt3/node.js with multer ,
i can't store or receive file in my server and i can't see req.file in root, its empty all time.
server Code:
const upload = multer({ dest: './uploads/' })
router.post('/sendNewQuestionCSV', upload.single('csv'),adminControler.sendNewQuestionCSV.bind(adminControler))
and my FrontEnd Code with nuxt3:
async function fileSelected(e) {
let formData = new FormData();
formData.append("csv", e.target.files[0]);
const res = await $postFetch("/admin/sendNewQuestionCSV", formData, {
"Content-Type": "multipart/form-data",
});
}
note:$postFetch is an method i made my self use fetch and third argument is "headers". its a nuxt3 Plugin
this Plugin code:
export default defineNuxtPlugin(async () => {
return {
provide: {
postFetch: async (url, body,headers={}) => {
let token = useCookie('token');
return await $fetch(url, {
method: 'post',
body: { token: token.value, ...body },
baseURL: useRuntimeConfig().API_BASE,
...headers
}).catch((error) => error.data)
}
}
}
})
try using .append to add the token:
postFetch: async (url, body,headers={}) => {
let token = useCookie('token');
body.append('token', token.value);
return await $fetch(url, {
method: 'post',
body: body,
baseURL: useRuntimeConfig().API_BASE
}).catch((error) => error.data)
}
EDIT
also try removing headers

Axios and Oauth1.0 - 'status: 400, Bad Request'

I'm new on Nodejs and all the modules related with Node. I've been trying to use axios for send a Oauth1.0 Autorization signature, but i'm getting: response: { status: 400, statusText: 'Bad Request', ...}
import { BASE_URL } from '../../../config/config.js';
import axios from 'axios';
import status from 'http-status';
import OAuth from 'oauth-1.0a';
import { createHmac } from 'crypto';
import dotenv from 'dotenv';
dotenv.config();
const CONSUMERKEY = process.env.consumer_key;
const CONSUMERSECRET = process.env.consumer_secret;
const TOKENKEY = process.env.access_token;
const TOKENSECRET = process.env.token_secret;
export const oauth = OAuth({
consumer: {
key: CONSUMERKEY,
secret: CONSUMERSECRET,
},
signature_method: 'HMAC-SHA1',
hash_function(base_string, key) {
return createHmac('sha1', key)
.update(base_string)
.digest('base64')
},
})
export const token = {
key: TOKENKEY,
secret: TOKENSECRET,
}
const doRequest = async (query) => {
const request_data = {
url: `${BASE_URL}`,
method: 'GET',
params: { q: `${query}` },
};
const authHeader = oauth.toHeader(oauth.authorize(request_data, token));
return await axios.get(request_data.url, request_data.params, { headers: authHeader });
};
const searchU = async (term) => {
return await doRequest(`${term}`);
};
export const userS = async (req, res, next) => {
try {
const { query } = req;
const { data } = await searchU(query.q);
const string = JSON.stringify(data);
const Rs = JSON.parse(string);
const response = {
code: 1,
message: 'sucess',
response: Rs
};
res.status(status.OK).send(response);
} catch (error) {
next(error);
if (error.response){
console.log("Response: ");
console.log(error.response);
} else if(error.request){
console.log("Request: ");
console.log(error.request)
} else if(error.message){
console.log("Message: ");
console.log(error.message)
}
}
};
I've been also trying the solution given On this post: but there's no way I can make this work, no idea what i could be doing wron...
When i try the following code (see below), using Request module (which is deprecated) works well, but I really need to do it with Axios...
const request_data = {
url: `${BASE_URL}`,
method: 'GET',
params: { q: `${query}` },
};
const authHeader = oauth.toHeader(oauth.authorize(request_data, token));
request(
{
url: request_data.url,
method: request_data.method,
form: request_data.params,
headers: authHeader,
},
function(error, response, body) {
console.log(JSON.parse(body));
}
)
Any thoughts on what I'm doing wrong on this?? Thank you very much!!
Refer to the following link for the Request Config for Axios. I believe you need to have the query params after the header in the axios.get()
Axios Request Config
Try, the following and see how it goes:-
return await axios.get(request_data.url, { headers: authHeader }, request_data.params);

How can I get Axios to send a request with FormData?

I'm unable to get the server that I'm calling to recognize the FormData that I'm providing when I use axios. It keeps telling me that I'm not providing the right FormData even though it works in Postman and Node native http (see below):
import { Router } from "express";
import axios from "axios";
import * as FormData from "form-data";
const router = Router();
const cookieHeader = {
Cookie: "XXX",
};
router.get("/", async (_req, res) => {
try {
const formData = new FormData();
formData.append("key1", JSON.stringify(["value1"]));
formData.append("key2", "value2");
formData.append("key3", "value3");
const response = await axios.post("https://xxx", formData, { headers: { "Content-Type": "multipart/form-data; boundary=--------------------------811161660471543283806813" } });
res.send(response.data);
} catch (error) {
console.log(error);
}
});
module.exports = router;
I am able to get it working in Postman and used that to export using Node's native http, which also works:
import { Router } from "express";
import { https } from "follow-redirects";
const router = Router();
router.get("/", () => {
const options = {
method: "POST",
hostname: "xxx",
path: "/xx/xxx",
headers: {
"Content-Type": "multipart/form-data; boundary=--------------------------811161660471543283806813",
Cookie: "xxx",
},
maxRedirects: 20,
};
const req = https.request(options, (res: any) => {
const chunks: any[] = [];
res.on("data", (chunk: any) => {
chunks.push(chunk);
});
res.on("end", () => {
const body = Buffer.concat(chunks);
console.log(body.toString());
});
res.on("error", (error: any) => {
console.error(error);
});
});
const postData = `------WebKitFormBoundary7MA4YWxkTrZu0gW\nContent-Disposition: form-data; name=\"key1\"\n\n[\"value1\"]\n------WebKitFormBoundary7MA4YWxkTrZu0gW\nContent-Disposition: form-data; name=\"key2\"\n\nvalue2\n------WebKitFormBoundary7MA4YWxkTrZu0gW\nContent-Disposition: form-data; name=\"key3\"\n\nvalue3\n------WebKitFormBoundary7MA4YWxkTrZu0gW--`;
req.setHeader("content-type", "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW");
req.write(postData);
req.end();
});
module.exports = router;
I figured it out after reading through https://github.com/axios/axios/issues/318. It wasn't until near the end that Googrosh posted that he used .getHeaders(). Lo and behold, I added that to my headers too and it worked.
So updating my code, here's what it looks like:
const response = await axios.post("https://xxx", formData, { headers: formData.getHeaders() });
onst formUrlEncoded = x =>
Object.keys(x).reduce((p, c) => p + `&${c}=${encodeURIComponent(x[c])}`, '')
var axios = require("axios");
axios({
url: 'https://login.xyz.com/oauth/v2/token',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: formUrlEncoded({
client_id: '***',
client_secret: '***',
grant_type: 'authorization_code',
})
})
.then(function(response) {
console.log(response.data)
})
.catch(function(error) {
console.log(error)
})

How to pass parameters in headers

I need to call an API from my Angular Node application.For that i have to pass username and password along with header request.How to pass parameters?
I tried below code
From Angular service,
checkUserApi(url: string): Observable<any> {
const headers = new HttpHeaders()
.set('Authorization', 'my-auth-token')
.set('Content-Type', 'application/json')
.set('userName','prismtest')
.set('password','12345678');
return this.http.post('/upload/checkUserApi/', { headers })
.map((response: Response) => {
console.log(response);
return response;
})
}
In Node,
router.post('/checkUserApi',function(req,res,next){
var proxyUrl = 'http://cors-anywhere.herokuapp.com/';
Request.post({
"headers": { "userName": "prismtest","password":"12345678" },
"url": proxyUrl+"https://example.com",
"body": {}
}, (error, response, body) => {
if(error) {
return console.log(error);
}
res.send(response);
});
});
You can pass the form parameters as the second attribute to post request:
checkUserApi(url: string): Observable<any> {
const headers = new HttpHeaders()
.set('Authorization', 'my-auth-token')
.set('Content-Type', 'application/json');
return this.http.post('/upload/checkUserApi/', {username: 'prismtest', password: '123'}, { headers })
.map((response: Response) => {
console.log(response);
return response;
})
}
You can do it by using interceptors which is Angular Service.
this should be helpfull :How to pass a param to HttpInterceptor?
Can you try below code following
/* SERVICE ANGULAR*/
import {Injectable} from '#angular/core';
import {HttpClient, HttpHeaders} from '#angular/common/http';
import {Observable,of} from 'rxjs';
import { map,catchError } from 'rxjs/operators';
import {User} from '../_models';
const httpOptions = {
headers:new HttpHeaders({'Content-Type':'application/json'})
};
const API_URL = "http://localhost/app/api";
#Injectable({
providedIn:'root',
})
export class UserService{
constructor(private http:HttpClient){}
/**
* POST LOGIN USER
*/
login(user: any) {
return this.http.post<any>(API_URL+"/login", user,httpOptions)
.pipe(map(user => {
return user;
}));
}
}
/*NODEJS*/
/* 1) install $ npm install body-parser --save*/
var bodyParser = require('body-parser');
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies */
/ POST http://localhost:8080/api/users
// parameters sent with
app.post('/api/login', function(req, res) {
var user_id = req.body.id;
var token = req.body.token;
var geo = req.body.geo;
res.send(user_id + ' ' + token + ' ' + geo);
});
Can you seen : Use ExpressJS to Get URL and POST Parameters
Login State Angular + Laravel
const headerOptions = {
headers : new HttpHeaders({
'Constent-Type' : 'application/json',
'Authorization : 'you token here'
})
}
http.post('you action', {body Params}, headerOptions, function(res){
console.log('your respose is ', res);
})

Resources