jQuery PUT ajax request not working - javascript

I'm trying to save a Backbone model in couchdb so I've overridden the save method with a ajax requet to couchdb:
$.ajax({
type: 'PUT',
url: 'http://127.0.0.1:5984/movies/' + this.get('id'),
contentType: 'application/json',
data: JSON.stringify(this.toJSON()),
success: function() {
console.log('asdf');
},
failure: function() {
console.log('test');
}
});
The request is sent but when I look at the couchdb log jQuery seems to send a OPTIONS HTTP method instead of PUT:
[info] [<0.1601.0>] 127.0.0.1 - -
'OPTIONS' /movies/862 405
and couchdb sends a 405 HTTP Response code (method not allowed). Any Ideas?
Edit
Here are the headers sent to CouchDB:
OPTIONS /movies/862 HTTP/1.1
Host: 127.0.0.1:5984
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Origin: http://localhost:8888
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: content-type

There's a backbone connector for couch-db.. https://github.com/janmonschke/backbone-couchdb

PUT isn't supported by all browsers. Also, the property for your data is "data", not "body".

Related

AJAX request returning "405 Method Not Allowed"

I'm trying to write a submit form that sends a JSON object to an application on another server but I keep getting a 405 Method Not Allowed error in the console.
The app is set up to accept POST and that's what I'm sending so I'm lost at where the error is. There is also a warning in the console Loading failed for the <script> with source "Request URL"
Is this a problem with the way the application is reading the JSON or the format the JSON is being sent in?
From the app server
Failed to execute: javax.ws.rs.NotSupportedException: RESTEASY003065: Cannot consume content type
Code
json = JSON.parse(string);
$.ajax({
type: 'POST',
dataType: "jsonp",
contentType: "application/json",
url: "http://test:8080/request/committee",
data: json,
cache: false,
success: function (response) {
$("#successModal").modal('show');
},
failure: function (response) {
$("#failureModal").modal('show');
},
error: function (response) {
$("#failureModal").modal('show');
}
});
e.preventDefault();//prevents the form from being submitted by default
Request Headers
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.5
Connection: keep-alive
Host: test:8080
Referer: http://www.form.com/servlet/rsvp.jsp?location=110%20Road%20Bolton%20Landing,%20NY&purpose=%20TPAS%20Teleconference%20(RSVP%20here%20to%20attend%20in-person)&visitDate=2018-03-15&visitStartTime=6:00%20AM&visitEndDate=7:00%20AM&committee=all
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0
Response Headers
HTTP/1.1 405 Method Not Allowed
Allow: POST, OPTIONS
Connection: keep-alive
Content-Length: 0
Date: Mon, 16 Apr 2018 15:38:24 GMT
Edit: corrected contentType. Same error occurs
From your exception details , it seems to be
Failed to execute: javax.ws.rs.NotSupportedException: RESTEASY003065: Cannot consume content type
either you are passing invalid content type or not passing at all , I see your content type is application/jsonp.
just give a try with application/javascript.
This error happened to me once. My java method wanted xml not json. this annotation (in java) fixed it for me.
#Consumes(MediaType.APPLICATION_JSON)
I hope this helps!

Failed to load JSON file using JQuery [duplicate]

