What is "406-Not Acceptable Response" in HTTP? - json

In my Ruby on Rails application I tried to upload an image through the POSTMAN REST client in Base64 format. When I POST the image I am getting a 406 Not Acceptable Response. When I checked my database, the image was there and was successfully saved.
What is the reason for this error, is there anything I need to specify in my header?
My request:
URL --- http://localhost:3000/exercises.json
Header:
Content-Type - application/json
Raw data:
{
"exercise": {
"subbodypart_ids": [
"1",
"2"
],
"name": "Exercise14"
},
"image_file_name": "Pressurebar Above.jpg",
"image":"******base64 Format*******"
}

Your operation did not fail.
Your backend service is saying that the response type it is returning is not provided in the Accept HTTP header in your Client request.
Ref: http://en.wikipedia.org/wiki/List_of_HTTP_header_fields
Find out the response (content type) returned by Service.
Provide this (content type) in your request Accept header.
http://en.wikipedia.org/wiki/HTTP_status_code -> 406

406 Not Acceptable
The resource identified by the request is only capable of generating response entities which have content characteristics not
acceptable according to the accept headers sent in the request.
406 happens when the server cannot respond with the accept-header specified in the request.
In your case it seems application/json for the response may not be acceptable to the server.

You mentioned you're using Ruby on Rails as a backend. You didn't post the code for the relevant method, but my guess is that it looks something like this:
def create
post = Post.create params[:post]
respond_to do |format|
format.json { render :json => post }
end
end
Change it to:
def create
post = Post.create params[:post])
render :json => post
end
And it will solve your problem. It worked for me :)

"Sometimes" this can mean that the server had an internal error, and wanted to respond with an error message (ex: 500 with JSON payload) but since the request headers didn't say it accepted JSON, it returns a 406 instead. Go figure. (in this case: spring boot webapp).
In which case, your operation did fail. But the failure message was obscured by another.

You can also receive a 406 response when invalid cookies are stored or referenced in the browser - for example, when running a Rails server in Dev mode locally.
If you happened to run two different projects on the same port, the browser might reference a cookie from a different localhost session.
This has happened to me...tripped me up for a minute. Looking in browser > Developer Mode > Network showed it.

const request = require('request');
const headers = {
'Accept': '*/*',
'User-Agent': 'request',
};
const options = {
url: "https://example.com/users/6",
headers: headers
};
request.get(options, (error, response, body) => {
console.log(response.body);
});

Changing header to Accept: */* resolved my issue and make sure you don't have any other Accept Header

In my case, I added:
Content-Type: application/x-www-form-urlencoded
solved my problem completely.

If you are using 'request.js' you might use the following:
var options = {
url: 'localhost',
method: 'GET',
headers:{
Accept: '*/*'
}
}
request(options, function (error, response, body) {
...
})

In my case for a API in .NET-Core, the api is set to work with XML (by default is set to response with JSON), so I add this annotation in my Controller :
[Produces("application/xml")]
public class MyController : ControllerBase {...}
Thank you for putting me on the path !

It could also be due to a firewall blocking the request. In my case the request payload contained string properties - "like %abc%" and ampersand symbol "&" - which caused the firewall to think it is a security risk (eg. a sql injection attack) and it blocked the request. Note here the request does not actually go to the server but is returned at the firewall level itself.
In my case, there were no application server logs generated so I knew that the request did not actually reach the server and was blocked before that. The logs that helped me were Web application firewall (WAF) logs.

Related

Issue with Axios GET properties from Model Properties API on Autodesk Forge

I'm having trouble getting the results for [GET projects/:projectId/diffs/:diffId/properties] from the new Model Properties API provided by Autodesk Forge.
I've been able to get all the Model Properties API calls (both Index and Diff) to work on Postman. However, on a NodeJS server (using axios) the properties call doesn't work, and returns a 502 error.
Below is an example code:
const result = await axios.get(
`https://developer.api.autodesk.com/construction/index/v2/projects/${projectId}/diffs/${diffId}/properties`,
{
headers: {
Authorization: `Bearer ${internalToken.access_token}`,
},
},
);
If I replace properties with either manifest or fields, the results are returned normally. This applies to both Index and Diff.
I'm not sure if this is actually an internal server error (which is the error returned), or is there something wrong in the request that is being sent?
Note: if it makes any difference, it is a BIM360 project.
Update: After some further usage, it seems that the error 502 with status of 'Bad Gateway' occurs when the response is large. Responses above ~14MB return this error. This is confirmed because the results return normally on Postman.
Could anyone from Autodesk help me with this? And if there are any alternatives to fixing this issue.
In case somebody runs into the same problem, it was solved by adding 'Accept-Encoding': 'gzip, deflate, br' to the header in the request.

