forked from DSpace/dspace-angular
-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request DSpace#3358 from 4Science/task/main/DURACOM-288
Provide a setting to use a different REST url during SSR execution
- Loading branch information
Showing
18 changed files
with
695 additions
and
266 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
194 changes: 194 additions & 0 deletions
194
src/app/core/dspace-rest/dspace-rest.interceptor.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
import { | ||
HTTP_INTERCEPTORS, | ||
HttpClient, | ||
} from '@angular/common/http'; | ||
import { | ||
HttpClientTestingModule, | ||
HttpTestingController, | ||
} from '@angular/common/http/testing'; | ||
import { PLATFORM_ID } from '@angular/core'; | ||
import { TestBed } from '@angular/core/testing'; | ||
|
||
import { | ||
APP_CONFIG, | ||
AppConfig, | ||
} from '../../../config/app-config.interface'; | ||
import { DspaceRestInterceptor } from './dspace-rest.interceptor'; | ||
import { DspaceRestService } from './dspace-rest.service'; | ||
|
||
describe('DspaceRestInterceptor', () => { | ||
let httpMock: HttpTestingController; | ||
let httpClient: HttpClient; | ||
const appConfig: Partial<AppConfig> = { | ||
rest: { | ||
ssl: false, | ||
host: 'localhost', | ||
port: 8080, | ||
nameSpace: '/server', | ||
baseUrl: 'http://api.example.com/server', | ||
}, | ||
}; | ||
const appConfigWithSSR: Partial<AppConfig> = { | ||
rest: { | ||
ssl: false, | ||
host: 'localhost', | ||
port: 8080, | ||
nameSpace: '/server', | ||
baseUrl: 'http://api.example.com/server', | ||
ssrBaseUrl: 'http://ssr.example.com/server', | ||
}, | ||
}; | ||
|
||
describe('When SSR base URL is not set ', () => { | ||
describe('and it\'s in the browser', () => { | ||
beforeEach(() => { | ||
TestBed.configureTestingModule({ | ||
imports: [HttpClientTestingModule], | ||
providers: [ | ||
DspaceRestService, | ||
{ | ||
provide: HTTP_INTERCEPTORS, | ||
useClass: DspaceRestInterceptor, | ||
multi: true, | ||
}, | ||
{ provide: APP_CONFIG, useValue: appConfig }, | ||
{ provide: PLATFORM_ID, useValue: 'browser' }, | ||
], | ||
}); | ||
|
||
httpMock = TestBed.inject(HttpTestingController); | ||
httpClient = TestBed.inject(HttpClient); | ||
}); | ||
|
||
it('should not modify the request', () => { | ||
const url = 'http://api.example.com/server/items'; | ||
httpClient.get(url).subscribe((response) => { | ||
expect(response).toBeTruthy(); | ||
}); | ||
|
||
const req = httpMock.expectOne(url); | ||
expect(req.request.url).toBe(url); | ||
req.flush({}); | ||
httpMock.verify(); | ||
}); | ||
}); | ||
|
||
describe('and it\'s in SSR mode', () => { | ||
beforeEach(() => { | ||
TestBed.configureTestingModule({ | ||
imports: [HttpClientTestingModule], | ||
providers: [ | ||
DspaceRestService, | ||
{ | ||
provide: HTTP_INTERCEPTORS, | ||
useClass: DspaceRestInterceptor, | ||
multi: true, | ||
}, | ||
{ provide: APP_CONFIG, useValue: appConfig }, | ||
{ provide: PLATFORM_ID, useValue: 'server' }, | ||
], | ||
}); | ||
|
||
httpMock = TestBed.inject(HttpTestingController); | ||
httpClient = TestBed.inject(HttpClient); | ||
}); | ||
|
||
it('should not replace the base URL', () => { | ||
const url = 'http://api.example.com/server/items'; | ||
|
||
httpClient.get(url).subscribe((response) => { | ||
expect(response).toBeTruthy(); | ||
}); | ||
|
||
const req = httpMock.expectOne(url); | ||
expect(req.request.url).toBe(url); | ||
req.flush({}); | ||
httpMock.verify(); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('When SSR base URL is set ', () => { | ||
describe('and it\'s in the browser', () => { | ||
beforeEach(() => { | ||
TestBed.configureTestingModule({ | ||
imports: [HttpClientTestingModule], | ||
providers: [ | ||
DspaceRestService, | ||
{ | ||
provide: HTTP_INTERCEPTORS, | ||
useClass: DspaceRestInterceptor, | ||
multi: true, | ||
}, | ||
{ provide: APP_CONFIG, useValue: appConfigWithSSR }, | ||
{ provide: PLATFORM_ID, useValue: 'browser' }, | ||
], | ||
}); | ||
|
||
httpMock = TestBed.inject(HttpTestingController); | ||
httpClient = TestBed.inject(HttpClient); | ||
}); | ||
|
||
it('should not modify the request', () => { | ||
const url = 'http://api.example.com/server/items'; | ||
httpClient.get(url).subscribe((response) => { | ||
expect(response).toBeTruthy(); | ||
}); | ||
|
||
const req = httpMock.expectOne(url); | ||
expect(req.request.url).toBe(url); | ||
req.flush({}); | ||
httpMock.verify(); | ||
}); | ||
}); | ||
|
||
describe('and it\'s in SSR mode', () => { | ||
beforeEach(() => { | ||
TestBed.configureTestingModule({ | ||
imports: [HttpClientTestingModule], | ||
providers: [ | ||
DspaceRestService, | ||
{ | ||
provide: HTTP_INTERCEPTORS, | ||
useClass: DspaceRestInterceptor, | ||
multi: true, | ||
}, | ||
{ provide: APP_CONFIG, useValue: appConfigWithSSR }, | ||
{ provide: PLATFORM_ID, useValue: 'server' }, | ||
], | ||
}); | ||
|
||
httpMock = TestBed.inject(HttpTestingController); | ||
httpClient = TestBed.inject(HttpClient); | ||
}); | ||
|
||
it('should replace the base URL', () => { | ||
const url = 'http://api.example.com/server/items'; | ||
const ssrBaseUrl = appConfigWithSSR.rest.ssrBaseUrl; | ||
|
||
httpClient.get(url).subscribe((response) => { | ||
expect(response).toBeTruthy(); | ||
}); | ||
|
||
const req = httpMock.expectOne(ssrBaseUrl + '/items'); | ||
expect(req.request.url).toBe(ssrBaseUrl + '/items'); | ||
req.flush({}); | ||
httpMock.verify(); | ||
}); | ||
|
||
it('should not replace any query param containing the base URL', () => { | ||
const url = 'http://api.example.com/server/items?url=http://api.example.com/server/item/1'; | ||
const ssrBaseUrl = appConfigWithSSR.rest.ssrBaseUrl; | ||
|
||
httpClient.get(url).subscribe((response) => { | ||
expect(response).toBeTruthy(); | ||
}); | ||
|
||
const req = httpMock.expectOne(ssrBaseUrl + '/items?url=http://api.example.com/server/item/1'); | ||
expect(req.request.url).toBe(ssrBaseUrl + '/items?url=http://api.example.com/server/item/1'); | ||
req.flush({}); | ||
httpMock.verify(); | ||
}); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { isPlatformBrowser } from '@angular/common'; | ||
import { | ||
HttpEvent, | ||
HttpHandler, | ||
HttpInterceptor, | ||
HttpRequest, | ||
} from '@angular/common/http'; | ||
import { | ||
Inject, | ||
Injectable, | ||
PLATFORM_ID, | ||
} from '@angular/core'; | ||
import { Observable } from 'rxjs'; | ||
|
||
import { | ||
APP_CONFIG, | ||
AppConfig, | ||
} from '../../../config/app-config.interface'; | ||
import { isEmpty } from '../../shared/empty.util'; | ||
|
||
@Injectable() | ||
/** | ||
* This Interceptor is used to use the configured base URL for the request made during SSR execution | ||
*/ | ||
export class DspaceRestInterceptor implements HttpInterceptor { | ||
|
||
/** | ||
* Contains the configured application base URL | ||
* @protected | ||
*/ | ||
protected baseUrl: string; | ||
protected ssrBaseUrl: string; | ||
|
||
constructor( | ||
@Inject(APP_CONFIG) protected appConfig: AppConfig, | ||
@Inject(PLATFORM_ID) private platformId: string, | ||
) { | ||
this.baseUrl = this.appConfig.rest.baseUrl; | ||
this.ssrBaseUrl = this.appConfig.rest.ssrBaseUrl; | ||
} | ||
|
||
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { | ||
if (isPlatformBrowser(this.platformId) || isEmpty(this.ssrBaseUrl) || this.baseUrl === this.ssrBaseUrl) { | ||
return next.handle(request); | ||
} | ||
|
||
// Different SSR Base URL specified so replace it in the current request url | ||
const url = request.url.replace(this.baseUrl, this.ssrBaseUrl); | ||
const newRequest: HttpRequest<any> = request.clone({ url }); | ||
return next.handle(newRequest); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.