[英]Angular 4: unable to read headers from response - not a CORS issue
In the context of a server automatically renewing a token, I'm struggling with the basics: Obtaining header data from a response. 在服务器自动更新令牌的上下文中,我正在努力解决基本问题:从响应中获取头数据。
It does not seem to be CORS related as my Node/express allwos the Authorization/x-access-token and reponds accordingly (see network tab screeencap below). 它似乎与CORS无关,因为我的Node / express allwos授权/ x-access-token并相应地响应(请参阅下面的网络选项卡screeencap)。
The first step I want to see working is simply reading the header from the response. 我希望看到工作的第一步是简单地从响应中读取标题。 See my code, it's boilerplate as found in the docs.
请参阅我的代码,它是文档中的样板文件。 Event getting "Content-Length" returns null.
获取“Content-Length”的事件返回null。
auth-service.ts AUTH-service.ts
login(username:string, password:string):Observable<boolean>{
this.loggedIn = false;
return new Observable( (observer:Observer<boolean>) => {
const body = {user: username, pwd: password};
const url = this.config.API_ENDPOINT_PUBLIC_AUTH;
this.httpClient.post(url, body, {
responseType: 'text',
observe: "response"
}).first().subscribe(
(response:HttpResponse<string>) => {
// DEBUG
console.log(response.headers.get('Authorization'));
console.log(response.headers.get('X-Test-Header'));
console.log(response.headers.get('Content-length'));
this.token = response.headers.get('Authorization');
this.storeToken(this.token);
this.currentUser = username;
this.loggedIn = true;
this.authChanged$.next('auth');
observer.next(true);
},
(err) => observer.next(false),
() => {},
);
});
}
Console output: 控制台输出:
null
空值
null
空值
null
空值
Compare this to the contents of my network tab for this request: 将此与此请求的网络选项卡的内容进行比较:
Needless to say my HttpInterceptor doesn't work either - upon being provided "Authorization" header in a response, it uses the value as new token. 不用说我的HttpInterceptor也不起作用 - 在响应中提供“Authorization”标头时,它将该值用作新标记。 This to implement auto-renewal of tokens:
这样可以实现令牌的自动续订:
token.interceptor.ts token.interceptor.ts
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const authService = this.injector.get(AuthService);
const token = authService.getToken();
if(token){
request = request.clone({
setHeaders: { 'x-access-token' : token }
});
}
return next.handle(request).do(
(event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
const response:HttpResponse<any> = (<HttpResponse<any>> event);
const authorizationHeader = response.headers.get('Authorization');
console.log('Authorization header value: ' + authorizationHeader);
if(authorizationHeader){
authService.setToken(authorizationHeader);
}
}
},
(err: any) => {
if (err instanceof HttpErrorResponse){
if (err.status === 401) {
this.router.navigate(['/']);
}
}
});
}
Ok, here is the answer: I'm using Node.js/Express as backend and even though headers are visible in the network tab of Chrome, it doesn't make them available for processing by Angular. 好的,这就是答案:我使用Node.js / Express作为后端,即使标题在Chrome的网络标签中可见,也不会使它们可供Angular处理。
"How comes they're visible yet cannot be used?" “他们怎么可见但却无法使用?” is still not clear to me.
我还不清楚。
Configure your Node/Express app (look for the comment "SOLUTION HERE"): 配置您的Node / Express应用程序(查找评论“SOLUTION HERE”):
function configureExpress(expressApp){
expressApp.use(bodyparser.urlencoded({ extended: true }));
expressApp.use(bodyparser.json());
// Middleware: Use CORS, add headers and allow methods
expressApp.use(expressMiddleware);
}
function expressMiddleware(req, res, next) {
// Request origin: Allow ALL
res.header("Access-Control-Allow-Origin", "*");
// Allowed headers
res.header("Access-Control-Allow-Headers",
"Origin"
+",X-Requested-With" // Dont allow AJAX CORS without server consent - see http://stackoverflow.com/questions/17478731/whats-the-point-of-the-x-requested-with-header
+",x-access-token"
+",Content-Type"
+",Authorization"
+",Accept"
);
// SOLUTION HERE
// Allow headers access
res.header("access-control-expose-headers",
",Authorization"
+",Content-Length"
);
// Allowed methods
res.header('Access-Control-Allow-Methods',
'GET,'
+',POST'
+',OPTIONS'
+',PUT,'
+',DELETE'
);
// Handle CORS requests: cross-domain/origin requests will begin with an OPTION request to the same endpoint.
if('OPTIONS' === req.method){
res.sendStatus(200);
}
else{
// Request validations complete
next();
}
}
Adding the answer with some more relevant information 添加一些更相关的信息
I am using Angular 7 and just adding the custom header in Access-Control-Expose-Headers in the API didn't work for me. 我正在使用Angular 7 ,只是在API中的Access-Control-Expose-Headers中添加自定义标头对我来说不起作用。
The catch here is the custom header has to be in lower case as comma delimited values in Access-Control-Expose-Headers 这里的问题是自定义标头必须是小写,因为Access-Control-Expose-Headers中的逗号分隔值
Example (Express) 示例(快递)
const cors = require('cors');
const corsOptions = {
allowedHeaders: 'x-custom-one,x-custom-two',
exposedHeaders: 'x-custom-one,x-custom-two'
}
app.use(cors(corsOptions));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.