6

I am using Angular2 RC5 (core, http, etc) and trying to connect to a CORS enabled Node.js server. My application is fresh generated from Angular-CLI (version: "1.0.0-beta.11-webpack.2").

// src/app/app.component.ts
...
ngOnInit () {
   const headers: Headers = new Headers();
   headers.append('Accept', 'application/json');
   headers.append('Content-Type', 'application/json');
   headers.append('Access-Control-Allow-Origin', '*');

   const options = new RequestOptions({
     headers: headers
   });

   this.http.get('http://localhost:9000/api/v1/users', options)
    .map((res: Response) => res.json())
    .subscribe(users => console.log(users));
}

...

When the application starts, the OnInit hook got called, I got an error in the console. Here is the error message that I got.

EXCEPTION: TypeError: Cannot read property 'toString' of null
browser_adapter.js:84EXCEPTION: TypeError: Cannot read property 'toString' of nullBrowserDomAdapter.logError @ browser_adapter.js:84BrowserDomAdapter.logGroup @ browser_adapter.js:94ExceptionHandler.call @ exception_handler.js:65(anonymous function) @ application_ref.js:267ZoneDelegate.invoke @ zone.js:323onInvoke @ ng_zone_impl.js:53ZoneDelegate.invoke @ zone.js:322Zone.run @      zone.js:216(anonymous function) @ zone.js:571ZoneDelegate.invokeTask @ zone.js:356onInvokeTask @ ng_zone_impl.js:44ZoneDelegate.invokeTask @ zone.js:355Zone.runTask @ zone.js:256drainMicroTaskQueue @ zone.js:474
zone.js:461 Unhandled Promise rejection: Cannot read property 'toString' of null ; Zone: <root> ; Task: Promise.then ; Value: TypeError: Cannot read property 'toString' of null(…)consoleError @ zone.js:461_loop_1 @ zone.js:490drainMicroTaskQueue @ zone.js:494
zone.js:463 Error: Uncaught (in promise): TypeError: Cannot read property 'toString' of null(…)

If I drop off the options and header completely, I got CORS error but response status 200 from the server. (I guess that If I can pass the correct Header, it should work. )

 this.http.get('http://localhost:9000/api/v1/users')
  .map((res: Response) => res.json())
  .subscribe(users => console.log(users)); 

Here is the error from the console

XMLHttpRequest cannot load http://localhost:4000/api/v1/users. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access.
browser_adapter.js:93EXCEPTION: Response with status: 0  for URL: null
browser_adapter.js:84EXCEPTION: Response with status: 0  for URL: nullBrowserDomAdapter.logError @         browser_adapter.js:84BrowserDomAdapter.logGroup @    browser_adapter.js:94ExceptionHandler.call @ exception_handler.js:65next @ application_ref.js:348schedulerFn @ async.js:89SafeSubscriber.__tryOrUnsub @ Subscriber.js:225SafeSubscriber.next @ Subscriber.js:174Subscriber._next @ Subscriber.js:124Subscriber.next @ Subscriber.js:88Subject._finalNext @     Subject.js:128Subject._next @ Subject.js:120Subject.next @ Subject.js:77EventEmitter.emit @ async.js:77onHandleError @ ng_zone_impl.js:74ZoneDelegate.handleError @ zone.js:327Zone.runTask @ zone.js:259ZoneTask.invoke @ zone.js:423
Subscriber.js:229Uncaught Response with status: 0  for URL: null

Can someone help, please? thanks.

MMA
  • 525
  • 1
  • 10
  • 19

3 Answers3

4

I am a newbie so bear with me please, but as far as I am concerned the Access-Control-Allow-Origin header should be returned by the backend Node.js server. CORS on server side is disabled by default due to security. Use the following question to help you with implementation: How to allow CORS?

Community
  • 1
  • 1
Mike Spencer
  • 85
  • 2
  • 10
  • 1
    Thank you for commenting. My server is enabled CORS and should be able to return the payload. Here is more generic question, if I simply want to pass custom header value via Angular2 HTTP, how can I do that? I did it in the beta version of Angular2. Now in RC5, does @angular/http change its calling signature? – MMA Aug 14 '16 at 14:59
  • 1
    In that case I am scared that I won't be able to help you. Your code seems perfectly legitimate to me. I will try to reproduce the problem tomorrow. – Mike Spencer Aug 14 '16 at 18:15
  • 1
    Still, I suggest you check that there is 'Access-Control-Allow-Origin' header present on the response from the server given that the second error suggests otherwise. Also please note that 'Access-Control-Allow-Origin' header is response header and there is no reason to put it on the request. – Mike Spencer Aug 14 '16 at 18:30
  • 1
    Mike, You are right on 'Access-Control-Allow-Origin' header present on the response. The issue is not from angular2 code. It is the server side problem. I am not using Express, instead of a brand new framework called egg.js. So many things that I am still trying to figure out. Well, I finally nailed down the issue and fixed on the server side. – MMA Aug 15 '16 at 04:51
1

Your problem is caused by a bug introduced in rc5. The XHRBackend for Http was modified to convert the body of any request into a string. It looks at the Content-Type header and attempts to call the appropriate conversion method.

In your code above, you are setting the Content-Type header to application/json which causes the XHRBackend to try to convert it into a string. However, since you're making a GET request, body is null, so this exception is being thrown.

In your case, just remove the Content-Type header, and everything should work fine.

TedCHoward
  • 151
  • 6
1

It is written about here:

https://github.com/angular/angular/issues/10612

To resolve

EXCEPTION: TypeError: Cannot read property 'toString' of null

you need to set body to ''

headers.append('body', '');
ganjan
  • 6,443
  • 22
  • 74
  • 126