Image via post request and form-data body [duplicate] - javascript

I want to set _boundry in my header.
First, I dispatch the form data:
//component.js
const form = new FormData();
form.append('email', 'eray#serviceUser.com')
form.append('password', '12121212')
dispatch(FetchLogin.action(form))
Second, I prepare api call;
//loginService.js
import api from '#/Services'
export default async form => {
const response = await api.post('user/login/', form)
return response.data
}
Third, I make api call;
//Services/index.js
import axios from 'axios'
import { Config } from '#/Config'
const instance = axios.create({
baseURL: Config.API_URL,
headers: {
'Content-Type': `multipart/form-data; boundary=${form._boundary}`, //Cannot access form here
},
timeout: 3000,
})
instance.interceptors.response.use(
response => response,
({ message, response: { data, status } }) => {
return handleError({ message, data, status })
},
)
export default instance
I want to access form data within to axios instance to be able to use form._boundry in headers.
How can I pass form data from loginService.js to Services/index.js?

This question seems to come up often enough yet I cannot seem to find a canonical answer so here goes...
When performing AJAX requests from a browser (via fetch or XMLHttpRequest), the runtime knows what to do for certain request body formats and will automatically set the appropriate Content-type header
If the request body is a FormData instance, the Content-type will be set to multipart/form-data and will also include the appropriate mime boundary tokens from the data instance.
All of these examples will post the data as multipart/form-data with appropriate mime boundary tokens
const body = new FormData();
// attach files and other fields
body.append("file", fileInput.files[0]);
body.append("foo", "foo");
body.append("bar", "bar");
// fetch
fetch(url, { method: "POST", body });
// XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.send(body);
// Axios
axios.post(url, body);
If the request body is a URLSearchParams instance, the Content-type will be set to application/x-www-form-urlencoded
All of these examples will post the data as application/x-www-form-urlencoded
const body = new URLSearchParams({ foo: "foo", bar: "bar" });
// serialises to "foo=foo&bar=bar"
// fetch
fetch(url, { method: "POST", body });
// XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.send(body);
// Axios
axios.post(url, body);
You only need to manually set the content-type if you intend to send string data in a particular format, eg text/xml, application/json, etc since the runtime cannot infer the type from the data.
const body = JSON.stringify({ foo: "foo", bar: "bar" });
// fetch
fetch(url, {
method: "POST",
headers: {
"content-type": "application/json",
},
body
});
// XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.setRequestHeader("content-type", "application/json");
xhr.send(body);
On Axios
Axios will automatically stringify JavaScript data structures passed into the data parameter and set the Content-type header to application/json so you only need minimal configuration when dealing with JSON APIs
// no extra headers, no JSON.stringify()
axios.post(url, { foo: "foo", bar: "bar" })
Under the hood, Axios uses XMLHttpRequest so the specifications for FormData and URLSearchParams also apply.
Axios v0.27.1 is broken
This specific version of Axios is unable to make a proper request with FormData. Do not use it!
Axios v1.0.0+ is broken
This is verging into my own opinion but every Axios release post v1.0.0 has been fundamentally broken in one way or another. I simply cannot recommend anyone use it for any reason.
Much better alternatives are:
The Fetch API (also available in Node v18+)
got for Node.js
ky for browsers
NodeJS
When using Axios from the backend, it will not infer Content-type headers from FormData instances. You can work around this using a request interceptor.
axios.interceptors.request.use(config => {
if (config.data instanceof FormData) {
Object.assign(config.headers, config.data.getHeaders());
}
return config;
}, null, { synchronous: true });
or simply merge in the headers when making a request
axios.post(url, body, {
headers: {
"X-Any-Other-Headers": "value",
...body.getHeaders(),
},
});
See https://github.com/axios/axios#form-data
On jQuery $.ajax()
jQuery's $.ajax() method (and convenience methods like $.post()) default to sending request body payloads as application/x-www-form-urlencoded. JavaScript data structures will be automatically serialised using jQuery.param() unless told not to. If you want the browser to automatically set the Content-type header based on the body format, you also need to configure that in the options
const body = new FormData()
body.append("foo", "foo")
body.append("bar", "bar")
$.ajax({
url,
method: "POST",
data: body,
contentType: false, // let the browser figure it out
processData: false // don't attempt to serialise data
})

Related

Error 415 uploading an image from fetch react js but not with postman [duplicate]

