Reputation: 9873
In my HttpServive
, I have shared http methods that will handle starting/ending the loading bar, setting the proper headers for JWT, and so on.
All is fine, but now I am trying to add some logic in the catch
to check the response in the event of a non-200 status code (such as 401), so that I can do something and then re-make the failed request.
The problem is, the response I get back in the event of a non-200 status code is not accessible from that catch
for whatever reason.
For instance, this is the code:
// ...
return this.http[method](url, options || defaultOptions)
.map((res: Response) => res.json()) // <--- gives JSON from response
.catch((error: any)) => {
console.log(error);
console.log(error.json()); // <--- should give JSON from response, but gives ProgressEvent instead
return Observable.throw(error.json()); // also gives ProgressEvent when I 'subscribe' to the observable
})
.finally(() => {
this.loadingBarService.complete();
});
The console.log(error)
outputs the error of type Response
; The console.log(error.json())
outputs some data of type ProgressEvent
.
Why am I getting a ProgressEvent, instead of the JSON sent from the non-200 status code response?
This is the ProgressEvent
:
{
bubbles: false,
cancelBubbles: false,
cancelable: false,
composed: false,
currentTarget: XMLHttpRequest,
defaultPrevented: false,
eventPhase: 0,
isTrusted: true,
lengthComputable: false,
loaded: 0,
path: Array(0),
returnValue: true,
srcElement: XMLHttpRequest,
target: XMLHttpRequest,
timeStamp: 1234.115,
total: 0,
type: "error",
__proto__: ProgressEvent
}
As you can see, the ProgressEvent
is not my response. My response is a JSON object with just one error
property, which contains a message and a status. This is just wrong, why don't I get my response?
Upvotes: 4
Views: 3954
Reputation: 2128
I got a similar issue working on a spa project based on Angular and Asp.Net Core.
If it is the same issue it should have depend from the missing of CORS headers in the http response that client receives from server. This response violates the browser CORS policy and most likely depends from not handled run time errors in the server.
Even catching all errors and putting into returning response some info and http status, Angular, when occur CORS constraints violations, doesn't allow to have access to any info of the response, not even the http status, and so it produces the "empty" response:
Response {_body: ProgressEvent, status: 0, ok: false, statusText: "", headers: Headers, …} headers : Headers {_headers: Map(0), _normalizedNames: Map(0)} ok : false status : 0 statusText : "" type : 3 url : null..
I solved this issue putting CORS headers into the response returned by the ASp.Net Core api server to the client in this way:
app.UseExceptionHandler(appError => {
appError.Run(async context => {
var _config = ServiceProviderFactory.ServiceProvider.GetService<AppConfigurations>();
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.ContentType = "application/json";
context.Response.Headers.Add("Access-Control-Allow-Origin", $"{_config.AngularSiteUrl}");
context.Response.Headers.Add("Access-Control-Allow-Headers", "access-control-allow-origin,authorization,content-type");
var contextFeature = context.Features.Get<IExceptionHandlerFeature>();
if (contextFeature != null) {
var ex = contextFeature.Error;
var sp = services.BuildServiceProvider();
var _logger = sp.GetService<IGenericRepository<Log>>();
_logger.AddAndSave(new Log {
Description = "Exception not handled occurred",
Reason = ex.ToString(),
Type = "Error"
});
await context.Response.WriteAsync(
JsonConvert.SerializeObject(new {
Status = context.Response.StatusCode,
Message = "Internal Server Error."
}));
}
});
The code has to be put into in the Configure
method of Startup
class.
I hope that it could be of some help.
Upvotes: 1