How to detect if browser supports PUT/DELETE verbs? [duplicate] - javascript

Is there a way to see if a client browser supports PUT or SEARCH methods for usage with JQuery & AJAX requests?
HTML5 PUT/DELETE methods not working in Chrome?
Are the PUT, DELETE, HEAD, etc methods available in most web browsers?
I have the following code, and PUT does not appear on the server side for me in Chromium and Chrome ... I'd like to know, if PUT isn't supported by the browser, how to change it to a POST request ... for backwards compatibility
function do_data(url, action, query) {
try {
if ($.browser.msie) {
var xdr = new XDomainRequest();
if (query !== null) {
console.log(query);
xdr.open(action, url + '?' + $.param(query));
} else {
xdr.open(action, url);
}
xdr.onload = function() {
var data = $.parseJSON(this.responseText);
show_data(data);
};
xdr.send();
} else {
if (query !== null) {
$.ajax({
url: url,
data: query,
type: action,
success: function(data) {
console.log(data);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(textStatus);
}
});
} else {
console.log(query);
$.ajax({
url: url,
type: action,
success: function(msg) {
console.log(data);
}
});
}
}
} catch (e) {}
}
Using the above code, if I use "PUT" on Chromium / Chrome, error: function(jqXHR, textStatus, errorThrown) will print out simply error.
On the server side, I see the REQUEST_METHOD: OPTIONS and not PUT.
Just to confirm, for anyone who comes across this ... there isn't a programmatic way

The common way of handling the lack of PUT and DELETE support in most browsers is to use HTTP POST tunneling. Basically you use a POST and add the real VERB to a X-HTTP-Method-Override HTTP header. On the service you check for the latter, if not found use the normal HTTP method.
See here for more info.

Related

jQuery.GET intermittent failure in Safari in ipad

I have the following utility function which I use as a standard way of adding headers to an HTTP GET request.
const get1 = function(url, callback) {
console.log("in get1 with url : " + url);
return new Promise(function(resolve, reject) {
firebase.auth().currentUser.getIdToken()
.then(function(idToken) {
return {
'Authorization': 'Bearer ' + idToken,
'ACTING_ON_BEHALF_OF': ns.actingAs
};
})
.then(function(headers) {
resolve($.get({
url: url,
headers: headers,
dataType: "json",
error: function(jqXHR, textStatus, errorThrown) {
alert(textStatus);
alert(errorThrown);
alert(jqXHR.responseText);
}
}));
});
});
};
I call it with structures similar to this
const targetUrl = ns.operation + "/" + ns.stage + "/" + ns.category;
utils.get1("/api/gameconfig/v1/oddoneout/" + targetUrl)
.then(function(data) {
console.log("THEN Block")
// blah blah blah
});
This seems to work reliably in all browsers except Safari on iPad where, periodically, the GET request appears to be executed but the .then block never gets entered.
Debugging the javascript seems to indicate that the HTTP request is still executing, but the server side seems to think that it has successfully completed the request and returned a response.
I'm at a loss as to why I see this behaviour. There doesn't seem any pattern to it. Sometimes I can make 50 calls without a problem, sometimes it fails more or less immediately.
Any help will be gratefully received - even if it's hints about how to debug this.
I'm using jQuery 3.3.1 if that makes any difference.

CefSharp - Get result of AJAX request

