JQuery Ajax пост-запрос застрял в ожидании на Chrome
У меня есть клиент jQuery, который отправляет Ajax-запрос к Spring Controller. На стороне сервера не было зарегистрировано ни одной ошибки. На стороне клиента запрос задерживается на очень долгое время, минуты, а затем может завершиться с ошибкой либо с ERR_SPDY_PROTOCOL_ERROR, либо с ERR_CONNECTION_CLOSED.
Эта проблема воспроизводима в Chrome, но не в Firefox. Проверенная уязвимая версия - 70.0.3538.77, могут быть и другие. Кроме того, проблема возникает при конкретном развертывании приложения, а не в другом месте, разработке или производстве.
Клиент отправляет запросы HTTPS 2 в этой среде. В среде разработки это HTTP 1.1. На сервере все запросы записываются как 1.1.
Без видимой причины запросы начали проходить, но это повторяющаяся проблема, и мы хотели бы ее решить. Поскольку проблема начала возникать, я не могу воспроизвести ее и проверить, не является ли проблема слишком большим количеством подключений к серверу (более 6). Я использую три DNS-сервера, последний из которых - Google 8.8.8.8.
Я ищу исправление кода или подсказку, может ли это быть связано с настройкой сервера. Я почти уверен, что это комбинация клиентского кода и сетей.
В чем проблема не так:
Что я безуспешно пытался:
Что не отвечает на вопрос:
На стороне клиента я пытался очистить данные браузера, очистить сокеты и приватный просмотр/инкогнито.
Единственное, что иногда, редко, обходит ошибку - это инкогнито, очистка сокетов и очистка кеша из событий chrome://net-internals/#
var formData = new FormData();
formData.append( /* ... */ );
//...
$.ajax({
type: "POST",
url: "/somepath/update",
cache: false,
data: formData,
contentType: false,
processData: false,
success: function(result) {
//...
},
fail: function(result) {
//....
},
error: function( jqXHR, textStatus, errorThrown ){
alert(textStatus + ":" + errorThrown);
}
});
Отдельный запрос с использованием $.post проходил через:
$.post("someotherpath/update", $("#someForm").serialize())
.done(function (data) {
//...
})
.fail(function (data) {
//...
})
.always(function () {
//...
});
Сторона сервера:
@RequestMapping(value="/somepath/update", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public @ResponseBody String update(ModelClass model) {
JSONObject result = new JSONObject();
//...
return result.toString();
}
Если это актуально, существуют следующие фильтры. Боюсь, я не могу опубликовать больше из них в данный момент:
@Configurable
public class Filter1 extends OpenEntityManagerInViewFilter implements Filter{
public void doFilterInternal(HttpServletRequest httpReq, HttpServletResponse httpResp, FilterChain chain)
throws ServletException, IOException {
//...
}
}
@Configurable
public class Filter2 extends OncePerRequestFilter implements Filter{
public void doFilterInternal(HttpServletRequest httpReq, HttpServletResponse httpResp, FilterChain chain)
throws ServletException, IOException {
//...
}
}
@Order(/* very small integer */)
public class Filter3 extends OncePerRequestFilter {
}
Ожидаемый результат состоит в том, что код должен пройти обратный вызов успеха. Вместо этого запрос застревает на ожидании в течение нескольких минут, затем вводится сообщение об ошибке.
Ответы
Ответ 1
$.post
вызывает $.ajax
под прикрытием, просто по умолчанию некоторые из параметров.
$.post
умолчанию contentType
значение "application/x-www-form-urlencoded; charset=UTF-8"
что будет соответствовать вашей полезной нагрузке сериализованных данных формы.
Ваш вызов $.ajax
устанавливает для contentType
значение false
что может привести к тому, что браузер отправит на сервер предварительный запрос OPTIONS перед полетом, что может привести к разнице в поведении, которое вы испытываете.
Я хотел бы предложить прочитать подробности о jQuery.ajax()
и различные варианты поведения, основанные на опциях, переданных здесь.