Angular2 REST запрос HTTP код состояния 401 изменяется на 0
Я разрабатываю приложение Angular2. Кажется, когда мой токен доступа истекает, код состояния HTTP 401 изменяется на значение 0 в объекте ответа. Я получаю 401 несанкционированный, но объект ответа на ошибку имеет статус 0. Это мешает мне перехватить ошибку 401 и попытаться обновить токен. Что вызывает изменение кода состояния HTTP 401 в код состояния HTTP 0?
вот скриншот из Firefox консоль:
вот мой код:
get(url: string, options?: RequestOptionsArgs): Observable<any>
{
//console.log('GET REQUEST...', url);
return super.get(url, options)
.catch((err: Response): any =>
{
console.log('************* ERROR Response', err);
if (err.status === 400 || err.status === 422)
{
return Observable.throw(err);
}
//NOT AUTHENTICATED
else if (err.status === 401)
{
this.authConfig.DeleteToken();
return Observable.throw(err);
}
else
{
// this.errorService.notifyError(err);
// return Observable.empty();
return Observable.throw(err);
}
})
// .retryWhen(error => error.delay(500))
// .timeout(2000, new Error('delay exceeded'))
.finally(() =>
{
//console.log('After the request...');
});
}
этот код находится в пользовательской службе http, которая расширяет HTTP Angular2, поэтому я могу перехватывать ошибки в одном месте.
в Google Chrome я получаю это сообщение об ошибке:
XMLHttpRequest не удается загрузить https://api.cloudcms.com/repositories/XXXXXXXXXXXXXXXX/branches/XXXXXXXXXXXXXXXX/nodesXXXXXXXXXXXXXXXX - ... Нет заголовка "Access-Control-Allow-Origin" присутствует на запрашиваемый ресурс. Происхождения 'http://screwtopmedia.local.solutiaconsulting.com', следовательно, не разрешен доступ. Ответ имел код состояния HTTP 401.
это сбивает с толку, потому что я включаю заголовок "Access-Control-Allow-Origin" в запрос.
вот изображение результатов, полученных в Google Chrome:
Я попытался получить доступ к заголовку ответа "WWW-Authenticate" в качестве средства ловушка для 401. Однако следующий код возвращает значение NULL:
err.headers.get("WWW-Authenticate")
это озадачивает, что я получаю проблему CORS, потому что я не получаю никаких ошибок CORS, когда предоставляется действительный токен доступа.
Как мне поймать код состояния HTTP 401? Почему 401 код состояния HTTP изменяется на 0?
Спасибо за вашу помощь.
6 ответов
Я работаю на Cloud CMS. Я могу подтвердить, что мы правильно установили заголовки CORS для вызовов API. Однако для 401 ответа заголовки не устанавливаются должным образом. Это было решено, и исправление будет доступно в общедоступном API в конце этой недели.
кстати, если вы используете наш драйвер javascripthttps://github.com/gitana/gitana-javascript-driver вместо того, чтобы писать в API напрямую, поток повторной аутентификации обрабатывается автоматически, и вам не нужно ловить 401 ошибки вообще.
вопрос CORS запросы см. этот вопрос github
заголовок "Access-Control-Allow-Origin" отсутствует в запрошенном заголовке ресурс
означает, что 'Access-Control-Allow-Origin'
требуется в заголовках ответов.
Angular не получает никаких кодов состояния, поэтому он дает вам 0
что вызвано браузером, не позволяющим xml parser
для разбора response
из-за недопустимого headers
.
вам нужно добавить правильное заголовки CORS на error response
а также success
.
если cloudcms.com сделать, чтобы не установить Access-Control-Allow-Origin
в ответе 401, тогда вы ничего не можете сделать. Вы должны правильно открыть билет поддержки с ними, чтобы подтвердить, является ли это нормальным поведением.
javascript в браузерах (FF, Chrome и Safari), которые я тестировал, не получит никакой информации, если произойдет ошибка CORS, кроме статуса 0. Angular2 не контролирует его.
Я создал простой тест и получил тот же результат, что и ваш:
geturl() {
console.log('geturl() clicked');
let headers = new Headers({ 'Content-Type': 'application/xhtml+xml' });
let options = new RequestOptions({ 'headers': headers });
this.http.get(this.url)
.catch((error): any => {
console.log('************* ERROR Response', error);
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Web Server error';
return Observable.throw(error);
})
.subscribe(
(i: Response) => { console.log(i); },
(e: any) => { console.log(e); }
);
}
после долгого гугления я нашел следующее (https://github.com/angular/angular.js/issues/3336):
лукасп прокомментировал 19 августа 2013
Я нашел проблему на некоторое время, но я забыл опубликовать здесь ответ. Каждый ответ, даже Ошибка 500, должен иметь прикрепленные заголовки CORS. Если сервер не присоединяет заголовки CORS к ответу Error 500, объект XHR не будет анализировать его, таким образом, у объекта XHR не будет тела ответа, состояния или других данных ответа внутри.
результат от сетевого монитора Firefox, похоже, поддерживает вышеуказанную причину.
запрос Javascript получит пустой ответ.
простой запрос url(скопируйте и вставьте ссылку в адресной строке) получит тело ответа
Javascript используйте XHRHttpRequest для http-связи.
когда придет ответ XHR, браузер обработает заголовок, поэтому вы увидите эти 401 сетевые сообщения. Однако, если ответ XHR от другого хоста, то javascript и заголовок ответа не содержат заголовка CORS(например,Access-Control-Allow-Origin: *
), браузер не будет передавать информацию обратно в слой XHR. В результате тело ответа будет полностью пустым без статуса (0).
Я тестировал с FF 48.0.1, Chrome 52.0.2743.116 и Safari 9.1.2, и все они имеют одинаковое поведение.
используйте сетевой монитор браузера, чтобы проверить заголовок ответа для тех 401 Unauthorized
записи, очень вероятно, что нет Access-Control-Allow-Origin
заголовок и вызывая проблемы. Это может быть ошибка или по дизайну на стороне поставщика услуг.
Access-Control-Allow-Origin
- это только HTTP-заголовок ответа. Для получения дополнительной информации https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#The_HTTP_response_headers
по данным W3C по, если атрибут status имеет значение 0, это означает, что:
- состояние не отправлено или открыто.
или
- установлен флаг ошибки.
Я думаю, что это не Angular2
вопрос, похоже, что ваш запрос имеет проблемы.
вы должны использовать сторонний монитор протокола http (например, CharlesProxy), а не инструменты Chrome dev, чтобы подтвердить, какие заголовки фактически отправляются в службу API, и если он возвращает 401.
у меня была та же проблема и из-за того, что сервер не отправил правильный ответ (хотя в журнале консоли указано 401, угловая ошибка имела статус 0). Мой сервер был Tomcat с Java-приложением, использующим Spring MVC и Spring Security.
теперь он работает с помощью folowing setup:
SecurityConfig.java
...
protected void configure(HttpSecurity http) throws Exception {
....
http.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.authenticationEntryPoint(authenticationEntryPoint);
// allow CORS option calls
http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll();
...
SomeAuthenticationEntryPoint.java
@Component
public class SomeAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
HttpStatus responseStatus = HttpStatus.UNAUTHORIZED;
response.sendError(responseStatus.value(), responseStatus.getReasonPhrase());
}
}
web.в XML
<error-page>
<error-code>403</error-code>
<location>/errors/unauthorised</location>
</error-page>
<error-page>
<error-code>401</error-code>
<location>/errors/unauthorised</location>
</error-page>
контроллер для обработки /ошибки./.. ранее определено
@RestController
@RequestMapping("/errors")
public class SecurityExceptionController {
@RequestMapping("forbidden")
public void resourceNotFound() throws Exception {
// Intentionally empty
}
@RequestMapping("unauthorised")
public void unAuthorised() throws Exception {
// Intentionally empty
}
}
}