I am really new to CefSharps Chromium browser and have difficulty figuring out how to get the result of a jquery ajax request.
My first attempt was to pass my AJAX requesto to EvaluateScriptAsync. In fact the script works. It does exactly what I want, but I do not get any results/status codes, because my Cef-Task does not wait until AJAX has completed its work.
Here an example (just a sample code):
var tasks = pdBrowser.EvaluateScriptAsync(#"
(function(){
$.ajax({
type: ""POST"",
dataType: ""json"",
cache: false,
url: ""_resources/php/ajaxRequests.php"",
async: false,
data: {
action: ""insertCrossPlatform"",
type: """",
values: JSON.stringify(""foo bar"")
},
success: function(response) {
if (typeof response === 'string' && response.substring(0, 5) == ""ERROR"")
{
return response;
}
else
{
//pageReload();
return ""OK"";
}
},
error: function(xhr, textStatus, errorThrown) {
return errorThrown + ""\n"" + xhr.responseText;
},
complete: function() {
return ""COMPLETE"";
}
});
})();", null);
tasks.ContinueWith(t =>
{
if (!t.IsFaulted)
{
var response = t.Result;
if (response.Success)
{
if (response.Result != null)
{
MessageBox.Show(response.Result.ToString());
}
}
else
{
MessageBox.Show(response.Message, "Ein Fehler ist aufgetreten", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
}, TaskScheduler.Default);
Afterwards I have read that there is a SchemeHandler, but I do not properly understand how to implement it. Can anyone help me out?
Thanks in advance.
Firstly SchemeHandler is unlikely to be suitable in this scenario, you would typically implement a SchemeHandler when your providing the response.
Most people choose to bind an object, and call a method on their bound object when they wish to communicate with the parent application. See the FAQ for an example. https://github.com/cefsharp/CefSharp/wiki/Frequently-asked-questions#3-how-do-you-expose-a-net-class-to-javascript
With 49.0.0 you can implement ResponseFilter to gain access to the underlying response buffer, it's complex and not well documented, so if your not comfortable digging through reference C++ code then this option isn't for you. Here's a reference https://github.com/cefsharp/CefSharp/blob/cefsharp/49/CefSharp.Example/Filters/PassThruResponseFilter.cs#L17
Something that I did was create an element on the page through javascript with an ID that is the response of the ajax call. So for example, when you make an ajax call assign an ID to the ajax call.
When the ajax call returns, write an element on the page with the pre-assigned id and callback information. Then you can just use cefsharp to read the element content from the page and this will be your callback information.
var myDivElement =document.getElementById('textareaInfo');
if( myDivElement === null)
{
var input = document.createElement('textarea');
input.id = "textareaInfo";
input.value = "Test"
input.rows="4";
input.cols="50";
input.style="height:100%;width:900px;"
var dom = document.getElementsByClassName("page-body")[0];
dom.insertAdjacentElement('afterbegin', input)
}
Then later with ajax
var root = 'https://jsonplaceholder.typicode.com';
var _holder = callbackObj;
callbackObj.showMessage(""ajax"");
$.ajax({
url: root + '/posts/1',
contentType: 'application/json; charset=utf-8',
method: 'GET',
complete: function(data){
},
success: function(response) {
$(#'textareaInfo').value(response);
}
}).then(function(data) {
callbackObj.showMessage(data);
});
Then read the texarea from cefsharp in c#
chromeBrowser.GetMainFrame().EvaluateScriptAsync(function()...$(textareaInfo).value).Result
You can use PostMessage javascript method to notify .NET application:
CefSharp.PostMessage('Your data Here');
Here is .NET code example for headless browser:
var browser = new ChromiumWebBrowser("", null, RequestContext);
browser.JavascriptMessageReceived += (sender, e) =>
{
if ((string)e.Message.notificationid == "notification1")
{
// Your processing code goes here
}
};
browser.Load(destinationUrl);
browser.ExecuteScriptAsync("(function() { ... ; CefSharp.PostMessage({data: data, notificationid: 'notification1'});})()");

how to find which method is causing the error during parallel ajax call

I am using $.when to make parallel ajax call to webapi controller and it works perfectly fine. The structure is given below,
$.when(GetDataFromMethodA(),GetDataFromMethodB(),GetDataFromMethodC())
.done(function (responseFromMethodA,responseFromMethodB, responseFromMethodC) {
if (responseFromMethodA != null) {
//do some action
}
if (responseFromMethodB != null) {
//do some action
}
if (responseFromMethodC != null) {
//do some action
}
}).fail(function (xhr, textStatus, errorThrown) {
//which method raised the exception?
});
Methods:
function GetDataFromMethodA() {
var Request = {};
Request.Code = name.find(':selected').val();
return $.ajax({
url: 'api/Data/GetCurrentView',
type: 'POST',
dataType: 'json',
data: Request
});
}
similarly, I have method B and C.
QUESTION:
There are situations where any one of the method fails and based on the failing method, I need to display appropriate message to the user. When anyone of the method fails, the exception is caught in the 'fail' section. But, how to find which method raised the exception?
If you use always instead of done, you can inspect whether the request succeeded with isResolved() or isRejected(), for instance:
$.when(GetDataFromMethodA(),GetDataFromMethodB(),GetDataFromMethodC())
.always(function (responseFromMethodA,responseFromMethodB, responseFromMethodC) {
if(responseFromMethodA.isRejected()) {
console.log('A did not work!');
}
if(responseFromMethodB.isRejected()) {
console.log('B did not work!');
}
// ...etc.
});

Dealing with Origin http://localhost is not allowed by Access-Control-Allow-Origin Without CORS header

So I've got a simple getJSON() function:
$.getJSON(apiURL, function(data) {
console.log('success');
if (data.results.length > 0) {
$(song).find('source').attr('src', data.results[0].previewUrl);
song.play();
}
else {
console.log('No match found for track information specified.');
}
});
apiURL is an itunes API url, defined like this:
var apiURL =" https://itunes.apple.com/search" +
"?term=" + artist + "+" + album + "+" + title +ยท
"&media=music&entity=musicTrack&callback=?";
I'm getting the classic Origin localhost is not allowed by Access-Control-Allow-Origin error. I've dug for some answers on this, and they usually boil down to either using $.ajax and setting the dataType to 'jsonp', or using .getJSON and supplying a 'callback=?' parameter to the URL, which I've tried above. Neither of those seem to be working, and I've heard rumblings that they may be outdated. What is the most current, up to date advise on dealing with this problem? Besides collecting the data on the server.
You have a space at the beginning of your api url... once I removed that, the call went through:
http://jsfiddle.net/UU8tT/
var apiURL = "https://itunes.apple.com/search" +
Try using the full .ajax method, rather than the .getJSON shorthand method:
var terms = ["Halestorm"];
terms.forEach(function (val, i, arr) {
terms[i] = encodeURIComponent(val);
});
$.ajax({
"url": "https://itunes.apple.com/search",
"dataType": "jsonp",
"data": {
"term": terms.join('+'),
"media": "music",
"entity": "musicTrack"
},
"error": function (jqXHR, textStatus, message) {
console.log(message);
},
"success": function (data, textStatus, jqXHR) {
console.log(data);
}
});
The above works for me in the browser console (while on stackoverflow). It also works on jsFiddle: http://jsfiddle.net/xYthU/
Browser will request server with OPTIONS method. Server has to response following headers to support CORS.
Access-Control-Allow-Headers : Accept
Access-Control-Allow-Methods : *
Access-Control-Allow-Origin : *
If we request https://itunes.apple.com/search URL with OPTIONS method. It responses with error that not Supported.
Screenshot: https://blog.gaurangjadia.com/wp-content/uploads/2013/10/itunes.apple_.com_.png

Save temporary Ajax parameters in jQuery

I am developing a heavily scripted Web application and am now doing some Error handling. But to do that, I need a way to access the AJAX parameters that were given to jQuery for that specific AJAX Request. I haven't found anything on it at jquery.com so I am asking you folks if you have any idea how to accomplish that.
Here is an example of how I want to do that codewise:
function add_recording(filename) {
updateCounter('addRecording','up');
jQuery.ajax({
url: '/cgi-bin/apps/ajax/Storyboard',
type: 'POST',
dataType: 'json',
data: {
sid: sid,
story: story,
screen_id: screen_id,
mode: 'add_record',
file_name: filename
},
success: function(json) {
updateCounter('addRecording','down');
id = json[0].id;
create_record(id, 1, 1, json);
},
error: function() {
updateCounter('addRecording','error',hereBeData);
}
})
}
hereBeData would be the needed data (like the url, type, dataType and the actual data).
updateCounter is a function which updates the Status Area with new info. It's also the area where the User is notified of an Error and where a Dismiss and Retry Button would be generated, based on the Info that was gathered in hereBeData.
Regardless of calling complete() success() or error() - this will equal the object passed to $.ajax() although the values for URL and data will not always be exactly the same - it will convert paramerters and edit the object around a bit. You can add a custom key to the object to remember your stuff though:
$.ajax({
url: '/',
data: {test:'test'},
// we make a little 'extra copy' here in case we need it later in an event
remember: {url:'/', data:{test:'test'}},
error: function() {
alert(this.remember.data.test + ': error');
},
success: function() {
alert(this.remember.data.test + ': success');
},
complete: function() {
alert(this.remember.data.url + ': complete');
}
});
Of course - since you are setting this data originally from some source - you could rely on the variable scoping to keep it around for you:
$("someelement").click(function() {
var theURL = $(this).attr('href');
var theData = { text: $(this).text(); }
$.ajax({
url: theUrl,
data: theData,
error: function() {
alert('There was an error loading '+theURL);
}
});
// but look out for situations like this:
theURL = 'something else';
});
Check out what parameters you can get in the callback for error.
function (XMLHttpRequest, textStatus, errorThrown) {
// typically only one of textStatus or errorThrown
// will have info
this; // the options for this ajax request
}
You can use the ajax complete event which passes you the ajaxOptions that were used for the request. The complete fires for both a successful and failed request.
complete : function (event, XMLHttpRequest, ajaxOptions) {
//store ajaxOptions here
//1 way is to use the .data on the body for example
$('body').data('myLastAjaxRequest', ajaxOptions);
}
You can then retireve the options using
var ajaxOptions = $('body').data('myLastAjaxRequest');

Categories