I've suddenly stared getting a 400 Bad request error in Safari when I POST a form to jQuery AJAX. I think this is strange, because it's been working fine for 2-3 years, and it's still working in Firefox. I'm not sure where to start debugging, can somebody help me?
submitHandler: function()
{
var formElement = document.getElementById("frmBanner");
var bannerfil = new FormData(formElement);
bannerfil.append("gruppe412", $('#gruppe412').val() );
$.ajax(
{
type: "POST",
url: "/modContent/ajax/banner-copy.php?a=frmBanner&type=45",
data: bannerfil,
dataType: "html",
processData: false,
contentType: false,
success: function(data)
{
if( data.length > 10 )
$("#content").html( data );
else
location.href="#modContent/ajax/" + data;
},
error: function (xhr, ajaxOptions, thrownError) { alert(xhr.statusText); }
});
return false;
},
// Do not change code below
errorPlacement : function(error, element) {
error.insertAfter(element.parent());
}
}
Interestingly, I found the same problems on one of my websites just a few hours after your post. I agree with you that this has to be a more recent problem, but I couldn't tell which version of Safari introduced the bug.
Here's what I figured out:
You construct your FormData
object by passing the form to it, which should be perfectly fine. But it seems like Safari has a bug: When you construct the FormData object by passing a form with an empty file input to it, the request breaks for some reason.
Work-Around:
Instead of doing var bannerfil = new FormData(formElement);
to initialize my FormData
, I'm now initializing an empty FormData object and add the values manually. Before adding a file input, I check whether it actually has any files attached.
formData = new FormData();
var $form = $(this); // <- change this depending on your scope/usecase
// [type="file"] will be handled separately
$form.find('input[name][type!="file"], select[name], textarea[name]').each(function(i, e) {
if ($(e).attr('type') == 'checkbox' || $(e).attr('type') == 'radio') {
if ($(e).is(':checked')) {
formData.append($(e).attr('name'), $(e).val());
}
} else {
formData.append($(e).attr('name'), $(e).val());
}
});
$form.find('input[name][type="file"]').each(function(i, e) {
if ($(e)[0].files.length > 0) {
formData.append($(e).attr('name'), $(e)[0].files[0]);
}
});
Edit for clarification: In your specific case, something like this should make it work:
submitHandler: function() {
var formElement = $("frmBanner");
var bannerfil = new FormData();
// [type="file"] will be handled separately
formElement.find('input[name][type!="file"], select[name], textarea[name]').each(function(i, e) {
if ($(e).attr('type') == 'checkbox' || $(e).attr('type') == 'radio') {
if ($(e).is(':checked')) {
bannerfil.append($(e).attr('name'), $(e).val());
}
} else {
bannerfil.append($(e).attr('name'), $(e).val());
}
});
formElement.find('input[name][type="file"]').each(function(i, e) {
if ($(e)[0].files.length > 0) {
bannerfil.append($(e).attr('name'), $(e)[0].files[0]);
}
});
bannerfil.append("gruppe412", $('#gruppe412').val() );
$.ajax({
type: "POST",
url: "/modContent/ajax/banner-copy.php?a=frmBanner&type=45",
data: bannerfil,
dataType: "html",
processData: false,
contentType: false,
success: function(data) {
if( data.length > 10 )
$("#content").html( data );
else
location.href="#modContent/ajax/" + data;
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.statusText);
}
});
return false;
},
// Do not change code below
errorPlacement : function(error, element) {
error.insertAfter(element.parent());
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With