У меня есть два HTTP-запроса, один из которых написан на curl, а другой - на javascript в хроме. Запрос curl работает, а запрос chrome - нет, но я не уверен, почему.

Хром:

PUT /api/Account HTTP/1.1
Host: mydomain.co.nz
Connection: keep-alive
Content-Length: 152
Pragma: no-cache
Cache-Control: no-cache
Authorization: Bearer eyJhb..
Origin: http://localhost:4200
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36
Content-Type: multipart/form-data; boundary=--------------------------33e4cd665cd7a003
Accept: application/json
Referer: http://localhost:4200/conversations
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8

--------------------------33e4cd665cd7a003
Content-Disposition: form-data; name="data"

{"isoncall" : true}
--------------------------33e4cd665cd7a003--

Свернуться :

PUT /api/Account HTTP/1.1
Host: mydomain.co.nz
User-Agent: curl/7.51.0
accept: application/json
authorization: Bearer eyJhbGciO....
cache-control: no-cache
Content-Length: 158
Expect: 100-continue
Content-Type: multipart/form-data; boundary=--------------------
----a8c24af99c272f79

--------------------------a8c24af99c272f79
Content-Disposition: form-data; name="data"

{"isoncall" : true}
--------------------------a8c24af99c272f79--

Ошибка, которую я получаю с хромом:

[{"error": "Неожиданный конец потока, возможно, содержимое уже было прочитано другим компонентом.", "type": "IOException", "stack": "в Microsoft.AspNetCore.WebUtilities.MultipartReaderStream.d__41.MoveNext () \ r \ n --- Конец трассировки стека из предыдущего места, где было сгенерировано исключение --- \ r \ n в System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () \ r \ n в System.Runtime.CompilerServices. TaskAwaiter.HandleNonSuccessAndDebuggerNotification (задача задачи) \ r \ n в Microsoft.AspNetCore.WebUtilities.StreamHelperExtensions.d__3.MoveNext () \ r \ n --- Конец трассировки стека из предыдущего места, где было сгенерировано исключение --- \ r \ n в System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () \ r \ n в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (Task task) \ r \ n в Microsoft.AspNetCore.WebUtilities.MultipartReader.d \ n --- Конец трассировки стека из предыдущего места, где было сгенерировано исключение --- \ r \ n в System.Runtime.ExceptionServices .ExceptionDispatchInfo.Throw () \ r \ n в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (Task task) \ r \ n в Microsoft.AspNetCore.Http.Features.FormFeature.d__18.MoveNext () \ n-- - Конец трассировки стека из предыдущего места, где было сгенерировано исключение --- \ r \ n в System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () \ r \ n в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (Task task) \ r \ n в Microsoft.AspNetCore.Mvc.ModelBinding.FormValueProviderFactory.d__1.MoveNext () \ r \ n --- Конец трассировки стека из предыдущего места, где было сгенерировано исключение --- \ r \ n в System.Runtime.ExceptionServices .ExceptionDispatchInfo.Throw () \ r \ n в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (Task task) \ r \ n в Microsoft.AspNetCore.Mvc.ModelBinding.CompositeValueProvider.d__2.MoveN - Конец трассировки стека из предыдущего места, где было сгенерировано исключение --- \ r \ n в System.Runtime.Ex ceptionServices.ExceptionDispatchInfo.Throw () \ r \ n в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (задача задачи) \ r \ n в Microsoft.AspNetCore.Mvc.Internal.DefaultController6. - Конец трассировки стека из предыдущего места, где было сгенерировано исключение --- \ r \ n в System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () \ r \ n в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (задача задачи) \ r \ n в Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__22.MoveNext () \ r \ n --- Конец трассировки стека из предыдущего места, где было сгенерировано исключение --- \ r \ n в System.Runtime. ExceptionServices.ExceptionDispatchInfo.Throw () \ r \ n в Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow (контекст ResourceExecutedContext) \ r \ n в Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next (State & Scope, Scope & Scope) Объект и состояние, логическое значение и isCompleted) \ r \ n в Microsoft.AspN etCore.Mvc.Internal.ControllerActionInvoker.d__20.MoveNext () \ r \ n --- Конец трассировки стека из предыдущего места, где было сгенерировано исключение --- \ r \ n в System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () \ r \ n в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (задача задачи) \ r \ n в Microsoft.AspNetCore.Builder.RouterMiddleware.d__4.MoveNext () \ r \ n --- Конец трассировки стека из предыдущего местоположения где было сгенерировано исключение --- \ r \ n в System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () \ r \ n в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (Task task) \ r \ n в Microsoft.AspNetCore. Builder.Extensions.MapMiddleware.d__3.MoveNext () \ r \ n --- Конец трассировки стека из предыдущего места, где было сгенерировано исключение --- \ r \ n в System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () \ r \ n в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (задача задачи) \ r \ n в IdentityMode l.AspNetCore.ScopeValidation.ScopeValidationMiddleware.d__3.MoveNext () \ r \ n --- Конец трассировки стека из предыдущего места, где было сгенерировано исключение --- \ r \ n в System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () \ r \ n в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (задача задачи) \ r \ n в Microsoft.AspNetCore.Authentication.AuthenticationMiddleware 1.<Invoke>d__18.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware 1.d__18.MoveNext () \ r \ n --- End трассировки стека из предыдущего места, где было сгенерировано исключение --- \ r \ n в System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () \ r \ n в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (Task task) \ r \ n в IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationMiddleware.d__7.MoveNext () \ r \ n --- Конец трассировки стека из предыдущего места, где было сгенерировано исключение --- \ r \ n в System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () \ r \ n в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccess AndDebuggerNotification (задача задачи) \ r \ n в Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.d__7.MoveNext () \ r \ n --- Конец трассировки стека из предыдущего места, где было сгенерировано исключение --- \ r \ n в System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () \ r \ n в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (Task task) \ r \ n в System.Runtime.CompilerServices.TaskResult.Get в Celo.Api.Middleware.Exceptions.ExceptionHandlingMiddleware.d__5.MoveNext () в D: \ a \ 1 \ s \ src \ Celo.Api \ Middleware \ Exceptions \ ExceptionHandlingMiddleware.cs: строка 41 "}]