I want to set _boundry in my header.
First, I dispatch the form data:
//component.js
const form = new FormData();
form.append('email', 'eray#serviceUser.com')
form.append('password', '12121212')
dispatch(FetchLogin.action(form))
Second, I prepare api call;
//loginService.js
import api from '#/Services'
export default async form => {
const response = await api.post('user/login/', form)
return response.data
}
Third, I make api call;
//Services/index.js
import axios from 'axios'
import { Config } from '#/Config'
const instance = axios.create({
baseURL: Config.API_URL,
headers: {
'Content-Type': `multipart/form-data; boundary=${form._boundary}`, //Cannot access form here
},
timeout: 3000,
})
instance.interceptors.response.use(
response => response,
({ message, response: { data, status } }) => {
return handleError({ message, data, status })
},
)
export default instance
I want to access form data within to axios instance to be able to use form._boundry in headers.
How can I pass form data from loginService.js to Services/index.js?
This question seems to come up often enough yet I cannot seem to find a canonical answer so here goes...
When performing AJAX requests from a browser (via fetch or XMLHttpRequest), the runtime knows what to do for certain request body formats and will automatically set the appropriate Content-type header
If the request body is a FormData instance, the Content-type will be set to multipart/form-data and will also include the appropriate mime boundary tokens from the data instance.
All of these examples will post the data as multipart/form-data with appropriate mime boundary tokens
const body = new FormData();
// attach files and other fields
body.append("file", fileInput.files[0]);
body.append("foo", "foo");
body.append("bar", "bar");
// fetch
fetch(url, { method: "POST", body });
// XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.send(body);
// Axios
axios.post(url, body);
If the request body is a URLSearchParams instance, the Content-type will be set to application/x-www-form-urlencoded
All of these examples will post the data as application/x-www-form-urlencoded
const body = new URLSearchParams({ foo: "foo", bar: "bar" });
// serialises to "foo=foo&bar=bar"
// fetch
fetch(url, { method: "POST", body });
// XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.send(body);
// Axios
axios.post(url, body);
You only need to manually set the content-type if you intend to send string data in a particular format, eg text/xml, application/json, etc since the runtime cannot infer the type from the data.
const body = JSON.stringify({ foo: "foo", bar: "bar" });
// fetch
fetch(url, {
method: "POST",
headers: {
"content-type": "application/json",
},
body
});
// XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.setRequestHeader("content-type", "application/json");
xhr.send(body);
On Axios
Axios will automatically stringify JavaScript data structures passed into the data parameter and set the Content-type header to application/json so you only need minimal configuration when dealing with JSON APIs
// no extra headers, no JSON.stringify()
axios.post(url, { foo: "foo", bar: "bar" })
Under the hood, Axios uses XMLHttpRequest so the specifications for FormData and URLSearchParams also apply.
Axios v0.27.1 is broken
This specific version of Axios is unable to make a proper request with FormData. Do not use it!
Axios v1.0.0+ is broken
This is verging into my own opinion but every Axios release post v1.0.0 has been fundamentally broken in one way or another. I simply cannot recommend anyone use it for any reason.
Much better alternatives are:
The Fetch API (also available in Node v18+)
got for Node.js
ky for browsers
NodeJS
When using Axios from the backend, it will not infer Content-type headers from FormData instances. You can work around this using a request interceptor.
axios.interceptors.request.use(config => {
if (config.data instanceof FormData) {
Object.assign(config.headers, config.data.getHeaders());
}
return config;
}, null, { synchronous: true });
or simply merge in the headers when making a request
axios.post(url, body, {
headers: {
"X-Any-Other-Headers": "value",
...body.getHeaders(),
},
});
See https://github.com/axios/axios#form-data
On jQuery $.ajax()
jQuery's $.ajax() method (and convenience methods like $.post()) default to sending request body payloads as application/x-www-form-urlencoded. JavaScript data structures will be automatically serialised using jQuery.param() unless told not to. If you want the browser to automatically set the Content-type header based on the body format, you also need to configure that in the options
const body = new FormData()
body.append("foo", "foo")
body.append("bar", "bar")
$.ajax({
url,
method: "POST",
data: body,
contentType: false, // let the browser figure it out
processData: false // don't attempt to serialise data
})

How can I send data on request.body in an ajax call? [duplicate]