Using Vue and axios post to json file problem

I got problem with axis posting to local .json file. It gives me an error:
POST http://localhost:8080/todolist.json 404 (Not Found)
TodoListEditor.vue?b9d6:110 Error: Request failed with status code 404
at createError (createError.js?2d83:16)
at settle (settle.js?467f:18)
at XMLHttpRequest.handleLoad (xhr.js?b50d:77)
I tried many address schemes but everything ends the same. When I pass exact same address into axios.get() - it returns proper data and reads the file.
Here's my part of code:
axios.post('http://localhost:8080/todolist.json',
this.todolist,{
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
"Access-Control-Allow-Origin": "*",
}
}).then((response)=>{
console.log(response);
}).catch((error)=>{
console.log(error);
});
Thanks for help
The types of HTTP requests GET and POST have their own roles. GET is a request to retrieve information, POST is a request to write data, and the server acts differently for each method. The above error indicates that the server is unable to process the request for POST requests.
Sending a get request from the URL above seems to work well because it means bringing in the todolist.json file, and sending a post request to a specific file is inappropriate.

Postman - Error 400 Bad Request

I'm trying to access an API using Postman to get a response using basic authentication, but when I submit the data, it gives me the dreaded 400 error, which apparently indicates that some headers aren't set up properly.
Here's the API info:
Request
Endpoint: {loginUrl}
Data to submit: an email and a password
POST /login HTTP/1.1
Host: {baseUrl}
Accept: application/json
Content-Type: application/json
Content-Length: 68
{
"email": "{email}",
"password": "{password}"
}
And in response, I should get an encrypted token in form of JSON, instead I'm getting this error.
Here are the postman screenshots:
Am I missing something?
I also faced the same issue and i updated my postman header with the below image. And issue solved.
From the lack of details it's difficult to offer a specific answer but I can offer something that you can try - The Request data you posted in the question looks like you should be adding:
{
"email": "{email}",
"password": "{password}"
}
In the Body section of the request but your images don't show that you've added that to the Body on any request, you've added it as a Auth header instead, so remove that before trying again. I'm not sure of the need to add the Content-Length header as that will change for different username and password combinations in the payload or for the length of the response.
In case anyone finds this helpful, I ran into the same issue and the culprit turned out to be missing headers. I knew I needed the "Content-Type": "application/json" header, which I already had in place, but I didn't know that I was missing two other headers.
The solution for me was also adding the "Content-Length" and "Host" headers in Postman.
I see some others have questioned the need for the "Content-Length" header, but in my case, the minimum three needed were "Content-Type", "Content-Length", and "Host" or it would always fail.
I faced a similar issue. it got resolved when i called my placeholder as a tuple.

Why is my ajax get request responding with an error even though it was successful?

