`Good day, colleagues!
I cannot find a way to get Response and/or custom Response Header in Angular.
Angular is embedded into JSP page. Angular sends post request to Spring Boot app with multi part file. If the size of the file exceeds 10 MB Spring Boot app throws MaxFileSizeExceededException, which is handled in it and wrapped into EsignError as follows:
@ControllerAdvice
@Slf4j
public class EsignExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(value
= {EsignException.class})
public ResponseEntity<Object> scannerException(Exception ex, WebRequest request) {
log.error(ex.getMessage());
log.info("Inside first handler");
String bodyOfResponse = ex.getMessage();
return handleExceptionInternal(ex, bodyOfResponse,
HTTPUtil.getCommonHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request);
}
@ExceptionHandler(MaxUploadSizeExceededException.class)
public @ResponseBody ResponseEntity<?> handleMaxUploadSizeExceededException(MaxUploadSizeExceededException ex) {
log.error(ex.getMessage());
log.info("Inside second handler");
EsignError error = new EsignError(HttpStatus.BAD_REQUEST.value(), ex.getMessage());
HttpHeaders headers = new HttpHeaders(HTTPUtil.getCommonHeaders());
headers.setAccessControlAllowOrigin("*");
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("msgHeader", ex.getMessage());
return new ResponseEntity<>(error, headers, HttpStatus.BAD_REQUEST);
}
}
EsignError class is as follows:
@Data
public class EsignError {
private int status;
private String message;
private Date timestamp;
public EsignError(int status, String message) {
this.status = status;
this.message = message;
this.timestamp = new Date();
}
}
Spring Boot app returns the following JSON as an example:
{ "status": 400, "message": "Maximum upload size exceeded; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException: the request was rejected because its size (31238283) exceeds the configured maximum (10485760)", "timestamp": "2022-11-17T08:41:45.580 00:00" }
In browser (Network tab) I see the following custom header among Response Headers: Maximum upload size exceeded; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException: the request was rejected because its size (31238845) exceeds the configured maximum (10485760)
I also see the following in Response in browser:
{"status":400,"message":"Maximum upload size exceeded; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException: the request was rejected because its size (31238845) exceeds the configured maximum (10485760)","timestamp":"2022-11-17T08:45:38.705 00:00"}
I tried to catch and see the custom header value or response in Angular as follows:
First, I tried it in the postFile() method of angular component, that sends the post request to the Spring Boot app:
postFile() {
this.uploadState = 'отправка файла...';
var certHolders: string = '';
this.corresp.approvals.forEach(a => {
certHolders = certHolders a.logname ';';
});
const formData: FormData = new FormData();
formData.append('file', this.file, 'file.pdf');
formData.append('idappli', String(this.corresp.idappli));
formData.append('odcorresp', String(this.corresp.odcorresp));
formData.append('idletter', String(this.corresp.idletter));
formData.append('certHolders', certHolders);
formData.append('fpage', String(this.stampStart));
formData.append('lpage', String(this.stampEnd));
const headers = new HttpHeaders().append("Access-Control-Allow-Origin", "*")
.append("Access-Control-Allow-Origin", "*")
.append("Access-Control-Allow-Methods", "POST")
.append("Access-Control-Allow-Headers", "Origin, Accept, Authorization, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers")
const o: Observable<any> = this.http.post(this.corresp.url, formData, {headers, responseType: "blob"});
o.subscribe(blob => {
this.addHistory("insert");
this.getFileWithSign();
this.corresp.exists = true;
console.log('blob.error: ' blob.error);
console.log('blob.message: ' blob.message);
},
error => {
this.uploadState = 'ошибка отправки файла на подпись!';
console.log('console.log error.status: ' error.status);
// console.log('console.log error.error(): ' error.error());
// console.log('console.log error.errorDetails: ' error.errorDetails);
console.log('console.log error: ' error);
console.log('console.log error.error: ' error.error);
// The following line results in error in browser console: ERROR TypeError: Cannot read properties of undefined (reading 'status')
// console.log('console.log error.error.status: ' error.error.status);
if (error.status === 400) {
const msg2 = error.headers.get('msgHeader');
alert('msg2: ' msg2);
}
}
);
}
It does not show anything out of the custom header or response.
Also I tried to do it via three kinds of Interceptors as follows:
- ErrorInterceptor:
import {Injectable} from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor, HttpErrorResponse, HttpResponse
} from '@angular/common/http';
import {Observable, throwError} from 'rxjs';
import {catchError, retry, tap} from "rxjs/operators";
@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
constructor() {
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
catchError((errorResponse: HttpErrorResponse) => {
if (errorResponse.status === 400) {
console.log('!!! Размер файла не может быть больше 10 Мб !!!');
console.log('errorResponse.error: ' errorResponse.error);
console.log('errorResponse.error.message: ' errorResponse.error.message);
console.log('errorResponse.error.status: ' errorResponse.error.status);
console.log('errorResponse.error.timestamp: ' errorResponse.error.timestamp);
alert('!!! Размер файла не может быть больше 10 Мб !!!');
alert(errorResponse.status);
alert(errorResponse.message);
alert(errorResponse.error);
const msg = errorResponse.headers.getAll('msgHeader');
console.log(msg);
alert(msg);
}
return throwError(() => new Error('test error 400'));
}));
}
}
ErrorIterseptor allows to get status of 400, but not the message or timestamp.
- EventInterceptor
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor, HttpResponse, HttpErrorResponse
} from '@angular/common/http';
import { Observable } from 'rxjs';
import {retry, tap} from "rxjs/operators";
@Injectable()
export class EventInterceptor implements HttpInterceptor {
constructor() {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
tap(event => {
if (event instanceof HttpResponse) {
console.log('Response');
console.log(event);
alert(event);
console.log(event.body);
console.log(event.status);
console.log(event.headers);
}
if (event instanceof HttpErrorResponse) {
console.log('Error')
console.log(event);
alert(event);
console.log(event.error);
console.log(event.status);
console.log(event.headers);
}
}
));
}
}
EventInterceptor looks useless.
- ResponseHeaderInterceptor
import {Injectable} from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor, HttpResponse
} from '@angular/common/http';
import {Observable, throwError} from 'rxjs';
import {catchError, filter, retry} from "rxjs/operators";
@Injectable()
export class ResponseHeaderInterceptor implements HttpInterceptor {
constructor() {
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
filter(event => event instanceof HttpResponse),
catchError(error => {
if (error.status === 400) {
const msg = error.headers.get('msgHeader');
console.log(msg);
alert(msg);
}
return throwError(error);
})
);
}
}
This interceptor does not help either.
Can you please help me to figure out how I can get either custom header value or response value in either component from which post is senyour text
t or in any interceptor?
CodePudding user response:
Try to add observe: 'response' to your options object. Then you can read the header value from the response by blop.headers.get('your-x-header-name')
const o: Observable<any> = this.http.post(this.corresp.url, formData, {headers, responseType: blob, observe: 'response'});
CodePudding user response:
Colleagues, I solved the issue by changing the responseType from "blob" to "json" in options in http.post() in postFile() method, listed above. Then I switched off all interceptors in app.module.ts and played with fields of error in error => {} part of postFile() method which now is as follows:
error => {
this.uploadState = 'ошибка отправки файла на подпись!';
console.log('console.log error.status: ' error.status);
console.log('console.log error.error.message: ' error.error.message);
console.log('console.log error.error.timestamp: ' error.error.timestamp);
alert(`!!! Размер файла не может превышать 10Мб !!!\nСтатус ошибки: ${error.status}.\nСообщение: ${error.error.message}.\nДата и время: ${error.error.timestamp}.`);
}
I also removed everything connected with adding and reading the custom header. It does not work. All information is read from response body.
Thanks for answering and paying attention to my question.