I have a React application where I am changing POST method to GET with the request body as it is. It works fine with POST request however when I change the method to GET, it gives me error-
message: "org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public
My Front End Code-
export const setData = (getData) => dispatch => {
axios({
method: 'GET',
url: 'http://localhost:8080/api',
headers: {
'Content-Type': 'application/json'
},
data: getData
})
.then (response => {
dispatch({
type: API_DATA,
payload: response.data
})
dispatch({
type: SET_SEARCH_LOADER,
payload: false
})
})
.catch(function(error) {
})
}
Can someone let me know what I am missing here. As per my understanding, http allows to have a request body for GET method.
As per my understanding, http allows to have a request body for GET method.
While this is technically true (although it may be more accurate to say that it just doesn't explicitly disallow it), it's a very odd thing to do, and most systems do not expect GET requests to have bodies.
Consequently, plenty of libraries will not handle this.
The documentation for Axois says:
// `data` is the data to be sent as the request body
// Only applicable for request methods 'PUT', 'POST', and 'PATCH'
Under the hood, if you run Axios client side in a web browser, it will use XMLHttpRequest. If you look at the specification for that it says:
client . send([body = null])
Initiates the request. The body argument provides the request body, if any, and is ignored if the request method is GET or HEAD.
If you want to send parameters with get request in axios, you should send parameters as params.
If you want to set "Content-type":"application/json" and send params with get request, you should also send an empty data object.
For example:
const AUTH_TOKEN = 'Bearer token'
const config = {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': AUTH_TOKEN,
},
data: {},
params: {
"post_id": 1
}
}
axios.get("http://localhost/api/v1/posts/", config)
This is not axios, the error origniates from the java backend you're talking to. The public field in your request body is missing.
If you just want to send the data as parameters (which would be odd), pass it using params instead of data (as shown here: https://github.com/axios/axios#example).
I personally don't think your API should support GET with a request body (talk to the devs and ask for documentation).

Using FormData() inside fetch api is not working

I read all over but couldn't find the answer.
When I use FormData(), it returns status 404 bad request.
However, if I pass the data (hardcoded) as in const requestBody (example below), it works perfectly.
This is my code:
var formData = new FormData();
formData.append("nickname", "johxns");
formData.append("password", "john_password");
formData.append("email", "john#server.com");
// If I do it this way, and assign this to body inside fetch, it works perfectly
// const requestBody = '{"nickname": "johxns","password":"john_password","email":"john#server.com"}';
fetch("http://localhost:5000/create_user", {
// if instead of formData, I assign requestBody to body, it works!
body: formData,
headers: {
"Content-Type": "application/json"
},
method: "POST"
}).then(function(response) {
return response.text();
}).then(function(data){
console.log('data', data);
}).catch(function(err){
console.err(err);
});
I already tried with URLSearchParams, but still couldn't make it work.
Thanks.
You shouldn't set the Content-Type header to application/json if you're not sending json. According to this answer, you don't need to set the Content-Type header.
body data type must match "Content-Type" header
Using Fetch
You should either send json data if you set Content-Type to application/json or not set any Content-Type if using FormData API since the fetch function is able to determine the correct Content-Type.
See here for more informations.

Make a correct POST request and get response data

I have an application hosted on pythonanywhere.com. It throws a 400 error if sended data does not contain data property, otherwise it returns a response data. This is Flask code of the server:
#app.route('/api', methods=['POST'])
def get_post():
if not request.json or not 'data' in request.json:
abort(400)
data = request.json['data']
# do something with the data...
return jsonify({'response': str(data)}), 200
And my front-end part of application should send a POST request with a data and get a response. I am trying to use fetch but it gets a 400 error though I send a JSON object with a data object:
function sendData(value) {
data = { 'data': value };
fetch('http://' + appUrl, {
method: 'POST',
headers: {
'content-type': 'application/json',
},
mode: 'no-cors',
body: JSON.stringify(data),
})
.then(data => { return data.json() })
}
Also I tried to use XMLHttpRequest:
var xhr = new XMLHttpRequest();
xhr.open("POST", 'http://' + appUrl, true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(data);
But I can't find out how to disable CORS and get a response data.
if you are having CORS issue, always check if the server accept your origin of request (other than pythonanywhere.com) if not, you should allow it from your server.
you mentioned that you are using Flask as your backend, you might want to check out this library:
https://flask-cors.readthedocs.io/en/latest/
if you follow the docs from the link, you can allow, accept http request depends on the parameter you provided.
Happy Coding

Sending Request body for GET method in AXIOS throws error

I have a React application where I am changing POST method to GET with the request body as it is. It works fine with POST request however when I change the method to GET, it gives me error-
message: "org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public
My Front End Code-
export const setData = (getData) => dispatch => {
axios({
method: 'GET',
url: 'http://localhost:8080/api',
headers: {
'Content-Type': 'application/json'
},
data: getData
})
.then (response => {
dispatch({
type: API_DATA,
payload: response.data
})
dispatch({
type: SET_SEARCH_LOADER,
payload: false
})
})
.catch(function(error) {
})
}
Can someone let me know what I am missing here. As per my understanding, http allows to have a request body for GET method.
As per my understanding, http allows to have a request body for GET method.
While this is technically true (although it may be more accurate to say that it just doesn't explicitly disallow it), it's a very odd thing to do, and most systems do not expect GET requests to have bodies.
Consequently, plenty of libraries will not handle this.
The documentation for Axois says:
// `data` is the data to be sent as the request body
// Only applicable for request methods 'PUT', 'POST', and 'PATCH'
Under the hood, if you run Axios client side in a web browser, it will use XMLHttpRequest. If you look at the specification for that it says:
client . send([body = null])
Initiates the request. The body argument provides the request body, if any, and is ignored if the request method is GET or HEAD.
If you want to send parameters with get request in axios, you should send parameters as params.
If you want to set "Content-type":"application/json" and send params with get request, you should also send an empty data object.
For example:
const AUTH_TOKEN = 'Bearer token'
const config = {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': AUTH_TOKEN,
},
data: {},
params: {
"post_id": 1
}
}
axios.get("http://localhost/api/v1/posts/", config)
This is not axios, the error origniates from the java backend you're talking to. The public field in your request body is missing.
If you just want to send the data as parameters (which would be odd), pass it using params instead of data (as shown here: https://github.com/axios/axios#example).
I personally don't think your API should support GET with a request body (talk to the devs and ask for documentation).

Categories

Resources