The AJAX request works fine, but the moment I add a header via beforeSend or headers, an OPTIONS pre-flight request is made and the GET request is aborted.
Code: $.ajax({
type: "GET",
crossDomain: true,
beforeSend: function (xhr)
{
xhr.setRequestHeader("session", $auth);
},
url: $url,
success: function (data) {
$('#something').html(data);
},
error: function (request, error) {
$('#something').html("<p>Error getting values</p>");
}
});
Similar AJAX Request w/o headers specified (the moment I add/modify header, an OPTIONS call is made)
Request GET /api/something?filter=1 HTTP/1.1
Referer http://app.xyz.dj/dashboard
Accept application/json, text/javascript, */*; q=0.01
Accept-Language en-US
Origin http://app.xyz.dj
Accept-Encoding gzip, deflate
User-Agent Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; MASMJS; rv:11.0) like Gecko
Host 162.243.13.172:8080
DNT 1
Connection Keep-Alive
Cache-Control no-cache
Similar Server Response Header (for GET request)
Response HTTP/1.1 200 OK
Server Apache-Coyote/1.1
Access-Control-Allow-Origin *
Access-Control-Allow-Methods GET, POST, DELETE, PUT, OPTIONS, HEAD
Access-Control-Allow-Headers Content-Type, Accept, X-Requested-With
Access-Control-Allow-Credentials true
Content-Type application/json
Transfer-Encoding chunked
Date Thu, 09 Jan 2014 14:43:07 GMT
What I am doing wrong?
Solved.
Thanks #JasonP for pointers. Changed Server Response Headers from
Access-Control-Allow-Headers:*
to specific ones
Access-Control-Allow-Headers: Content-Type, Accept, X-Requested-With, Session
and now it works!

In PhoneGap App, AJAX call error event gets triggered even the server returns 200 OK status

I am using the below Ajax call to connect with Spring security from crossdomain (PhoneGap). The response I got is 200 OK - it has the expected response in JSON format. But the error event is getting fired due to CORS. On the Spring side, I have added a CORS filter to allow any type of URL (Access-Control-Allow-Origin = ' * ').
$.ajax({
type:'POST',
url: CONTEXTPATH + '/j_spring_security_check',
data: formData,
dataType: 'text json',
cache: false,
crossdomain: false,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-Requested-With' : 'XMLHttpRequest',
},
success: function(data) {
},
error: function(data) {
}
});
The response in the browser console is:
POST XHR http://192.168.0.20:8080/startupbay/j_spring_security_check [HTTP/1.1 200 OK 260ms] Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://192.168.0.20:8080/startupbay/j_spring_security_check. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
The request and response headers are:
RESPONSE HEADER:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Content-Type, x-requested-with, Origin, Accept
Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS, PATCH, HEAD
Access-Control-Allow-Origin:*
Access-Control-Max-Age:86400
Access-Control-Request-Headers:x-requested-with
Cache-Control:no-cache, no-store, max-age=0, must-revalidate
Content-Length:0
Date: Thu, 23 Feb 2017 06:14:39 GMT
Expires:0
Pragma:no-cache
Server:Apache-Coyote/1.1
X-Content-Type-Options:nosniff
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block
REQUEST HEADER:
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.5
Access-Control-Request-Headers:x-requested-with
Access-Control-Request-Method:POST
Connection:keep-alive
Host:192.168.0.20:8080
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0
origin:http://192.168.0.20:3000
In the Error section, I looked for the error mentioned in 'xhr'. The statusText:error, responseText:'', status:0.
Please help me in resolving this issue.
When I set the crossdomain:true, that time in the browser console I can see only the OPTIONS request, but not followed by the POST request.
Just to add, this issue is appearing only for the '/j_spring_security_check' URL. For another URL, the same type setup is working fine.

jQuery & CORS always fail on an open remote server

I'm trying to simulate a POST, with jQuery $.ajax() method, on a remote server which is supposed to have CORS enabled.
The idea is to submit a form with username/password provided and get the cookie delivered by the server from a successful authentication.
Here is the jQuery:
$.ajax({
type: 'POST',
crossDomain: true,
async: false,
url: this.url,
data: {
username: this.username,
password: this.password
},
xhrFields: {
withCreditentials: true
},
success: function(responseData, textStatus, jqXHR) {
console.info(jqXHR.getAllResponseHeaders());
},
error: function(responseData, textStatus, errorThrown) {
console.warn(errorThrown);
}
});
Here is the response headers:
HTTP/1.1 200 OK
Connection: close
Content-Type: text/html
Pragma: no-cache
Cache-control: no-cache,max-age=0,must-revalidate
Content-Encoding: gzip
Vary: Accept-Encoding
Transfer-Encoding: chunked
And the request headers:
Accept: * / *
Accept-Encoding: gzip, deflate, sdch
Accept-Language: fr,en-US;q=0.8,en;q=0.6
Cache-Control: max-age=0
Connection: keep-alive
Host: my remote server (URL is hidden)
The problem is that I get a console.warn telling me:
Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'URL'
I also tried with a Chrome extension which simulate a POST: I put the same data as in my jQuery and everything succeed, from the call to the cookie delivered once the form is submitted.
I don't understand how my jQuery fails to load the URL but is giving me a 200 OK anyway! And I don't understand how to make it right!
Where I'm doing a mistake?
It would appear that you need to add the Access-Control-Allow-Origin: * header to the api response header. Your REST client (the chrome extension) doesn't abide by CORS rules like the browser, which is why it works.

Adding a custom header to HTTP request using angular.js

I am a novice to angular.js, and I am trying to add some headers to a request:
var config = {headers: {
'Authorization': 'Basic d2VudHdvcnRobWFuOkNoYW5nZV9tZQ==',
'Accept': 'application/json;odata=verbose'
}
};
$http.get('https://www.example.com/ApplicationData.svc/Malls(1)/Retailers', config).success(successCallback).error(errorCallback);
I've looked at all the documentation, and this seems to me like it should be correct.
When I use a local file for the URL in the $http.get, I see the following HTTP request on the network tab in Chrome:
GET /app/data/offers.json HTTP/1.1
Host: www.example.com
Connection: keep-alive
Cache-Control: max-age=0
If-None-Match: "0f0abc9026855b5938797878a03e6889"
Authorization: Basic Y2hhZHN0b25lbWFuOkNoYW5nZV9tZQ==
Accept: application/json;odata=verbose
X-Requested-With: XMLHttpRequest
If-Modified-Since: Sun, 24 Mar 2013 15:58:55 GMT
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22
X-Testing: Testing
Referer: http://www.example.com/app/index.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
As you can see, both of the headers were added correctly. But when I change the URL to the one shown in the $http.get above (except using the real address, not example.com), then I get:
OPTIONS /ApplicationData.svc/Malls(1) HTTP/1.1
Host: www.datahost.net
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://mpon.site44.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22
Access-Control-Request-Headers: accept, origin, x-requested-with, authorization, x-testing
Accept: */*
Referer: http://mpon.site44.com/app/index.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
The only difference in code between these two is one is for the first the URL is a local file, and for the second the URL is a remote server. If you look at the second Request header, there is no Authentication header, and the Accept appears to be using a default instead of the one specified. Also, the first line now says OPTIONS instead of GET (although Access-Control-Request-Method is GET).
Any idea what is wrong with the above code, or how to get the additional headers included using when not using a local file as a data source?
I took what you had, and added another X-Testing header
var config = {headers: {
'Authorization': 'Basic d2VudHdvcnRobWFuOkNoYW5nZV9tZQ==',
'Accept': 'application/json;odata=verbose',
"X-Testing" : "testing"
}
};
$http.get("/test", config);
And in the Chrome network tab, I see them being sent.
GET /test HTTP/1.1
Host: localhost:3000
Connection: keep-alive
Accept: application/json;odata=verbose
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22
Authorization: Basic d2VudHdvcnRobWFuOkNoYW5nZV9tZQ==
X-Testing: testing
Referer: http://localhost:3000/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Are you not seeing them from the browser, or on the server? Try the browser tooling or a debug proxy and see what is being sent out.
Basic authentication using HTTP POST method:
$http({
method: 'POST',
url: '/API/authenticate',
data: 'username=' + username + '&password=' + password + '&email=' + email,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"X-Login-Ajax-call": 'true'
}
}).then(function(response) {
if (response.data == 'ok') {
// success
} else {
// failed
}
});
...and GET method call with header:
$http({
method: 'GET',
url: '/books',
headers: {
'Authorization': 'Basic d2VudHdvcnRobWFuOkNoYW5nZV9tZQ==',
'Accept': 'application/json',
"X-Login-Ajax-call": 'true'
}
}).then(function(response) {
if (response.data == 'ok') {
// success
} else {
// failed
}
});
If you want to add your custom headers to ALL requests, you can change the defaults on $httpProvider to always add this header…
app.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.headers.common = {
'Authorization': 'Basic d2VudHdvcnRobWFuOkNoYW5nZV9tZQ==',
'Accept': 'application/json;odata=verbose'
};
}]);
my suggestion will be add a function call settings like this
inside the function check the header which is appropriate for it. I am sure it will definitely work. it is perfectly working for me.
function getSettings(requestData) {
return {
url: requestData.url,
dataType: requestData.dataType || "json",
data: requestData.data || {},
headers: requestData.headers || {
"accept": "application/json; charset=utf-8",
'Authorization': 'Bearer ' + requestData.token
},
async: requestData.async || "false",
cache: requestData.cache || "false",
success: requestData.success || {},
error: requestData.error || {},
complete: requestData.complete || {},
fail: requestData.fail || {}
};
}
then call your data like this
var requestData = {
url: 'API end point',
data: Your Request Data,
token: Your Token
};
var settings = getSettings(requestData);
settings.method = "POST"; //("Your request type")
return $http(settings);
What you see for OPTIONS request is fine. Authorisation headers are not exposed in it.
But in order for basic auth to work you need to add: withCredentials = true; to your var config.
From the AngularJS $http documentation:
withCredentials - {boolean} - whether to to set the withCredentials
flag on the XHR object. See requests with credentials for more
information.
And what's the answer from the server? It should reply a 204 and then really send the GET you are requesting.
In the OPTIONS the client is checking if the server allows CORS requests. If it gives you something different than a 204 then you should configure your server to send the correct Allow-Origin headers.
The way you are adding headers is the right way to do it.
Chrome is preflighting the request to look for CORS headers. If the request is acceptable, it will then send the real request. If you're doing this cross-domain, you will simply have to deal with it or else find a way to make the request non-cross-domain. This is by design.
Unlike simple requests (discussed above), "preflighted" requests first
send an HTTP request by the OPTIONS method to the resource on the
other domain, in order to determine whether the actual request is safe
to send. Cross-site requests are preflighted like this since they may
have implications to user data. In particular, a request is
preflighted if:
It uses methods other than GET, HEAD or POST. Also, if POST is used to
send request data with a Content-Type other than
application/x-www-form-urlencoded, multipart/form-data, or text/plain,
e.g. if the POST request sends an XML payload to the server using
application/xml or text/xml, then the request is preflighted. It sets
custom headers in the request (e.g. the request uses a header such as
X-PINGOTHER)
Ref: AJAX in Chrome sending OPTIONS instead of GET/POST/PUT/DELETE?
You are just adding a header which server does not allow.
eg - your server is set up CORS to allow these headers only (accept,cache-control,pragma,content-type,origin)
and in your http request you are adding like this
headers: {
'Authorization': 'Basic d2VudHdvcnRobWFuOkNoYW5nZV9tZQ==',
'Accept': 'application/json',
'x-testing': 'testingValue'
}
then the Server will reject this request since (Authorization and x-testing) are not allowed.
This is server side configuration.
And there is nothing to do with HTTP Options, it is just a preflight to server which is from different domain to check if server will allow actual call or not.
For me the following explanatory snippet worked. Perhaps you shouldn't use ' for header name?
{
headers: {
Authorization: "Basic " + getAuthDigest(),
Accept: "text/plain"
}
}
I'm using $http.ajax(), though I wouldn't expect that to be a game changer.

Categories