Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

400 Bad request when posting jQuery ajax in Safari only

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());
}
}
like image 838
johnohod Avatar asked Jan 29 '23 04:01

johnohod


1 Answers

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());
}
like image 137
Alex Avatar answered Jan 31 '23 08:01

Alex