I want caching into the "localstorage" the HttpRequest and HttpResponse classes from @angular/mon/http
.
The localstorage
only accept string
, therefore i want serialize/unserialize both objects (HttpRequest and HttpResponse) with JSON.stringfy()
and JSON.parse()
.
The problem is HttpRequest
and HttpResponse
are both plex class with some ES6 Map (eg. HttpHeaders) and some getter/setter function, with JSON.stringfy()
and JSON.parse()
the serialization/unserialization don't return the same object and some information are lost.
There is a way for serialize/unserialize HttpRequest
and HttpResponse
class?
I'm searching for a plete serialization/unserialization (headers, params, body, etc)
In this example there is two method for serialize and unserialize HttpRequest, eg.:
function serializeRequest(angularRequest: HttpRequest): string {
return null; // to implement
}
function unserializeRequest(jsonRequest: string): HttpRequest {
return null; // to implement
}
// this is an example of request
const originalRequest = new HttpRequest('POST', '', {foo: true}, {
params: new HttpParams().set('verbose', 'true'),
headers: new HttpHeaders({
BAR: 'baz',
}),
reportProgress: true,
responseType: 'json',
withCredentials: true
});
// serializeRequest trasform HttpRequest in json format
const jsonRequest: string = serializeRequest(originalRequest);
// unserializeRequest trasform json format to HttpRequest
const unserializedRequest : HttpRequest = unserializeRequest(jsonRequest);
// unserializedRequest as same object of originalRequest
expect(originalRequest).toEqual(unserializedRequest);
the same serialization/unserialization for the response
function serializeResponse(angularResponse: HttpResponse): string {
return null; // to implement
}
function unserializeResponse(jsonResponse: string): HttpResponse {
return null; // to implement
}
// this is an example of response
const originalResponse = new HttpResponse({
headers: new HttpHeaders({
BAR: 'baz',
}),
status: 200,
statusText: 'OK',
url: '',
body: {foo: true}}
);
// serializeResponse trasform HttpResponse in json format
const jsonResponse: string = serializeResponse(originalRequest);
// unserializeResponse trasform json format to HttpResponse
const unserializedResponse: HttpResponse = unserializeResponse(jsonResponse);
// unserializedResponse as same object of originalResponse
expect(originalResponse).toEqual(unserializedResponse);
I want caching into the "localstorage" the HttpRequest and HttpResponse classes from @angular/mon/http
.
The localstorage
only accept string
, therefore i want serialize/unserialize both objects (HttpRequest and HttpResponse) with JSON.stringfy()
and JSON.parse()
.
The problem is HttpRequest
and HttpResponse
are both plex class with some ES6 Map (eg. HttpHeaders) and some getter/setter function, with JSON.stringfy()
and JSON.parse()
the serialization/unserialization don't return the same object and some information are lost.
There is a way for serialize/unserialize HttpRequest
and HttpResponse
class?
I'm searching for a plete serialization/unserialization (headers, params, body, etc)
In this example there is two method for serialize and unserialize HttpRequest, eg.:
function serializeRequest(angularRequest: HttpRequest): string {
return null; // to implement
}
function unserializeRequest(jsonRequest: string): HttpRequest {
return null; // to implement
}
// this is an example of request
const originalRequest = new HttpRequest('POST', 'https://angular.io/docs?foo=bar', {foo: true}, {
params: new HttpParams().set('verbose', 'true'),
headers: new HttpHeaders({
BAR: 'baz',
}),
reportProgress: true,
responseType: 'json',
withCredentials: true
});
// serializeRequest trasform HttpRequest in json format
const jsonRequest: string = serializeRequest(originalRequest);
// unserializeRequest trasform json format to HttpRequest
const unserializedRequest : HttpRequest = unserializeRequest(jsonRequest);
// unserializedRequest as same object of originalRequest
expect(originalRequest).toEqual(unserializedRequest);
the same serialization/unserialization for the response
function serializeResponse(angularResponse: HttpResponse): string {
return null; // to implement
}
function unserializeResponse(jsonResponse: string): HttpResponse {
return null; // to implement
}
// this is an example of response
const originalResponse = new HttpResponse({
headers: new HttpHeaders({
BAR: 'baz',
}),
status: 200,
statusText: 'OK',
url: 'https://angular.io/docs',
body: {foo: true}}
);
// serializeResponse trasform HttpResponse in json format
const jsonResponse: string = serializeResponse(originalRequest);
// unserializeResponse trasform json format to HttpResponse
const unserializedResponse: HttpResponse = unserializeResponse(jsonResponse);
// unserializedResponse as same object of originalResponse
expect(originalResponse).toEqual(unserializedResponse);
Share
Improve this question
edited Aug 16, 2020 at 16:43
Simone Nigro
asked Aug 12, 2020 at 14:33
Simone NigroSimone Nigro
4,9074 gold badges46 silver badges80 bronze badges
5
- did you try HttpInterceptor you can intercept all request and response header, body and params etc – Iam Coder Commented Aug 17, 2020 at 18:33
- Yes, the point is serialize/unserialize request/response – Simone Nigro Commented Aug 17, 2020 at 19:34
- Why are you trying to cache http request & response to local storage ? What is the use case? For in memory caching you can use npmjs./package/ngx-cacheable its really simple & useful Library. – Saurabh Gangamwar Commented Aug 23, 2020 at 6:07
- @Simone Nigro Do you want to serialize the class or the response? And also, what's your motivation?, maybe we can workaround this :) – WSD Commented Aug 23, 2020 at 7:06
- I need to serialize and unserialize to/from string both class (response/request) . The motivation is store both class into localstorage, for persistent cache. – Simone Nigro Commented Aug 23, 2020 at 8:24
3 Answers
Reset to default 2 +50Although I would remend a Service Worker for Caching, the easiest way that I know is to clone the request/response and then get their information:
function serializeRequest(req: HttpRequest<any>): string {
const request = req.clone(); // Make a clone, useful for doing destructive things
return JSON.stringify({
headers: Object.fromEntries( // Just a helper to make this into an object, not really required but makes the output nicer
request.headers.keys.map( // Get all of the headers
(key: string) => [key, request.headers.getAll(key)] // Get all of the corresponding values for the headers
)
),
method: request.method, // The Request Method, e.g. GET, POST, DELETE
url: request.url, // The URL
params: Object.fromEntries( // Just a helper to make this into an object, not really required but makes the output nicer
request.headers.keys.map( // Get all of the headers
(key: string) => [key, request.headers.getAll(key)] // Get all of the corresponding values for the headers
)
), // The request parameters
withCredentials: request.withCredentials, // Whether credentials are being sent
respnseType: request.responseType, // The response type
body: request.serializeBody() // Serialize the body, all well and good since we are working on a clone
})
}
In a similar fashion we can serialize the response as well (assuming T
is JSON patible, a fair assumption in an HTTP Request):
function serializeResponse(res: HttpResponse<any>): string {
const response = res.clone();
return JSON.stringify({
headers: Object.fromEntries( // Just a helper to make this into an object, not really required but makes the output nicer
response.headers.keys.map( // Get all of the headers
(key: string) => [key, response.headers.getAll(key)] // Get all of the corresponding values for the headers
)
),
status: response.status,
statusText: response.statusText,
url: response.url,
body: response // Serialize the body, all well and good since we are working on a clone
})
}
And then, since we saved all required information, deserialization is a walk in the park:
function deserializeRequest<T = any>(req: string): HttpRequest<T> {
const request = JSON.parse(req);
const headers = new HttpHeaders(request.headers);
const params = new HttpParams(); // Probably some way to make this a one-liner, but alas, there are no good docs
for(let parameter in request.params){
request.params[parameter].forEach((paramValue: string) => params.append(parameter, paramValue));
}
return new HttpRequest(request.method, request.url, request.body, {
headers,
params,
respnseType: request.respnseType,
withCredentials: request.withCredentials
});
}
function deserializeResponse<T = any>(res: string): HttpResponse<T> {
const response = JSON.parse(res);
const headers = new HttpHeaders(response.headers);
return new HttpRequest({
headers,
body: response.body,
status: response.status,
statusText: response.statusText,
url: response.url,
});
}
Playground of the whole thing (although, regrettably the angular types do not load correctly)
Note that I have not tested this in any environment, so this is provided AS-IS, and I am not sure how
expect
would handle twoHttpHeaders
/HttpParams
, especially since they may not have the exact same order.
If you just want to serialize the HttpRequest
then the class itself provides serializeBody()
method, here
The below mentioned way is the best way of serialize the HttpResponse in Angular. res.json() function will show you the body,headers and params.
this.http.get('/app/lists.json').map((res:Response) => res.json());