
There is a weirdness in the Angular Location service. If the `baseHref` is only a single slash (`'/'`) then it changes it to be an empty string (`''`). The effect of this is that `Location.normaliseUrl(url)` does not strip off the leading slash from url paths. The problem is that the leading slash only appears on the initial Location path, and not on urls that arrive from subscribing to the Location service. This commit is a workaround this problem.
69 lines
2.1 KiB
TypeScript
69 lines
2.1 KiB
TypeScript
import { Injectable } from '@angular/core';
|
|
import { Http, Response } from '@angular/http';
|
|
|
|
import { Observable } from 'rxjs/Observable';
|
|
import { AsyncSubject } from 'rxjs/AsyncSubject';
|
|
import 'rxjs/add/operator/switchMap';
|
|
|
|
import { LocationService } from 'app/shared/location.service';
|
|
import { Logger } from 'app/shared/logger.service';
|
|
|
|
const FILE_NOT_FOUND_URL = 'file-not-found';
|
|
|
|
export interface DocumentContents {
|
|
title: string;
|
|
contents: string;
|
|
}
|
|
|
|
@Injectable()
|
|
export class DocumentService {
|
|
|
|
private cache = new Map<string, Observable<DocumentContents>>();
|
|
private fileNotFoundPath = this.computePath(FILE_NOT_FOUND_URL);
|
|
|
|
currentDocument: Observable<DocumentContents>;
|
|
|
|
constructor(private logger: Logger, private http: Http, location: LocationService) {
|
|
// Whenever the URL changes we try to get the appropriate doc
|
|
this.currentDocument = location.currentUrl.switchMap(url => this.getDocument(url));
|
|
}
|
|
|
|
private getDocument(url: string) {
|
|
this.logger.log('getting document', url);
|
|
const path = this.computePath(url);
|
|
if ( !this.cache.has(path)) {
|
|
this.cache.set(path, this.fetchDocument(path));
|
|
}
|
|
return this.cache.get(path);
|
|
}
|
|
|
|
private fetchDocument(path: string) {
|
|
this.logger.log('fetching document from', path);
|
|
const subject = new AsyncSubject();
|
|
this.http
|
|
.get(path)
|
|
.map(res => res.json())
|
|
.catch((error: Response) => {
|
|
if (error.status === 404) {
|
|
if (path !== this.fileNotFoundPath) {
|
|
this.logger.error(`Document file not found at '${path}'`);
|
|
// using `getDocument` means that we can fetch the 404 doc contents from the server and cache it
|
|
return this.getDocument(FILE_NOT_FOUND_URL);
|
|
} else {
|
|
return Observable.of({ title: 'Not Found', contents: 'Document not found' });
|
|
}
|
|
} else {
|
|
throw error;
|
|
}
|
|
})
|
|
.subscribe(subject);
|
|
return subject.asObservable();
|
|
}
|
|
|
|
private computePath(url) {
|
|
url = '/' + url;
|
|
url = url.endsWith('/') ? url + 'index' : url;
|
|
return 'content/docs' + url + '.json';
|
|
}
|
|
}
|