Implementing the odata standard which utilizes ETag has presented a challenge for me, particularly with PATCH requests. Each PATCH request requires sending the ETag in the header as If-None-Match
. A HTTP status of 200 indicates that the change was successfully applied, while a status of 412 signifies that the data on the server has been modified and needs to be fetched again for merging (which is beyond the scope of this question).
I've managed to create a working solution so far, where adding data and Etag to cache is done in the implementation of the get()
method:
export const HEADER_ETAG_MATCH = 'If-None-Match';
export const ODATA_ETAG_PROPERTY = '@odata.etag';
export interface CacheRecordStructure {
etag: string;
response: Response;
}
export class CachingService {
cache: { [key: string]: CacheRecordStructure } = {};
constructor(private http: Http) { }
patch(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
let stream$ = new Subject<Response>();
this.http[type](url, body, this.addEtagHeader(url, options)).subscribe(response => {
if (response.status === 412) {
delete this.cache[url];
this.get(url, options).subscribe(response2 => {
response2.status = 412;
stream$.next(response2);
});
} else {
this.cache[url].etag = response.json()[ODATA_ETAG_PROPERTY];
this.cache[url].response = response;
stream$.next(response);
}
});
return stream$.asObservable();
}
}
Question 1: How can I alter this code to use Rx-only without having to define stream$
?
Question 2: I would like to throw an error instead of returning status 412. Is it possible to include the newly fetched object from the server along with this error?