add full path to base href in Angular

Viewed 219

I want to get the base href in Angular including the domain (or subdomain)

use case:

I want to add ogg:image property using Meta service. the current content looks like /image.jpg but I want it to be https://example.com/image.jpg so it can be fetched properly by social media platforms.

note: I use SSR.

2 Answers

We do something related in our app-config.service.ts, where the URI lib will parse it for you const { scheme, host, path } = URI.parse(window.location.href);

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { tap, concatMap, catchError } from 'rxjs/operators';
import * as URI from 'uri-js';
import { Observable } from 'rxjs';
import { environment } from '../../../environments/environment';

@Injectable({
    providedIn: 'root',
})
export class AppConfigService {
    public config?: {} = {};
    private env?: {} = {};

    constructor(private readonly http: HttpClient) {
        this.getHostBase();
    }

    /**
     * Use to get the data found in the second file (config file)
     */
    public getConfig(key: any) {
        return this.config[key];
    }

    /**
     * Use to get the data found in the first file (env file)
     */
    public getEnv(key: any) {
        return this.env[key];
    }

    /**
     * This method:
     *   a) Loads "env.json" to get the current working environment (e.g.: 'production', 'development')
     *   b) Loads "config.[env].json" to get all env's variables (e.g.: 'config.development.json')
     */
    public load(): any {        
        return new Promise((resolve) => {
            this.http
                .get('assets/env.json')
                .pipe(
                    catchError((): any => {
                        resolve(true);
                    }),
                )
                .subscribe((envResponse: any) => {
                    this.env = envResponse;
                    const request = this.http.get(`assets/config.${envResponse.env}.json`);

                    if (request !== undefined) {
                        request
                            .pipe(
                                catchError((error: any): any => {
                                    resolve(true);
                                }),
                            )
                            .subscribe((responseData: object) => {
                                this.config = { ...this.config, ...responseData };
                                resolve(true);
                            });
                    } else {
                        resolve(true);
                    }
                });
        });
    }

    public get host(): string | undefined {
        return this.getConfig('api');
    }

    private getHostBase(): void {
        const { scheme, host, path } = URI.parse(window.location.href);
       
        this.config['host'] = URI.serialize({ scheme, host, path: `${cleanPath}/` });
        this.config['api'] = URI.serialize({ scheme, host, path: `${cleanPath}/api/` });
        
    }
}

You can see that we build the final URLs here: const { scheme, host, path } = URI.parse(window.location.href);

You can use Document.location.origin: https://developer.mozilla.org/en-US/docs/Web/API/Location - note that you have to inject the Document Object when using SRR (instead of just using the global document object).

Code example

class UrlService {
  constructor(@Inject(DOCUMENT) private document: Document,
              private router: Router) {}

  getOrigin(): string {
    return this.document.location.origin;
  }

  getPath(): string {
    return this.router.url;
  }
}
Related