2

I think it can be common problem for many other developers, but I didn't found some efficient solution yet.

I'm working on Angular2 project. Of course I have many places when I need to make http calls to manage my data. So I'm using Http service and everything works as expected.

On some architecture stage (when team have implemented most of pages), new requirement comes into place - now we need to connect deeper our server and client so additional header should be added to all requests initiated from client (it can be authenticated bearer token, method override instruction to pass firewall, many other).

Not a problem at all. 10 min to accomplish:

  • creating new service MyHttp
  • re-imlementing all get, post, put, delete methods with adding required headers
  • mass replace all Http references with new MyHttp
  • work done

But this approach is not good when you have many developers involved:

  • Some wiki resource should be created and defined new rules with accessing server. All developers from all teams should start follow this rules immediately
  • There is a risk that old Http service instead of MyHttp will be re-used as both services are accessible, so incorrect behavior will be introduced
  • More pain for server team to find incorrect behavior when incorrect client http service was chosen

So more suitable approach for multi-team development - is to use @NgModule module class annotation to replace old Http service with new MyHttp using provide configuration:

@NgModule({
  declarations: [ ... ],
  imports: [ ... ],
  providers: [..., {provide: Http, useClass: MyHttp}],
  bootstrap: [AppComponent]
})

From my point of view this approach has many advantages:

  • no need to modify files and replace Http to MyHttp
  • no need to change developer rules in using Http service
  • assure that server side always receive proper headers
  • no worry about incidentally using MyHttp instead of Http - they behave equally

The only problem, that we are creating cyclic dependency as inside MyHttp we need to use old Http

@Injectable()
export class HttpService {
  constructor(private http: Http) {
  }

  get(url: string) { return this.http.get(url); }
  post(url: string, data: any) { ...}
  ...
}  

So exception is thrown:

Cannot instantiate cyclic dependency!

So the only way - is to create MyHttp totally independent from Http. But it adds more complexity to code. And such kind of implementation smell, to be honest.

Is any solutions how to use Http inside MyHttp using configuration defined above?

Thanks.

1 Answer 1

5
@Injectable()
export class MyHttp extends Http {

}

@NgModule({
  declarations: [ ... ],
  imports: [ HttpModule, ... ],
  providers: [..., 
    {provide: ConnectionBackend, useClass: XhrBackend},
    {provide: Http, useClass: MyHttp}
  ],
  bootstrap: [AppComponent]
})

no need to inject HTTP this way.

Just override from https://github.com/angular/angular/blob/5921c872b6ef2f2de31f90576660a1bf56afb979/modules/%40angular/http/src/http.ts#L103-L184 what you want to have different behavior.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you. Trying to refactor my code, but I always receive exception No provider for ConnectionBackend! even having HttpModule defined in module imports.
They are using a weird way to provide Http github.com/angular/angular/blob/…. You need to add the ConnectionBackend provider yourself. See my updated answer.
You're welcome. Glad to hear you could make it work :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.