I am trying to use a REST API to upload a file. I have a function that works for every other type of request, but this one (which uploads a file) doesn't want to work:
var createItem = function ()
{
request.post(
{
url:browser.params.baseRestUrl + 'repositories/Samples/items',
auth: browser.params.auth,
body: fs.createReadStream(filepath),
form:
{
headers: {'content-type': 'application/octet-stream',
'Content-Disposition': 'attachment; filename="oneHourSally3.fmw"',
'Accept': 'application/json'
},
}
},
function(e,r,user){ console.log("Status code of createItem('oneHourSally'): " + r.statusCode);});
};
This returns a http 415 (unsupported media type) error.
Usually that error implies that the server is only willing to accept a specific Content-Type. You're specifying application/octet-stream and the server tells you it doesn't accept that. Consult the documentation of the API to figure out what is supported, or contact the authors of the API via a support channel.
Related
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).
I'm 'publishing' a zip file to a server app via a REST endpoint. If I POST via Postman or the app's frontend, I get a published zip file which is valid. I can turn around download it, and open it, etc.
If I attempt to do the same thing with my code and Axios, the server app's attempt to unzip and use the content I've uploaded fails. If I DL the archive, it is corrupt. The fact that the same archive works via Postman & the app's UE tells me this is either a PEBKAC or potentially an issue with Axios itself. Here is the code I'm using to POST to the endpoint. Note that at the end, I'm actually writing the data I POST to a local file on my machine as a zip so I can verify I'm not doing anything dumb whenI read the file via fs. The local copy of the file I created is fine and dandy.
Note how I'm actually hard-coding content-length, as well. I'm testing with a single file and I've verified the length is correct via fs.statSync AND that it matches the Content-Length I see when I upload via Postman & the App's UE.
var uploadFile = (data, fileInfo) => new Promise(resolveUpload => {
console.log("Starting Upload API call for:", fileInfo.description);
axios.post(aepServer + '/api/v1/files',
data, {
jar: cookieJar,
withCredentials: true,
headers: {
'Content-Type': 'application/octet-stream',
'path': fileInfo.path,
'description': fileInfo.description,
'Content-Length': 354198,
'Accept-Encoding': 'gzip, deflate, br',
'Accept': '*/*',
'Connection': 'keep-alive'
},
// DANGER: allow self-signed certs workaround which I must remove
httpsAgent: new https.Agent({
rejectUnauthorized: false,
})
}).then((response) => {
fileResponse = response.data;
console.log('\n', chalk.bgMagenta('FILE UPLOADED: '), response);
fs.writeFileSync('c:\\data\\newfile.zip', data, 'binary');
resolveUpload(fileResponse);
})
.catch((err) => {
console.log("AXIOS ERROR: ", err);
})
});
Does anything look wrong here? While looking at the response object, I do see something that has me scratching my head:
headers: {
Accept: '*/*',
'Content-Type': 'application/octet-stream',
path: '/Workspaces/Public%20Apps/UFOs.yxzp',
description: 'UFO Sitings in the US, 1995 to present',
'Content-Length': 532362,
'Accept-Encoding': 'gzip, deflate, br',
Connection: 'keep-alive',
Cookie: 'ayxSession=s%3Ac39f55a3-b219-43a5-9f8a-785e1222c81c.QR4KI8uXaQlL9axqkO8AkyabPVt3i37nGbz%2FJef0eqU',
'User-Agent': 'axios/0.19.2'
},
Look at the content length: 532362 bytes. It seems like the ~354k value I hard-coded in the headers is being ignored somehow. Might this be my problem? [BTW, if I use the same code to upload a csv or txt file, all is well - this seems related to compressed files only]
EDIT: Welp, it looks like Axios does override that property and there's nothing I can do about it: Axios set Content-Length manually, nodeJS. Now the question is if setting this incorrectly would munge the file and WHY the value is wrong. When I do a data.length, I get the 354198 value.
can you try with 'multipart/form-data'
axios.post('upload_file', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
alternatively get the CURL request using postman and use the header information supplied by postman
My answer was here:
Reading binary data in node.js
In essence, I was reading the zip file as 'binary" when I shouldn't have passed anything in at all.
var content = fs.readFileSync(aFile.readFrom);
//NOT
//var content = fs.readFileSync(aFile.readFrom, 'binary');
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).
I'm making a POST request to a node.js server and I'm having trouble getting it to work. Here's my request:
const headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'this-can-be-anything',
};
export const postVote = (id, vote) =>
fetch(`${uri}/posts/${id}`, {
method: 'POST',
headers,
body: JSON.stringify({options: vote}),
}).then(response => response.json())
.then(data => data)
.catch(err => console.log(err));
The function accepts an 'id' and a 'vote', both strings. The id is being used as part of the URI in the request, and the vote is being supplied as options so the API knows what to do with it. Both of the arguments are being passed correctly:
id = '8xf0y6ziyjabvozdd253nd'
vote = 'upVote'
Here's a link to the GitHub repository for the server/API:
Udacity Readable API
and a screenshot of the network when firing the request:
UPDATE: Added the second screenshot which shows status 200. Though it shows this and appears to have been successful, it still doesn't post to the server and the information stays the same.
What you are looking at is the OPTIONS request in the network tab. For cross origin requests, every request if preceeded by an OPTIONS request which tells the calling client (browser, for example) if those HTTP methods are supported by the remote server for use in crosss origin context.
Check the other requests out. If the OPTIONS request was responded to correctly by the server, the browser must automatically follow up with your POST request
EDIT:
Also, the docs specify the param name to be option whereas in your screenshot it is coming up as options.
Further reading: CORS
Try declaring the headers as such:
var headers = new Headers({
'Content-Type': 'application/json',
'Authorization': 'this-can-be-anything',
})
I am trying to send a file to the server using aurelia-fetch-client, but get the following error in the browser console. No 'Access-Control-Allow-Origin' header is present on the requested resource., but when I do the same with XMLHttpRequest file is uploaded.
Aurelia Fetch Client configuration and usage code
activate() {
await fetch;
this.http = this.httpClient();
this.http.configure(config => {
config
.useStandardConfiguration()
.withBaseUrl('http://localhost:3000')
});
}
makeRequest(data) {
this.http.fetch('upload', {
headers: {
'Content-Type': 'multipart/form-data'
},
method: 'post',
body: data
});
}
Following the comments here is the answer:
CORS was not enabled on the server, and Ilia suggested the use of the cors-express module if you are using node.
The following resources can be helpful for that:
http://enable-cors.org/server_expressjs.html
https://github.com/expressjs/cors