I am very frustrated and could not find the soloution:
I am creating a project using angularjs and nodejs.I get image data from angular side in node js and send this data to further api.I got error
{
"error": {
"detail": "Multipart form parse error - Invalid boundary in multipart: None"
}
}
here is my code in nodejs side:
var request = require('request');
console.log(req.files);
var data = {
website:'www.gamail.xom',
contact_number:'dsdsd',
services_offered:'dsadasd',
contact_name:'dasdas',
provider_category:'exchange',
email:'kk#gmail.com',
image:req.files
}
var api_url = global.common.base_url + 'vcard/1.0.0/visit_card/' + req.param('uuid') +'/';
request({
url: api_url,
method: 'PUT',
headers: {
'Content-Type': 'multipart/form-data',
'Authorization': 'Bearer '+req.cookies.apitoken
},
json: data
}, function(error, response, body) {
if(response.statusCode == 200 && !error){
res.end(JSON.stringify(body));
}else{
res.send(response.statusCode, { error: body });
}
});
}
In req.files i get
{ image:
[ { fieldName: 'image[0]',
originalFilename: 'icon_dd_chart_grey.png',
path: 'C:\\Users\\karakuma\\AppData\\Local\\Temp\\op74_gLSzPs-_49aT1GF0si
7.png',
headers: [Object],
size: 1474,
name: 'icon_dd_chart_grey.png',
type: 'image/png' } ] }
Try defining the content type as follows.
content_type='multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW'
I was facing the same issue and it worked for me in python.
I also faced this issue while trying to upload file. For me the issue was the FormData, which was coming as Object instead of FormData instance
So i converted my object to FormData using below code:
const getFormData = object => Object.keys(object).reduce((formData, key) => {
formData.append(key, object[key]);
return formData;
}, new FormData());
And the just executed my post request, in my case using Vue resource:
return Vue.http.post(url,
getFormData(formData),
{
headers: {
'Content-Type': 'multipart/form-data'
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
There is no need to mention the content type in header, fetch() will detect it's content type by itself.
let formData = new FormData()
formData.append("email", email);
formData.append("password", password);
formData.append("image", image);
const response = await fetch('http://localhost:8000/api/authentication/register/', {
method: 'POST',
headers: {'X-CSRFToken': csrftoken}, //django specific
body: formData,
});
I have been facing this problem in angular 11 connected to Django rest API, I was able to curl with something like this in order to upload a JSON with a form:
curl -X POST -S \
-H 'Accept: application/json' \
-u "user:password" \
-F "name=name" \
-F "label=mylabel" \
-F "otherfields=something" \
-F "photo=#./example.png;type=image/png" \
http://127.0.0.1:8000/api/v1/item/
But I was getting that exception using my header as httpOptions:
'content-type': 'multipart/form-data',
So I just commented out the content-type and it seems angular is so clever that he creates the header for you and will set the multipart together with the boundaries.
For more information on this:
What is the boundary in multipart/form-data?
A boundary is just the 'key' to separate the multiple "parts" of a multipart payload. Normally something like '&' is enough to separate the variables but you need something more unique to separate the payloads within the payload comment
You can use any value that not occurs in the data sent.
NOTE: Because boundary delimiters must not appear in the body parts being encapsulated, a user agent must exercise care to choose a unique boundary parameter value.
The simplest boundary delimiter line possible is something like "---", with a closing boundary delimiter line of "-----".
Related
I am trying to send the contents of a flashcard to a backend route http://127.0.0.1:5000/post onClick and it works when I send the data to webhook.site but when I change it to http://127.0.0.1:5000/post I get the error " question = data['question' TypeError: 'NoneType' object is not subscriptable ". Here is the code for the fetch request: async function postData() {
try {
let result = await fetch('http://127.0.0.1:5000/post', {
method: 'POST',
mode: 'no-cors',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
key: `${Date.now()}`,
question: flashcard.question,
answer: flashcard.answer,
options: flashcard.options
})
});
} catch(e) {
console.log(e)
}
}
and here is the code for the backend route in flask:
#app.route('/post', methods=['GET', 'POST'])
def post():
data = request.get_json()
question = data['question']
answer = data['answer']
options = data['options']
key = data['key']
return jsonify({'question' : question, 'answer' : answer, 'options' : options, 'key' : key})
if __name__ == "__main__":
app.run(debug=True)
I get that the error is stating that "data" has no value which I assume means it's not recieving the JSON objects that I'm posting. It's weird because it works perfectly when I use a webhook.site url. can anyone help? thanks for your time!
I am trying to send the contents of a flashcard to a backend route http://127.0.0.1:5000/post onClick and it works when I send the data to webhook.site but when I change it to http://127.0.0.1:5000/post I get the error " question = data['question' TypeError: 'NoneType' object is not subscriptable ". Here is the code for the fetch request:
async function postData() {
try {
let result = await fetch('http://127.0.0.1:5000/post', {
method: 'POST',
mode: 'no-cors',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
key: `${Date.now()}`,
question: flashcard.question,
answer: flashcard.answer,
options: flashcard.options
})
});
} catch(e) {
console.log(e)
}
}
and here is the code for the backend route in flask:
#app.route('/post', methods=['GET', 'POST'])
def post():
#save data to db
data = request.get_json()
question = data['question']
answer = data['answer']
options = data['options']
key = data['key']
return jsonify({'question' : question, 'answer' : answer, 'options' : options, 'key' : key})
if __name__ == "__main__":
app.run(debug=True)
I get that the error is stating that "data" has no value which I assume means it's not recieving the JSON objects that I'm posting. It's weird because it works perfectly when I use a webhook.site url. can anyone help? thanks for your time!
Seems like your content is not a valid json request. If that is the case then content will be equal to None(not subscriptable).
Try to debug how data looks in flask and based on that you will know if its valid json.
I want to generate token to do the CRUD operations in SharePoint Online list. I am able to generate the token in Postman. But I want that it automatically gets generated in my React app to do the CRUD operations. I copied the code snippet from the Postman and pasted in my React app, but it is throwing error. Here is the error :
UsingFetch.js:181 POST https://accounts.accesscontrol.windows.net/834fb7b4-624d-4de8-a977-2d46ad979bd9/tokens/OAuth/2 400 (Bad Request)
{"error":"invalid_request","error_description":"AADSTS900144: The request body must contain the following parameter: 'grant_type'.\r\nTrace ID: d2dcb2da-1aae-4af2-a3e3-aabc35ce4301\r\nCorrelation ID: c90dff14-b64d-4f47-a01c-dfe498ec2f40\r\nTimestamp: 2022-02-23 09:07:45Z","error_codes":[900144],"timestamp":"2022-02-23 09:07:45Z","trace_id":"d2dcb2da-1aae-4af2-a3e3-aabc35ce4301","correlation_id":"c90dff14-b64d-4f47-a01c-dfe498ec2f40","error_uri":"https://accounts.accesscontrol.windows.net/error?code=900144"}
Here is the screenshot of the
Here is the code snippet that I copied from Postman :
const generateToken = async () => {
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
myHeaders.append(
"Cookie",
"esctx=AQABAAAAAAD--DLA3VO7QrddgJg7WevrQx7IG43UK7gipYHXtqZImLB1jfBLK4PTkZlgLq3BvpTizt3xt8EZQrpUJGa0hTnSdpRf-AenJvnGNABiv2cWYWSyJj9QNm-vWalRGHuDZ6Km_DaX_5CQHUa4H8U-osEGCM48buOyj0G819e1NoxuvoOD6fZvMI5nnDWZyjNa1mogAA; fpc=An1vbDtRI8BAiCLlUBBGpFXf9_srAQAAACDgp9kOAAAA; stsservicecookie=estsfd; x-ms-gateway-slice=estsfd"
);
var formdata = new FormData();
formdata.append("grant_type", "client_credentials");
formdata.append(
"client_id",
"myclientid"
);
formdata.append(
"client_secret",
"mysecretcode"
);
formdata.append(
"resource",
"00000003-0000-0ff1-ce00-000000000000/cooponline.sharepoint.com#834fb7b4-624d-4de8-a977-2d46ad979bd9"
);
var requestOptions = {
method: "POST",
headers: myHeaders,
body: formdata,
redirect: "follow",
};
await fetch(
"https://accounts.accesscontrol.windows.net/834fb7b4-624d-4de8-a977-2d46ad979bd9/tokens/OAuth/2",
requestOptions
)
.then((response) => response.text())
.then((result) => console.log(result))
.catch((error) => console.log("error", error));
};
Can anyone please provide me with a solution?
Thank you.
This error says what's wrong: The request body must contain the following parameter: 'grant_type'.
To fix this, just add it as a parameter (formData in this case). According to the SharePoint docs, this value must be set to client_credentials.
formdata.append(
"grant_type",
"client_credentials"
);
EDIT:
Apparently, the request body has an unusual format. You're trying to send it as application/json, but MS expects application/x-www-form-urlencoded like this:
POST /{tenant}/oauth2/v2.0/token HTTP/1.1 //Line breaks for clarity
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id=535fb089-9ff3-47b6-9bfb-4f1264799865
&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&client_secret=sampleCredentia1s
&grant_type=client_credentials
So, instead of passing formData object as the request body, you should wrap it into a string like this:
const body = Object.keys(formData)
.map(key => `${key}=${formData[key]}`)
.join('&');
and pass that as the body.
I am trying to implement apollo-datasource-rest to handle image uploading by URL via Imgur's API (documentation here: https://apidocs.imgur.com/)
I initially was getting a 400 error which read We don't support that file type!, and determined that it was due to apollo-datasource-rest automatically setting the Content-Type to application/json. After fixing that issue using the form-data npm package, here's what my code looks like:
class ImgurAPI extends RESTDataSource {
constructor() {
super();
this.baseURL = "https://api.imgur.com/3/";
}
willSendRequest(request) {
request.headers.set("Content-Type", "multipart/form-data");
request.headers.set(
"Authorization",
`Client-ID ${process.env.IMGUR_CLIENT_ID}`
);
console.log(request);
}
async uploadImageFromUrl(url) {
const formData = new FormData();
formData.append("image", url);
return this.post("upload", formData);
}
}
I now no longer get the We don't support that file type! error, but I still get a 400 response with a status text of just Bad Request. The console.log() from the previous code snippet prints this:
{
method: 'POST',
path: 'upload',
body: FormData {
_overheadLength: 104,
_valueLength: 80,
_valuesToMeasure: [],
writable: false,
readable: true,
dataSize: 0,
maxDataSize: 2097152,
pauseStreams: true,
_released: false,
_streams: [
'----------------------------594660553626244976225816\r\n' +
'Content-Disposition: form-data; name="image"\r\n' +
'\r\n',
'https://upload.wikimedia.org/wikipedia/commons/a/a0/Sunflower_as_gif_websafe.gif',
[Function: bound ]
],
_currentStream: null,
_insideLoop: false,
_pendingNext: false,
_boundary: '--------------------------594660553626244976225816'
},
params: URLSearchParams {},
headers: Headers {
[Symbol(map)]: [Object: null prototype] {
'Content-Type': [Array],
Authorization: [Array]
}
}
}
What am I missing here? The API seems to be accepting my form data so I would think that maybe there's some issue with one of the other headers, but in Postman it looks like there's only a few required headers, most of which are calculated (e.g. Content-Length) and so I assume apollo-datasource-rest must be handling that.
After doing some more research into multipart/form-data, I found that the boundary parameter is mandatory, and must be added to the Content-Type value in the request for the server to be able to parse the payload. Furthermore I am unable to manually set it as a parameter in the request (at least not in a way that actually works). Postman normally calculates this field when the request is sent, but apollo-datasource-rest doesn't automatically handle that.
Changing the Content-Type to application/x-www-form-urlencoded and using a url encoded string instead of form-data fixed the issue.
Here's the updated code:
willSendRequest(request) {
request.headers.set("Content-Type", `application/x-www-form-urlencoded`);
request.headers.set(
"Authorization",
`Client-ID ${process.env.IMGUR_CLIENT_ID}`
);
console.log(request);
}
async uploadImageFromUrl(url) {
const formData = `image=${url}&album=${process.env.IMGUR_ALBUM_DELETE_HASH}&type=url`;
return this.post("upload", formData);
}
So I have never post a data using FormData and multipart/form-data as Content-Type in my React project. But now I'm kinda forced by backend to send it this way since we have some images in payload.
The problem is that the whole data is a JS object and can be parsed to JSON, and nothing more. So how can I convert my JS object into a valid FormData that backend would accept it? Everything works without a problem in Postman, but in the app I always get the same error.
Here is some more detail:
The working Postman sample:
What I expect to be working (but obviously doesn't):
const createProd = () =>
HttpRequest.post('/api/prod', {
body: {
Product: {
title: 'Test Prod',
shop: null,
description: "My new ad's description",
category: { id: '5d8c6aa6fadeaf26b0194667' },
condition: 'USED'
}
});
HttpRequest is a helper function which uses ES6 fetch for requests.
I always get the same error: "Required request part 'Product' is not present" with/without JSON.stringify.
I even tried to create a sample FormData to at least change the error:
cont payload = new FormData();
payload.append('Product', {foo: 'bar'});
But still same error. I also copied the code which is generated by Postman. But still no chance.
I would be thankful if you share your suggestions or workarounds.
Thanks in advance.
const formData = new FormData();
const product = { //your product object };
formData.append('product', JSON.stringify(product));
const config = {
headers: {
'Content-Type': 'multipart/form-data; charset=utf-8; boundary="another cool boundary";'
}
};
axios.post(`/api/ads`, formData, config).then((res) => {
console.log(res);
}).catch(err => {
console.log(err);
});
Maybe you should set header.
Try this one. In my case I used Axios. It worked for me in my project.