Я не знаю, почему это не так.

Для справки команда curl:

curl -X PUT https://mydomain.co.nz/api/Account -H 'accept: application/json' -H 'authorization: Bearer eyJhb..' -H 'cache-control: no-cache' -F 'data={"isoncall" : true}'

И вызов javascript:

let xhr:XMLHttpRequest = new XMLHttpRequest();
        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    console.log('200', xhr.response)
                    //resolve(<MyEntity>JSON.parse(xhr.response));
                } else {
                    console.log('err', xhr.response)
                    //reject(xhr.response);
                }
            }
        };

        xhr.open('PUT', 'https://mydomain.co.nz/api/Account', true);
        xhr.setRequestHeader("Accept", "application/json")
        xhr.setRequestHeader("Authorization", this.authService.getAuth())
        xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=--------------------------33e4cd665cd7a003')
        xhr.send(`--------------------------33e4cd665cd7a003
Content-Disposition: form-data; name="data"

{"isoncall" : true}
--------------------------33e4cd665cd7a003--`)
0
robert king 31 Июл 2017 в 04:23
Попробуйте вставить \r\n вместо новой строки в данных тела --------------------------33e4cd665cd7a003\r\nContent-Disposition: form-data; name="data"\r\n\r\n{"isoncall" : true}\r\n--------------------------33e4cd665cd7a003--\r\n
 – 
Bertrand Martel
31 Июл 2017 в 05:13
Попробовал, но это не сработало xhr.send ('-------------------------- 33e4cd665cd7a003 \ r \ nContent-Dispos‌ ition: form -data; name = "data" \ r \ n \ r \ n {"isoncall": true} \ r \ n ----------------------- --- 33e4cd665cd7a003 - \ r \ n ') хотя спасибо
 – 
robert king
31 Июл 2017 в 05:41

1 ответ

Лучший ответ

Явное различие между этими двумя запросами заключается в том, что в вашем запросе XHR вы не устанавливаете префикс границы в теле запроса двумя дефисами, как требуется.

Если вы посмотрите на запрос, сгенерированный CURL, вы увидите, что две границы имеют два дополнительных тире с префиксом (по сравнению с границей в заголовке), а также два дополнительных тире с суффиксом к последней границе тела. В вашем коде javascript нет префиксов.

Сказав это, я могу предложить два возможных решения:

  1. Исправьте текущий код - возможно, это быстрое решение.

    Как упоминалось выше, вам нужно добавить дополнительный префикс - к границе в теле. Во-вторых, я бы избегал многострочных строк в том виде, в каком они у вас есть, и использовал бы \ n в качестве разделителя строк.
    Это приведет к следующему javascript:

    xhr.open('PUT', 'https://mydomain.co.nz/api/Account', true);
    xhr.setRequestHeader("Accept", "application/json");
    xhr.setRequestHeader("Authorization", this.authService.getAuth());
    xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=--------------------------33e4cd665cd7a003')
    xhr.send(`----------------------------33e4cd665cd7a003\n' +
        'Content-Disposition: form-data; name="data"\n\n' +
        '{"isoncall" : true}\n\n' +
        '----------------------------33e4cd665cd7a003--');
    
  2. Вы также можете переключиться на XHR FormData API и избежать проблем при этом вручную.

    var formData = new FormData();
    formData.append("data", '{"isoncall" : true}');
    xhr.open('PUT', 'https://mydomain.co.nz/api/Account', true);
    xhr.setRequestHeader("Accept", "application/json");
    xhr.setRequestHeader("Authorization", this.authService.getAuth());
    xhr.send(formData);
    
1
brain99 4 Окт 2017 в 02:49
Спасибо - второй сработал. Мне нужно подождать 21 час, чтобы наградить вас наградой, спасибо
 – 
robert king
4 Окт 2017 в 03:46