Възпроизвеждане на 2.2.1 SimpleResult 4xx Response Body Възможно ли е чрез CORS XHR?

Опитвам се да изпратя JSON тяло на отговор, когато моят API обслужва 4xx http код на отговор. Всичко работи добре, когато кодът е 200, но променен на 4xx, не се получава тяло. Пощальонът за Chrome показва реакцията на тялото, но XHR (Chrome, FF) не.

Въобще възможно ли е да получите тялото на отговора вътре в XHR с nginx CORS правилно настроен (настроих го просто да ехо ...Allow-Origin: $http_origin)? Имам nginx като proxy_pass към действителния API сървър на 127.0.0.1:9001. Когато изпратя известни идентификационни данни, CORS и Allow-Origin работят добре с 200 OK. Ако просто използвам лоша парола, виждам кода на състоянието на грешката във Firebug, но XHR обектът (също $.ajax на jQuery) има Статус = 0, въпреки че заявка удря API сървъра.

Като минимум бих искал да мога да взема кода на състоянието 4xx в XHR обекта, за да мога поне да покажа обща информация за определени кодове 4xx вместо общото „не работи“. Това също не е налично и винаги получавам status=0, въпреки че API е засегнат и правилният код на отговор е регистриран в nginx.

Актуализация 3/23 Javascript XHR код:

var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://arinna-api/v1/401', true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.onload = function () {
    // do something to response
    console.log(this);
};

Възпроизвеждане на рамков код за връщане на състояние 200 OK JSON тип съдържание на отговора:

SimpleResult(
  header = ResponseHeader(200, Map(CONTENT_TYPE -> "application/json")),
  body = Enumerator("{\"error\":\"invalid grant\"}".getBytes())
)

200 OK работи според очакванията:

HTTP 200 OK Работи, но не е REST

Промяната на HTTP кода на 401 кара тялото на отговора да не бъде получено от XMLHttpRequest (xhr.status също е 0 вместо 401):

SimpleResult(
  header = ResponseHeader(401, Map(CONTENT_TYPE -> "application/json")),
  body = Enumerator("{\"error\":\"invalid grant\"}".getBytes())
)

xhr.send('username=username&password=badpassword&grant_type=password&client_id=mobile_platform');

HTTP 401 няма тяло, анализирано от отговор

Пощальон работи според очакванията:

въведете описание на изображението тук

Възможно ли е да получите тяло на отговор 4xx и код на състоянието чрез XHR? Според W3C дефиниции на код за състояние на HTTP 4xx:

Освен когато отговаря на заявка HEAD, сървърът ТРЯБВА да включва обект, съдържащ обяснение на ситуацията с грешка и дали тя е временно или постоянно състояние. Тези кодове на състояние са приложими за всеки метод на заявка. Потребителските агенти ТРЯБВА да показват всеки включен обект на потребителя.

Въпреки това, според тази дискусия:

2) Браузърите не показват тялото на отговора text/html на HTTP 401 отговор, вместо това те просто изскачат диалогов прозорец за модално удостоверяване (докато се натисне „отказ“).

3) Сървърите не изпращат смислено тяло на отговор със статус 401, тъй като браузърите така или иначе не го показват.


person notbrain    schedule 21.03.2014    source източник
comment
можете ли да добавите вашия javascript код?   -  person Ömer Faruk Gül    schedule 24.03.2014
comment
@ÖmerFarukGül XHR добави   -  person notbrain    schedule 24.03.2014
comment
Мислех, че може би onError или нещо друго се задейства вместо успех.   -  person Ömer Faruk Gül    schedule 24.03.2014


Отговори (1)


Кодът по-долу функционира според очакванията:

Application.scala

object Application extends Controller {

  def index = Action { request =>
    Ok(views.html.index())
  }

  def indexPost = Action { request =>
    Unauthorized("test").withHeaders(ACCESS_CONTROL_ALLOW_ORIGIN -> "*")
  }
}

routes

GET    /   controllers.Application.index
POST   /   controllers.Application.indexPost

index.html.scala

@()

@main("Welcome to Play 2.1") {
  <script type="text/javascript">
      var xhr = new XMLHttpRequest();
      xhr.open('POST', 'http://localhost:9000/');
      xhr.onload = function () {
      console.log(this);
    };
    xhr.send();
  </script>
}

Текстът "test" се показва в отговора (Opera, Chrome и Firefox). Имайте предвид, че стартирам Play два пъти, на порт 9000 и 9001 и използвам Play 2.2.1. След това от Play at 9001 правя заявка до 9000.

person EECOLOR    schedule 27.03.2014
comment
Благодаря - имам подобна настройка, работеща чрез прокси на домейна на API към /api крайна точка в домейна на моето приложение. Така че това не би било предмет на ограниченията на CORS (и не използва SSL). Крайната цел е да дадем възможност на нашите партньори да настроят едностранично приложение и да използват XHR заявки, за да получат подробни основни JSON отговори за условия на грешка. - person notbrain; 28.03.2014
comment
Въпросът ви беше: Възможно ли е да получите тяло на отговор 4xx и код на състоянието чрез XHR? С горната настройка отговорът е: да. Проблемът ти вероятно не е с Play, а с nginx - person EECOLOR; 28.03.2014
comment
Същият произход XHR != CORS XHR. - person notbrain; 28.03.2014
comment
Успях да възпроизведа грешката. Добавянето на заглавката Access-Control-Allow-Origin коригира проблема. Редактирах отговора си, за да отразя това. - person EECOLOR; 29.03.2014
comment
Благодаря (!), прав си, nginx не предава заглавката по някаква причина. Чудя се дали е възможно да настроите nginx да изпраща заглавката чрез proxy_pass дори когато приложението не задава изрично заглавки. Изглежда тромаво да добавяте в -Origin заглавки към всички отговори от страна на приложението. - person notbrain; 29.03.2014
comment
Въпреки че нямам опит с nginx, изглежда, че този модул прави това, от което се нуждаете: HttpHeadersMoreModule. Нормалният заглавен модул не ви позволява да коригирате заглавки за 4xx и 5xx кодове за състояние. - person EECOLOR; 29.03.2014
comment
Благодаря за указателя - надявах се да избегна компилирането на собствената си версия на nginx, но изглежда, че това е единствената друга опция, ако не искам да бъде кодирана в самото приложение. - person notbrain; 30.03.2014