I would like to test the api of an application, I've got a token from the developer, but I'm getting an error 'cy.request() failed on:
https://******************************
The response we received from your web server was:
406: Not Acceptable
This was considered a failure because the status code was not 2xx or 3xx.'
This is the code that I used:
describe('API Test', () => {
const token = 'your_token_here';
it('Should make a GET request with a Bearer token and avoid 406 error', () => {
cy.request({
method: 'GET',
url: 'https://your-api.com/endpoint',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body).to.be.an('object');
});
});
});
I tried with 'Accept': 'application/json' and 'Content-Type': 'application/json', but it didn't help.
the Content-type header is used to indicate the original media type of the resource.
Here since you are sending a GET request content-type does not matter.
the Accept header is used by the sender of the request(browser) to specify response media types that are acceptable. So here in your case maybe the type of the response is not application/json that's why you are gettin an
406: Not Acceptable
I found also in this source that in some cases, the server could be responsible for the 406 Error since it's the network object producing the error. Perhaps the server is misconfigured and can't handle the request correctly. Maybe it's a traffic routing issue.
so try your REQUEST without any header and if the 406 still occurs you are sure that it is from ther server and that your REQUEST is OK.
I'm really new to the concept of REST and I've been trying to work with Google's Sheets, Drive, and Classroom APIs. I have been able to pull classroom roster data, but I can't for the life of me figure out how to fix this issue with a parseError and Googling for hours hasn't helped.
let init = {
method: "POST",
async: true,
headers: {
Authorization: "Bearer " + token,
"Content-Type": "application/json",
},
body: {
"mimeType": "application/vnd.google-apps.spreadsheet"
},
"contentType": "application/json"
};
fetch('https://www.googleapis.com/drive/v3/files?key='+apicall, init)
.then((response) => response.json())
.then(function(data) {
console.log(data);
console.log(init);
});
The console logs are so I can view the data, this clearly isn't going to be in the final project, but every time I send the request, it throws me error 400 parseError, which Google clearly tells me is a Content-Type error, but I specified that it's JSON, so I'm a bit confused. Any help is very much appreciated!
I figured out my own answer after some tinkering around. I changed the Content-Type to application/javascript. Even though it wasn't what I was looking for, it threw an error saying to change the fetch URI. I tried, and it made a Javascript file containing nothing but [object Object]. I was confused so I changed it all back. I read up some more on JSON formatting when I came across this quote:
When you have a Javascript object, serializing JSON is very easy:
Which lead me to remember it made the empty Javascript object... ohhhh! The body information wasn't being formatted as JSON data, but rather as a Javascript array! So then I guess I should...
var bodydata = {"name": "New spreadsheet", "mimeType": "application/vnd.google-apps.spreadsheet"};
let init = {
method: "POST",
async: true,
headers: {
Authorization: "Bearer " + token,
"Content-Type": "application/json",
},
body: JSON.stringify(bodydata)
...convert the Javascript data into a JSON string!
And it worked! It was very satisfying, but I figured I'd answer my own question on here for anyone else just learning REST APIs and figuring out stuff on their own like me!
The fetch() API is not POSTing this JSON body.
var j = {
"addressee": "James"
};
return fetch('http://requestb.in/blahblahblah', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Cache-Control': 'no-cache'
},
body: JSON.stringify(j)
})
There is absolutely no request body showing up in RequestBin for this. What could be happening to the body? Debugging JSON.stringify(j) shows that it is indeed formatting the body correctly.
Turns out the fetch() API was sending an OPTIONS preflight request, to see the CORS configuration on the server. Removing the headers in my fetch() request stopped this from happening.
I solved this by changing
<input type="submit" onSubmit={()=>{}}/>
to
<button type="button" onClick={this.someFunction}>Submit</button>
Don't know why, but while using ReactJS developed app in Firefox, this has always worked for me. Without this, the browser simply did not fire the POST request(could not see it in the Developer Options:Network Tab).
Using this remedy, it just worked without doing any other change, started seeing the POST requests.
I'm developing an authentication website that authenticate data from a web service. My website is running locally and the web service is running on different domain ex: test.abc.com. if authentication is success then store the response in cookies.
if the data is available in cookies and not expired then in the second call do not ask for authentication but need to validate the user from back end. For that i am using below code.
$.ajax({
url:"https://test.abc.com/test/DummyTest",
method:"GET",
dataType:"json",
beforeSend: function(xhr){
xhr.withCredentials = true;
},
success:function(data){
alert(Success);
},
error:function(xhr,err){
alert("Error");
});
I am using jquery1.6
I have checked the browser Options and the cookies are stored with my localhost ip(160.225.230.50) address. but the web service is in different domain(abc.com). while accessing the second time, I got Error response.
Please help out me on this.
For this to work your auth page should send Access-Control-Allow-Origin and Access-Control-Allow-Credentials headers.
When using Access-Control-Allow-Credentials: true you cannot set Access-Control-Allow-Origin to wildcard, but need to specify origin: Access-Control-Allow-Origin: https://abc.com
Also, there is a simpler way to set xhr fields:
$.ajax({
xhrFields: {
withCredentials: true
},
type: 'POST',
url: ...
});
When I have this code
$.ajax({
type: 'POST',
//contentType: "application/json",
url: 'http://localhost:16329/Hello',
data: { name: 'norm' },
dataType: 'json'
});
in Fiddler I can see following raw request
POST http://localhost:16329/Hello HTTP/1.1
Host: localhost:16329
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://localhost:14693/WebSite1/index.html
Content-Length: 9
Origin: http://localhost:14693
Pragma: no-cache
Cache-Control: no-cache
name=norm
But what I'm trying is to set content-type from application/x-www-form-urlencoded to application/json. But this code
$.ajax({
type: "POST",
contentType: "application/json",
url: 'http://localhost:16329/Hello',
data: { name: 'norm' },
dataType: "json"
});
Generates strange request (which I can see in Fiddler)
OPTIONS http://localhost:16329/Hello HTTP/1.1
Host: localhost:16329
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Origin: http://localhost:14693
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Pragma: no-cache
Cache-Control: no-cache
Why is that? What is OPTIONS when it should be POST there? And where is my content-type set to application/json? And request parameters has gone for some reason.
UPDATE 1
On server side I have really simple RESTful service.
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class RestfulService : IRestfulService
{
[WebInvoke(
Method = "POST",
UriTemplate = "Hello",
ResponseFormat = WebMessageFormat.Json)]
public string HelloWorld(string name)
{
return "hello, " + name;
}
}
But for some reason I can't call this method with parameters.
UPDATE 2
Sorry for not answering so long.
I've added these headers to my server response
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: POST, GET, OPTIONS
It didn't help, I have Method not allowed error from server.
Here is what my fiddler says
So, now I can be sure that my server accepts POST, GET, OPTIONS (if response headers work like I expect). But why "Method not allowed"?
In WebView response from server (you can see Raw response on picture above) looks like this
It would seem that removing http:// from the URL option ensures the the correct HTTP POST header is sent.
I don't think you need to fully qualify the name of the host, just use a relative URL as below.
$.ajax({
type: "POST",
contentType: "application/json",
url: '/Hello',
data: { name: 'norm' },
dataType: "json"
});
An example of mine that works:
$.ajax({
type: "POST",
url: siteRoot + "api/SpaceGame/AddPlayer",
async: false,
data: JSON.stringify({ Name: playersShip.name, Credits: playersShip.credits }),
contentType: "application/json",
complete: function (data) {
console.log(data);
wait = false;
}
});
Possibly related:
jQuery $.ajax(), $.post sending "OPTIONS" as REQUEST_METHOD in Firefox
After some more research I found out the OPTIONS header is used to find out if the request from the originating domain is allowed. Using fiddler, I added the following to the response headers from my server.
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: POST, GET, OPTIONS
Once the browser received this response it then sent off the correct POST request with JSON data. It would seem that the default form-urlencoded content type is considered safe and so does not undergo the extra cross domain checks.
It looks like you will need to add the previously mentioned headers to your servers response to the OPTIONS request. You should of course configure them to allow requests from specific domains rather then all.
I used the following jQuery to test this.
$.ajax({
type: "POST",
url: "http://myDomain.example/path/AddPlayer",
data: JSON.stringify({
Name: "Test",
Credits: 0
}),
//contentType: "application/json",
dataType: 'json',
complete: function(data) {
$("content").html(data);
}
});
References:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
http://enable-cors.org/
https://developer.mozilla.org/en/http_access_control
I can show you how I used it
function GetDenierValue() {
var denierid = $("#productDenierid").val() == '' ? 0 : $("#productDenierid").val();
var param = { 'productDenierid': denierid };
$.ajax({
url: "/Admin/ProductComposition/GetDenierValue",
dataType: "json",
contentType: "application/json;charset=utf-8",
type: "POST",
data: JSON.stringify(param),
success: function (msg) {
if (msg != null) {
return msg.URL;
}
}
});
}
So all you need to do for this to work is add:
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
as a field to your post request and it'll work.
I recognized those screens, I'm using CodeFluentEntities, and I've got solution that worked for me as well.
I'm using that construction:
$.ajax({
url: path,
type: "POST",
contentType: "text/plain",
data: {"some":"some"}
}
as you can see, if I use
contentType: "",
or
contentType: "text/plain", //chrome
Everything works fine.
I'm not 100% sure that it's all that you need, cause I've also changed headers.
If you use this:
contentType: "application/json"
AJAX won't sent GET or POST params to the server.... don't know why.
It took me hours to lear it today.
Just Use:
$.ajax(
{ url : 'http://blabla.example/wsGetReport.php',
data : myFormData, type : 'POST', dataType : 'json',
// contentType: "application/json",
success : function(wsQuery) { }
}
)
I found the solution for this problem here. Don't forget to allow verb OPTIONS on IIS app service handler.
Works fine. Thank you André Pedroso. :-)
I was fighting this same issue and it was caused by a lack of JSON.stringfy() i.e.
data: JSON.stringfy({ name: 'norm' }),
Hope this saves someone else a lot of time!
I had the same issue. I'm running a java rest app on a jboss server. But I think the solution is similar on an ASP .NET webapp.
Firefox makes a pre call to your server / rest url to check which options are allowed. That is the "OPTIONS" request which your server doesn't reply to accordingly. If this OPTIONS call is replied correct a second call is performed which is the actual "POST" request with json content.
This only happens when performing a cross-domain call. In your case calling 'http://localhost:16329/Hello' instead of calling a url path under the same domain '/Hello'
If you intend to make a cross domain call you have to enhance your rest service class with an annotated method the supports a "OPTIONS" http request. This is the according java implementation:
#Path("/rest")
public class RestfulService {
#POST
#Path("/Hello")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.TEXT_PLAIN)
public string HelloWorld(string name)
{
return "hello, " + name;
}
//THIS NEEDS TO BE ADDED ADDITIONALLY IF MAKING CROSS-DOMAIN CALLS
#OPTIONS
#Path("/Hello")
#Produces(MediaType.TEXT_PLAIN+ ";charset=utf-8")
public Response checkOptions(){
return Response.status(200)
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Headers", "Content-Type")
.header("Access-Control-Allow-Methods", "POST, OPTIONS") //CAN BE ENHANCED WITH OTHER HTTP CALL METHODS
.build();
}
}
So I guess in .NET you have to add an additional method annotated with
[WebInvoke(
Method = "OPTIONS",
UriTemplate = "Hello",
ResponseFormat = WebMessageFormat.)]
where the following headers are set
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Headers", "Content-Type")
.header("Access-Control-Allow-Methods", "POST, OPTIONS")
I got the solution to send the JSON data by POST request through jquery ajax. I used below code
var data = new Object();
data.p_clientId = 4;
data = JSON.stringify(data);
$.ajax({
method: "POST",
url: "http://192.168.1.141:8090/api/Client_Add",
data: data,
headers: {
'Accept': 'application/json',
'Content-Type': 'text/plain'
}
})
.done(function( msg ) {
alert( "Data Saved: " + msg );
});
});
});
I used 'Content-Type': 'text/plain' in header to send the raw json data.
Because if we use Content-Type: 'application/json' the request methods converted to OPTION, but using Content-Type: 'test/plain' the method does not get converted and remain as POST.
Hopefully this will help some one.
Hi These two lines worked for me.
contentType:"application/json; charset=utf-8",
dataType:"json"
$.ajax({
type: "POST",
url: "/v1/candidates",
data: obj,
**contentType:"application/json; charset=utf-8",
dataType:"json",**
success: function (data) {
table.row.add([
data.name, data.title
]).draw(false);
}
Thanks,
Prashant
In the jQuery.ajax documentation, contentType specifies the type of content to send to the server. The default value is "application/x-www-form-urlencoded; charset=UTF-8".
For cross-domain requests, if a content type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain is set, the OPTIONS method will be sent in the request header. It is a check that ajax does by the CORS policies to check if the methods that you request to the server (in this case POST) in your domain, are allowed
If the OPTIONS method on your server where the API is hosted is allowed, the request you made to the server initially is made, in this case the POST is sent.
If you are making the request to the same domain and same port, the OPTIONS method is not sent. If this is the case, one of the solutions is to use "http://localhost:<port>..." or just use relative paths where you are going to make the request.
But if the REST API in your backend is in another domain, so there are two solutions.
Do not put in ajax contentType: "application/json", and send the data either in JSON format as an Object or as a string, or a string with the parameters to send type key=value.
Enable CORS in your Rest API (that is, allow OPTIONS, POST methods, for any domain, or your domain where you make the request).
The problem is that in some cases it is necessary to set the type of content to send as "application/json", because the server where the API is hosted does not accept other types of content.
If you have control over the BackEnd and the REST API, I recommend enabling CORS on it. (Also applies if it is the same domain but different port).
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: POST, GET, OPTIONS
Or also allow other types of content like application/x-www-form-urlencoded or encode it in such a way that it also accepts strings with key=value parameters. This prevents jQuery from sending OPTIONS in its request header.
One last thing: if contentType: "application/json" is used and the server expects "application/json" as well, you should use JSON.stringify() on data, since when sending the request to the server, it seems to take the JSON as a string and not as an object. In my case, not using JSON.stringify() and using contentType: "application/json", returned me a server error with status 500