I am attempting to retrieve some data from a 3rd party domain. When I enter the request url. I am able to see the data I requested. But when I attempt to make a call using ajax (to a different domain), it returns the error message. Why am I not able to retrieve the data? Might it have something to do with cross-domain policy and not using jsonp? Here is my code:
<script>
$(document).ready(function() {
$.ajax ({
type: 'GET',
url: 'https://crm.zoho.com/crm/private/json/Potentials/searchRecords?authtoken=xxx&scope=crmapi&criteria=(((Potential%20Email:test2#email.com))&selectColumns=Potentials(Potential%20Name)&fromIndex=1&toIndex=1',
dataType: 'json',
success: function(test) {
alert(JSON.stringify(test));
},
error: function(test) {
alert(JSON.stringify(test));
}
});
});
</script>
Because the request that you has send is blocked by the browser. When you perform a request using an object XmlHttpRequest and obviously javascript, the browser applied cross-domain policy, defined in WC3, and thus verify in url the origin and target domain (protocol, host and port), if those elements are in different domain (i.e. host and port), then the request never comes out from browser (a.k.a User Agent). You can use jsonp to "break" or "jump" this policy, simply is a tag "script" with a resource (src) defined in a different domain using a parameter called "jsonCallback=?" added in query string, who really receives the data in format json. This is more ugly and have a security risk, therefore never be used.
The other method is to use and enable a "technique" (is more than that) known like "CORS" (Cross Origin Request Sharing), where the client (browser) and server (resource at different domain), send, exchange and negotiate an Http Headers to secure that who send and who received are authorized to exchange information. The basics steps to realize CORS is:
Explicity define in client (ajax-jquery) that CORS will be used in request, specifying CrossDomain:true. This will enable HTTP Headers defined in CORS
Specify in the HTTP Server, a HTTP Header indicating the Domain Source that have permissions to call a resource hosted in server. The most general header can be defined like: Access-Control-Allow-Origin , with value asigned a domain, like "*" (all domain authorized) (Access-Control-Allow-Origin, *)
In some Browsers, sometimes they send a http header request called "preflight request", is like a discover via to know if the server is prepared to recieve cross-origin request. This Http Header contains a "Method HTTP" value or "Verb HTTP" (like PUT,POST,GET,DELETE) assigned to "OPTIONS", then the server must be configured too to recieve HTTP Headers with Method "OPTIONS", and therefore allow methods http like PUT, DELETE,POST or GET. In generals terms the server must have this headers when in the request had a method HTTP "OPTIONS":
Access-Control-Allow-Methods , "POST, PUT, DELETE, GET, OPTIONS"
Access-Control-Allow-Headers, ", "Content-Type, Accept"
Finally, the client (ajax) will recieve the data from the server.
This sounds a little confusing and the steps are few, sorry that not put a code like examples, but, really CORS is not hard to understand.
I hope this will help.
References from Mozilla:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
This show what is CORS and you can use in configuration server:
http://enable-cors.org/

Querying a JSON REST Service with POSTMAN/Rest Client

I have a simple RESTLET Service which returns a JSON representation, as shown below:
#Override
#Post("json")
public Representation helloWorld() {
Representation representation = new JacksonRepresentation<Hello>(new Hello("Hello World"));
representation.setMediaType(MediaType.APPLICATION_JSON);
representation.
return representation;
}
When I query this using cURL I get the response as expected:
{"greeting":"Hello World"}
However I do not get a response when I use the browser or POSTMAN or indeed any other web REST client. I get the response 'Could not get any response' from POSTMAN.
The preview of the POSTMAN request is:
POST /testingrestlet/hello HTTP/1.1
Host: 127.0.0.1:6000
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: 5141cd87-505c-e813-0045-3b7f4aa54144
I would at least have expected a REST client such as POSTMAN to work, or am I missing something?
Any help appreciated.
Regards
I think that you should use an header Accept for the content negotiation (conneg). Your request should be:
POST /testingrestlet/hello HTTP/1.1
Host: 127.0.0.1:6000
Content-Type: application/json
Accept: application/json
Cache-Control: no-cache
Postman-Token: 5141cd87-505c-e813-0045-3b7f4aa54144
As a matter of fact, since you specify the extension "json" in the annotation, Restlet expects that this header was sent with one of possible media types for JSON content. This hint is used to select the method for processing... You shouldn't have this problem if you remove the extension, as described below:
#Post
public Representation helloWorld() {
Representation representation
= new JacksonRepresentation<Hello>(new Hello("Hello World"));
representation.setMediaType(MediaType.APPLICATION_JSON);
(...)
return representation;
}
Hope it helps you,
Thierry
With help from Thierry's comments the issue was traced down to Google Chrome blocking requests to port 6000 as it considers them unsafe. The error was only visible in Chrome Debug mode where the ERR_UNSAFE_PORT error was reported. Changing to a higher port resolved the issue! Detail of this error can also be found here: https://superuser.com/questions/188006/how-to-fix-err-unsafe-port-error-on-chrome-when-browsing-to-unsafe-ports