Запрос JS Ajax вызывает ошибку на локальном хосте, но не на веб-сервере - PullRequest
1 голос
/ 27 марта 2019

Резюме

При использовании идентичного кода (на основном сайте asp.net) в разных браузерах при просмотре страницы IIS на локальном хосте XMLHttpRequest обнаруживает какую-то ошибку и вызывает ее событие ошибки и устанавливает статус равным нулю, несмотря на наличие успешно прочитал данные (сеть показывает 200 OK) и сохранил их в responseText.

На производственном / промежуточном веб-сервере код всегда работает нормально.

Файлы открытого текста, по-видимому, по какой-то причине работают нормально и локально (строго говоря, они обрабатываются более ранним промежуточным программным обеспечением), но сгенерированный контент (HTML и JSON) с обычными заголовками выдает ошибку.

У меня вопрос: почему он выдает эту ошибку сейчас, а не раньше?

Ответ ниже ...

Полное оригинальное сообщение

Еще совсем недавно (2-3 дня назад) вызовы AJAX с использованием $ .get () jQuery работали нормально на моей машине для разработки и в промежуточных / производственных средах.

Со вчерашнего дня (когда я заметил) вызовы AJAX теперь не работают на локальной версии сайта и работают нормально на рабочей версии.

Я пробовал в Firefox, Edge и Opera - у всех был одинаковый результат. Я сгенерировал наиболее урезанный код, который мог и все еще могу выдать тот же результат ошибки - который почти полностью исключает мой код.

Я проверил примечания к выпуску Firefox и Edge и не смог найти ничего подходящего для меня.

Локальный хост использует самозаверяющий тестовый сертификат, который имеет исключение в Firefox. Промежуточный сайт имеет настоящий сертификат, подписанный третьей стороной.

Полный код страницы:

