add support for multiple request methods

This commit is contained in:
Art Lowel
2017-11-29 16:47:40 +01:00
parent 84ea88c56b
commit 98a49b3191
5 changed files with 95 additions and 12 deletions

View File

@@ -5,6 +5,12 @@ import {
import { hasValue } from '../../shared/empty.util';
import { CacheEntry } from './cache-entry';
export enum DirtyType {
Created = 'Created',
Updated = 'Updated',
Deleted = 'Deleted'
}
/**
* An interface to represent objects that can be cached
*
@@ -13,6 +19,11 @@ import { CacheEntry } from './cache-entry';
export interface CacheableObject {
uuid?: string;
self: string;
// isNew: boolean;
// dirtyType: DirtyType;
// hasDirtyAttributes: boolean;
// changedAttributes: AttributeDiffh;
// save(): void;
}
/**

View File

@@ -6,12 +6,19 @@ import { RemoteDataBuildService } from '../cache/builders/remote-data-build.serv
import { CacheableObject } from '../cache/object-cache.reducer';
import { ResponseCacheService } from '../cache/response-cache.service';
import { CoreState } from '../core.reducers';
import { DSpaceObject } from '../shared/dspace-object.model';
import { GenericConstructor } from '../shared/generic-constructor';
import { HALEndpointService } from '../shared/hal-endpoint.service';
import { RemoteData } from './remote-data';
import { FindAllOptions, FindAllRequest, FindByIDRequest, RestRequest } from './request.models';
import { RequestService } from './request.service';
import { URLCombiner } from '../url-combiner/url-combiner';
import { RemoteData } from './remote-data';
import {
FindAllOptions,
FindAllRequest,
FindByIDRequest,
RestRequest,
RestRequestMethod
} from './request.models';
import { RequestService } from './request.service';
export abstract class DataService<TNormalized extends CacheableObject, TDomain> extends HALEndpointService {
protected abstract responseCache: ResponseCacheService;
@@ -102,4 +109,20 @@ export abstract class DataService<TNormalized extends CacheableObject, TDomain>
return this.rdbService.buildSingle<TNormalized, TDomain>(href, this.normalizedResourceType);
}
create(dso: DSpaceObject): Observable<RemoteData<TDomain>> {
const postHrefObs = this.getEndpoint();
// TODO ID is unknown at this point
const idHrefObs = postHrefObs.map((href: string) => this.getFindByIDHref(href, dso.id));
postHrefObs
.filter((href: string) => hasValue(href))
.take(1)
.subscribe((href: string) => {
const request = new RestRequest(href, RestRequestMethod.Post, dso);
this.requestService.configure(request);
});
return this.rdbService.buildSingle<TNormalized, TDomain>(idHrefObs, this.normalizedResourceType);
}
}

View File

@@ -1,18 +1,23 @@
import { Inject, Injectable, Injector } from '@angular/core';
import { Request } from '@angular/http';
import { RequestArgs } from '@angular/http/src/interfaces';
import { Actions, Effect } from '@ngrx/effects';
// tslint:disable-next-line:import-blacklist
import { Observable } from 'rxjs';
import { GLOBAL_CONFIG, GlobalConfig } from '../../../config';
import { isNotEmpty } from '../../shared/empty.util';
import { ErrorResponse, RestResponse } from '../cache/response-cache.models';
import { ResponseCacheService } from '../cache/response-cache.service';
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
import { DSpaceRESTv2Service } from '../dspace-rest-v2/dspace-rest-v2.service';
import { RequestActionTypes, RequestCompleteAction, RequestExecuteAction } from './request.actions';
import { RequestError } from './request.models';
import { RequestError, RestRequest } from './request.models';
import { RequestEntry } from './request.reducer';
import { RequestService } from './request.service';
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer';
import { NormalizedObjectFactory } from '../cache/models/normalized-object-factory';
@Injectable()
export class RequestEffects {
@@ -23,15 +28,24 @@ export class RequestEffects {
return this.requestService.get(action.payload)
.take(1);
})
.flatMap((entry: RequestEntry) => {
return this.restApi.get(entry.request.href)
.map((entry: RequestEntry) => entry.request)
.flatMap((request: RestRequest) => {
const httpRequestConfig: RequestArgs = {
method: request.method,
url: request.href
};
if (isNotEmpty(request.body)) {
const serializer = new DSpaceRESTv2Serializer(NormalizedObjectFactory.getConstructor(request.body.type));
httpRequestConfig.body = JSON.stringify(serializer.serialize(request.body));
}
return this.restApi.request(new Request(httpRequestConfig))
.map((data: DSpaceRESTV2Response) =>
this.injector.get(entry.request.getResponseParser()).parse(entry.request, data))
.do((response: RestResponse) => this.responseCache.add(entry.request.href, response, this.EnvConfig.cache.msToLive))
.map((response: RestResponse) => new RequestCompleteAction(entry.request.href))
this.injector.get(request.getResponseParser()).parse(request, data))
.do((response: RestResponse) => this.responseCache.add(request.href, response, this.EnvConfig.cache.msToLive))
.map((response: RestResponse) => new RequestCompleteAction(request.href))
.catch((error: RequestError) => Observable.of(new ErrorResponse(error))
.do((response: RestResponse) => this.responseCache.add(entry.request.href, response, this.EnvConfig.cache.msToLive))
.map((response: RestResponse) => new RequestCompleteAction(entry.request.href)));
.do((response: RestResponse) => this.responseCache.add(request.href, response, this.EnvConfig.cache.msToLive))
.map((response: RestResponse) => new RequestCompleteAction(request.href)));
});
constructor(

View File

@@ -9,9 +9,21 @@ import { BrowseResponseParsingService } from './browse-response-parsing.service'
import { ConfigResponseParsingService } from './config-response-parsing.service';
/* tslint:disable:max-classes-per-file */
export enum RestRequestMethod {
Get = 'GET',
Post = 'POST',
Put = 'PUT',
Delete = 'DELETE',
Options = 'OPTIONS',
Head = 'HEAD',
Patch = 'PATCH'
}
export class RestRequest {
constructor(
public href: string,
public method: RestRequestMethod = RestRequestMethod.Get,
public body?: any
) { }
getResponseParser(): GenericConstructor<ResponseParsingService> {

View File

@@ -1,11 +1,12 @@
import { Inject, Injectable } from '@angular/core';
import { Http, RequestOptionsArgs } from '@angular/http';
import { Http, RequestOptionsArgs, Request } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { RESTURLCombiner } from '../url-combiner/rest-url-combiner';
import { DSpaceRESTV2Response } from './dspace-rest-v2-response.model';
import { GLOBAL_CONFIG, GlobalConfig } from '../../../config';
import { RestRequest } from '../data/request.models';
/**
* Service to access DSpace's REST API
@@ -36,4 +37,26 @@ export class DSpaceRESTv2Service {
});
}
/**
* Performs a request to the REST API.
*
* @param httpRequest
* A Request object
* @return {Observable<string>}
* An Observable<string> containing the response from the server
*/
request(httpRequest: Request): Observable<DSpaceRESTV2Response> {
// const httpRequest = new Request({
// method: request.method,
// url: request.href,
// body: request.body
// });
return this.http.request(httpRequest)
.map((res) => ({ payload: res.json(), statusCode: res.statusText }))
.catch((err) => {
console.log('Error: ', err);
return Observable.throw(err);
});
}
}