1

I created an angular universal app with angular2 where I am requesting /category service.

this.hsService.getCategories(AppConstants.BASE_URL_GET_CATGORIES).subscribe(
  resp => {
    if (resp !== null) {
      console.log('response is not null');
    }else {
      console.log('response is null');
    }
  },
  err => {
    console.log('error');
    that.categories = that.Categories();
  }
);

But I got this error below error. But did not understand why?

ERROR Error: URLs requested via Http on the server must be absolute. URL: /category at validateRequestUrl (D:\Myprojects\angular universal\ciel\node_modules\@angular\platform-server\bundles\platform-server.umd.js:99:15 at new ZoneMacroTaskConnection (D:\Myprojects\angular universal\ciel\node_modules\@angular\platform-server\bundles\platform-server.umd.js:226:9) at ZoneMacroTaskBackend.createConnection (D:\Myprojects\angular universal\ciel\node_modules\@angular\platform-server\bundles\platform-server.umd.js:262:16) at httpRequest (D:\Myprojects\angular universal\ciel\node_modules\@angular\http\bundles\http.umd.js:1833:20) at Http.request (D:\Myprojects\angular universal\ciel\node_modules\@angular\http\bundles\http.umd.js:1943:34) at Http.get (D:\Myprojects\angular universal\ciel\node_modules\@angular\http\bundles\http.umd.js:1957:21) at n.getCategories (D:\Myprojects\angular universal\ciel\dist-server\main.bundle.js:1:26301) at n.XV61.n.getCategories (D:\Myprojects\angular universal\ciel\dist-server\main.bundle.js:1:24428) at n.XV61.n.ngOnInit (D:\Myprojects\angular universal\ciel\dist-server\main.bundle.js:1:24346) at checkAndUpdateDirectiveInline (D:\Myprojects\angular universal\ciel\node_modules\@angular\core\bundles\core.umd.js:10875:19)

Can anybody help me?

Vikas
  • 11,859
  • 7
  • 45
  • 69
Himani
  • 37
  • 8
  • 1
    It appears that Http requests in that API must be fully formed URLS such as `http://www.someDomain.com/somePath`. It appears you're trying to make a request to `/category`. Apparently you can't do that. Some code somewhere will have to include a protocol and domain with that. – jfriend00 May 27 '18 at 15:43

2 Answers2

2

In server-side rendering, any HTTP calls will need the absolute URL.

You can either

  1. Use absolute URLs for HTTP requests
  2. Inject the origin URL and prepend to base URL server-side

There are multiple workarounds to do option 2 in the answers to this question.

I personally would suggest configuring an injection token that gives you the server's origin and add it to the base URL using HTTP interceptors:

Add HTTP interceptor class:

import { Injectable, Inject, Optional } from '@angular/core';
import { HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';

@Injectable()
export class UniversalInterceptor implements HttpInterceptor {

  constructor(@Optional() @Inject('serverUrl') protected serverUrl: string) {}

  intercept(req: HttpRequest<any>, next: HttpHandler) {

    const serverReq = !this.serverUrl ? req : req.clone({
      url: `${this.serverUrl}${req.url}`
    });

    return next.handle(serverReq);

  }
}

Add it to server-side module's providers array:

providers: [
{
  provide: HTTP_INTERCEPTORS,
  useClass: UniversalInterceptor,
  multi: true
}

In your server-side configuration (express in this example), provide the token with the server's origin URL:

let protocol = 'http';
if (process.env.NODE_ENV == 'production') {
   protocol = 'https'
}

app.engine('html', (_, options, callback) => {
  let engine = ngExpressEngine({
    bootstrap: AppServerModuleNgFactory,
    providers: [
      provideModuleMap(LAZY_MODULE_MAP),
      {
        provide: 'serverUrl',
        useValue: `${protocol}://${options.req.get('host')}`
      }
    ]
  });

  engine(_, options, callback)
})
Joshua Chan
  • 1,797
  • 8
  • 16
  • Thanks for pointing out, protocol can be either http, https or any that your server is using. Edited the answer to include a general way of initialising the variable. – Joshua Chan Jan 23 '19 at 05:44
1

ERROR Error: URLs requested via Http on the server must be absolute.

Looking like AppConstants.BASE_URL_GET_CATGORIES is undefined or invalid http URL.

I think you need to inject the origin url to create absolute path

export function createTranslateLoader(http: Http, @Inject('AppConstants.BASE_URL_GET_CATGORIES') originUrl: string) {
  return new TranslateHttpLoader(http, originUrl);
}
Debug Diva
  • 26,058
  • 13
  • 70
  • 123