<html>
  <head>
    <style>@media print {#ghostery-purple-box {display:none !important}}</style>
  </head>
  <body>
    <h1>hi</h1>
    <script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
  </body>
</html>

Затем я запускаю этот javascript в окне консоли каждого браузера:

$.ajax({url:'/Test',error:function(a,b,c){alert(b)}, success:function(a){alert(a);}});

простите за форматирование, единственная строка была для более простого копирования / вставки и тестирования.

вывод в каждой конфигурации, о которой я могу думать, это то, что часть alert(b) запускается, а b равняется «ошибке».

Единственным отличием в двух конфигурациях является URL:

https://localhost:44300/Test

против

https://[productionfqdn]:444/Test

И заголовки обратно от веб-серверов, локально это IIS Express и удаленно это IIS - оба поддержаны Kestrel как часть сайта ASP.NET Core - хотя я исключил что-либо из этого как возможную часть проблема (я не буду вдаваться в подробности перехода к предыдущей версии кода, пока не понял, что это не имеет ничего общего с моей базой кода).

IIS Express: (dev)

HTTP/2.0 200 OK
content-type: text/html; charset=utf-8
server: Kestrel
x-sourcefiles: [redacted]
x-powered-by: ASP.NET
date: Tue, 26 Mar 2019 23:05:06 GMT
X-Firefox-Spdy: h2

IIS: (постановка)

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
Server: Kestrel
Strict-Transport-Security: max-age=2592000
Date: Tue, 26 Mar 2019 23:04:47 GMT

Результат вызовов на локальный сайт успешен, в devtools в FireFox я вижу, что ожидаемые данные были возвращены, в этом случае те же данные, которые были получены из / Test для запуска теста в первом место.

В результате тех же вызовов на промежуточном сайте выдается предупреждение с текстом html, как указано выше.

Я ожидаю, что эти две среды приведут к одному и тому же результату, а именно к получению html-текста.

Есть идеи? Я сбит с толку!

Редактировать 2019-03-28 Я попытался из контекста той же страницы сделать то же самое с ванильным XMLHttpRquest и получил следующее:

var x = new XMLHttpRequest();
undefined
x.open('GET', '/Test')
undefined
x.send(null)
undefined
x
XMLHttpRequest { onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, responseURL: "", status: 0, statusText: "", responseType: "",
response: "<h1>hi</h1>\r\n<script type=\"text/javascript\" src=\"https://code.jquery.com/jquery-3.3.1.min.js\"></script>"

Где можно ясно увидеть ожидаемый ответ от веб-сервера в поле ответа объекта. (разрыв строки для наглядности)

То же самое, прямо как изображение из браузера devtools:

Firefox javascript console

Редактировать 2 2019-03-28

(кроме того, на вкладке сети отображаются данные, возвращающиеся в порядке)

Так как последнее редактирование показало, что jQuery делает что-то глупое, я решил запустить отладчик и посмотреть, что происходит в jQuery. В текущей версии (3.3.1) я сломал строку 9300, то есть после того, как запрос был выполнен и после того, как jQuery оценил его. Я обнаружил, что функция done имеет значения, которые различаются для моего локального (dev) и удаленного (stg) веб-серверов:

Местное

Local web server values

Remote

Remote web server values

Основной смысл в том, что локальная версия jQuery запускается в done() с status = 0, тогда как удаленная версия запускается в done() с status = 200, что имеет смысл.

В обеих версиях поле состояния локальной переменной response равно 'success'. В строке 9247 jQuery оценивает переменную status, переданную в done(), и поскольку 0 не передается, isSuccess устанавливается в false.

Однако сеть показывает:

enter image description here

Я буду продолжать копать, но буду следить за любыми проницательными ответами:)

Редактировать 3

Значит, done() вызывается из строки 9538:

callback = function( type ) {
                    return function() {
                        if ( callback ) {
                            callback = errorCallback = xhr.onload =
                                xhr.onerror = xhr.onabort = xhr.ontimeout =
                                    xhr.onreadystatechange = null;

                            if ( type === "abort" ) {
                                xhr.abort();
                            } else if ( type === "error" ) {

                                // Support: IE <=9 only
                                // On a manual native abort, IE9 throws
                                // errors on any property access that is not readyState
                                if ( typeof xhr.status !== "number" ) {
                                    complete( 0, "error" );
                                } else {
                                    complete(

                                        // File: protocol always yields status 0; see #8605, #14207
                                        xhr.status,
                                        xhr.statusText
                                    );
                                }

Строка перед if ( typeof xhr.status !== "number" ) { проверяет xhr.status, что означает 0, а не фактический код состояния, несмотря на то, что он определенно возвращает 200. Это объясняет, откуда приходит сообщение «ошибка»! В done() проверяется этот код состояния:

isSuccess = status >= 200 && status < 300 || status === 304;

Так откуда взялся этот 0? *

jQuery handling XHR completion

Редактировать 4

В конечном счете, проблема, похоже, в том, что XMLHttpRequest дает мне статус 0 от localhost, и не было до нескольких дней назад. Супер разочарование:

var x = new XMLHttpRequest(); x.open('GET', 'https://localhost:44300/Test'); x.send(null);
undefined
x
XMLHttpRequest { onreadystatechange: null, readyState: 1, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, responseURL: "", 
status: 0, statusText: "", responseType: "", response: "" }

var x = new XMLHttpRequest(); x.open('GET', 'https://127.0.0.1:44300/Test'); x.send(null);
undefined
x
XMLHttpRequest { onreadystatechange: null, readyState: 1, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, responseURL: "", 
status: 0, statusText: "", responseType: "", response: "" }

Редактировать 5

Итак, снова, пытаясь свести его к минимуму, необходимо сделать ошибку. Я немного заглянул в jquery и заметил, что XHR вызывал обратный вызов ошибки JQ (назначенный xhr.onerror), поэтому я сделал то же самое:

var x = new XMLHttpRequest()
XMLHttpRequest { onreadystatechange: null, readyState: 0, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, responseURL: "", status: 0, statusText: "", responseType: "", response: "" }

x.onerror = function () {console.log('error happened')};
function onerror()

x.open('GET','/Test')
undefined
x.send(null)
undefined
error happened
x
XMLHttpRequest { onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, responseURL: "", status: 0, statusText: "", responseType: "", response: "<h1>hi</h1>\r\n<script type=\"text/javascript\" src=\"https://code.jquery.com/jquery-3.3.1.js\"></script>" }

Это привело к тому, что в сообщении было указано «произошла ошибка», поэтому я могу с уверенностью сказать, что это не jQuery, а нечто странное, вызывающее локальную ошибку.

Редактировать 6

Изменил выше, чтобы быть x.onerror = function (e) {console.log('error happened'); console.log(e)};, чтобы выбросить ошибку и получил это:

error
  ​bubbles: false
  ​cancelBubble: false
  ​cancelable: false
  ​composed: false
  ​currentTarget: null
  ​defaultPrevented: false
  ​eventPhase: 0
  ​explicitOriginalTarget: XMLHttpRequest { readyState: 4, timeout: 0, withCredentials: false, … }
​  isTrusted: true
  ​lengthComputable: false
  ​loaded: 0
  ​originalTarget: XMLHttpRequest { readyState: 4, timeout: 0, withCredentials: false, … }
  ​returnValue: true
  ​srcElement: XMLHttpRequest { readyState: 4, timeout: 0, withCredentials: false, … }
  ​target: XMLHttpRequest { readyState: 4, timeout: 0, withCredentials: false, … }
  ​timeStamp: 594573
  ​total: 0
  type: "error"

Который не проливает много света.

Редактировать 7

Изменение моей тестовой страницы, чтобы она была более полной, чтобы я мог лучше тестировать:

<code><script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script type="text/javascript">
    var x = new XMLHttpRequest();
    $(document).ready(function () {
        x.onerror = function (e) { console.log('error happened'); console.log(e); $('#err').text(e); };
        x.onreadystatechange = function () {
            if (x.readyState == 4) {
                $('#test').text(x.responseText);
            }
        };
        //x.open('GET', '/test.txt');
        x.open('GET', '/Search/Server?term=[redacted]');
        x.send(null);
    });
</script>
<h1>hi</h1>

<div style="border: 1px solid black">
    <pre id="test">
 

Когда я спрашиваю /test.txt, он работает нормально, status = 200 без ошибок

Когда я спрашиваю /Test, который представляет собой приведенный выше код, status = 0, возникает ошибка (без полезной информации о том, почему)

Когда я запрашиваю /Search/Server?term=[redacted], который возвращает правильно сформированный json, status = 0, ошибка произведена (без полезной информации)

Заголовки AJAX (рабочие)

HTTP/2.0 304 Not Modified
content-type: text/plain
last-modified: Thu, 28 Mar 2019 06:20:18 GMT
accept-ranges: bytes
etag: "1d4e52e505b3d27"
server: Kestrel
x-sourcefiles: [redacted]
x-powered-by: ASP.NET
date: Thu, 28 Mar 2019 06:47:09 GMT
X-Firefox-Spdy: h2

Заголовки AJAX (не работают)

HTTP/2.0 200 OK
content-type: text/html; charset=utf-8
server: Kestrel
x-sourcefiles: [redacted]
x-powered-by: ASP.NET
date: Thu, 28 Mar 2019 06:46:18 GMT
X-Firefox-Spdy: h2

HTTP/2.0 200 OK
content-type: application/json; charset=utf-8
server: Kestrel
x-sourcefiles: [redacted]
x-powered-by: ASP.NET
date: Thu, 28 Mar 2019 06:37:41 GMT
X-Firefox-Spdy: h2

может ли быть charset в заголовке content-type?!

Возможно, стоит повторить, что все эти вызовы с точным одним и тем же кодом прекрасно работают в производстве / постановке - те же браузеры, та же аутентификация (не то, что она актуальна после того, как это произошло), те же относительные URL-адреса, используемые и т. д. Единственное отличие состоит в том, что prd / stg является IIS и имеет реальный сертификат, а local является IIS express и использует самоподписанный исключение. Это я могу думать.

1 Ответ

0 голосов
/ 29 марта 2019

Оказывается, проблема была в специализированном промежуточном программном обеспечении asp.net, которое проверяет определенное условие и затем позволяет конвейеру продолжить работу.Я предполагаю, что все, что он делал в процессе разработки, вызывало прерывание запроса или его качество, которое мешало его работе.По сути, код проблемы был:

if (env.IsDevelopment())
{
    // Unimportant code here
    await _next(context);
    await Task.CompletedTask; // <<-- this line made it go wrong
}

замена строки проблемы на «возврат» исправила проблему.

if (env.IsDevelopment())
{
    // Unimportant code here
    await _next(context);
    return;
}

В операторе if больше работы, которую нужно пропуститьесли, однако, IsDevelopment() == true я считаю, что я не завершил это промежуточное ПО должным образом в первом блоке здесь.

Почему это привело к качественно другому ответу на XMLHttpRequest, мне не понятно.Я не могу найти ничего, что указывало бы на плохой ответ.

Тот факт, что статические файлы были в порядке через AJAX, указывал на то, что, поскольку это более раннее промежуточное ПО, вероятно, это было мое специальное промежуточное ПО, которое появилось позже в конвейере.в этом была проблема.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...