angular: HTTP throws "_private__.getDOM(...).getCookie is not a function" if used before bootstrap

I’m submitting a … (check one with “x”)

[x] bug report
[ ] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior After update to 2.0.0-rc.2 I get this error:

// Chrome
Uncaught TypeError: Cannot read property 'getCookie' of null

// FireFox
TypeError: platform_browser_1.__platform_browser_private__.getDOM(...) is null

// Safari
TypeError: null is not an object (evaluating 'platform_browser_1.__platform_browser_private__.getDOM().getCookie')

pointing to second line of this part of code:

        CookieXSRFStrategy.prototype.configureRequest = function (req) {
            var xsrfToken = platform_browser_1.__platform_browser_private__.getDOM().getCookie(this._cookieName);
            if (xsrfToken && !req.headers.has(this._headerName)) {
                req.headers.set(this._headerName, xsrfToken);
            }
        };

Reproduction of the problem It happens when I try to send GET request before app bootstrap:

import { ReflectiveInjector } from '@angular/core'
import { HTTP_PROVIDERS } from '@angular/http'

import { AuthDao } from '…some/place/in/app'

ReflectiveInjector.resolveAndCreate([...HTTP_PROVIDERS, AuthDao])
  .get(AuthDao)
  .check()

and AuthDao’s class check() method looks like this:

import { Observable } from 'rxjs/Observable'
import { Response, Headers, Http } from '@angular/http'

@Injectable()
export class AuthDao {

  constructor(http: Http) {}

  public check(): Observable<Response> {
    return this._http.get('/do/some/check', { 
      headers: new Headers({ 'Accept': 'text/plain;charset=UTF-8' }) 
    })
  }

  …

  • Angular version: 2.0.0-rc.2
  • Browser: [ Chrome 51.0.2704.84 (64-bit) | Firefox 45.0.2 | Safari 9.1.1 ]
  • Language: [ TypeScript 1.8 ]

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 3
  • Comments: 24 (9 by maintainers)

Most upvoted comments

Ok it works, but IMO it’s odd that one have to hack his favourite framework to make it just work 😦

new version of my code:

import { ReflectiveInjector } from '@angular/core'
import { HTTP_PROVIDERS, Request, XSRFStrategy } from '@angular/http'

import { AuthDao } from '…some/place/in/app'

class FakeXSRFStrategy implements XSRFStrategy {
  public configureRequest(req: Request) { /* */ }
}

const XRSF_MOCK = provide(XSRFStrategy, { useValue: new FakeXSRFStrategy() })

ReflectiveInjector.resolveAndCreate([...HTTP_PROVIDERS, XRSF_MOCK, AuthDao])
  .get(AuthDao)
  .check()

Living snippet for anyone who will fall into this issue.

@NathanWalker it’s already injectable - see https://github.com/angular/angular/blob/master/modules/%40angular/http/http.ts#L183

So you could mock it out as described, no?

This will be fixed in rc5

I believe that this problem exists only if you use http before you bootstrap. Can you confirm?

(explanation/notes: this happens because http depends on BrowserAdapter for access to cookies and we initialize BrowserAdapter only during bootstrap, so if you try to access getDom() before bootstrap you get nothing and that causes that call to fetch cookies to fail)

There should be no DOM dependency here at all actually. Having this line:

var xsrfToken = platform_browser_1.__platform_browser_private__.getDOM().getCookie(this._cookieName);

Causes issues with multi-platform integrations like NativeScript https://github.com/NativeScript/nativescript-angular

It would be great if this could come purely from an Injectable and not used explicitly. https://github.com/angular/angular/blob/master/modules/%40angular/http/src/backends/xhr_backend.ts#L152-L162 is not an Injectable and therefore requires multi-platform integration to provide an entire different XHRBackend to swap out the CookieXSRFStrategy which presents this problem.

Would be nice if we could just do this: provide(CookieXSRFStrategy, {useClass: NativeXSRFStrategy})