Can't resolve all parameters for UserServiceService: (?) - javascript

I'm trying to get users data by the link given in getsUserUrl.To do that
it requires a token(see the token variable) that I have added in the header. .Whenever I start the server I get an error like this.
Can't resolve all parameters for UserServiceService: (?).at syntaxError (compiler.js:1021)
Here is my code. I don't know what parameter am I missing in Header.
import { Injectable,Pipe } from '#angular/core';
import { HttpHeaders, HttpClient ,HttpErrorResponse,HttpClientModule}
from "#angular/common/http";
import { catchError } from 'rxjs/operators';
import { throwError } from 'rxjs';
import 'rxjs/add/operator/map';
import { Token } from '#angular/compiler';
#Injectable({
providedIn: 'root'
})
export class UserServiceService {
usersData: any[] = [];
user:string
getUserUrl="https://auth.openshift.io/api/search/users?q=rohit";
token=`eysdsfdp.whsofd23.fdiu`;
constructor(private httpclient:HttpClient) {
}
private handleError(err: HttpErrorResponse | any) {
console.error('An error occurred', err);
return throwError(err.message || err);
}
searchUsers()
{
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.token}`
})
};
var res=this.httpclient.get(this.getUserUrl,httpOptions);
return res.pipe(catchError(this.handleError));
}
}
Please let me know what am I doing wrong.
I'm attaching the code photo for your reference
As the person wanted my component code, I'm adding that too here

The Error messages Can't resolve all parameters for UserServiceService: (?) indicates that the angular DI can't find the HttpClient dependency, which is likely caused by you missing to import the HttpClientModule inside your AppModule.
To solve this add the HttpClientModule from #angular/common/http to the imports section of your AppModule.

Remove the following line from your code
import 'rxjs/add/operator/map';
And import the HttpClientModule in your module file. And declare into the imports array. LIke as following
import { HttpClientModule } from '#angular/common/http';
imports: [
HttpClientModule
And remove the importing of the HttpClientModule in your services file

You need to place authorization keyword in quotes as well
const httpOptions = new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.token}`
});
Or you can define it this way also
let httpOptions = new HttpHeaders();
httpOptions = httpOptions .set('h1', 'v1').set('h2','v2');

Related

Angular HttpInterceptor is not adding response headers

I am trying to modify response header or an API request that goes from my Angular Application. What I have done is I have created a RequestTracker interceptor which extends HttpInterceptor and adds Correlation-Id to request header. What I want is the same Correlation-Id to be part of the response header. I tried the below interceptor but it isn't working for me. Is there anything I am missing?
import * as uuid from 'uuid';
import {
HttpEvent,
HttpHandler,
HttpHeaders,
HttpInterceptor,
HttpRequest,
HttpResponse
} from '#angular/common/http';
import { filter, map } from 'rxjs/operators';
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs';
#Injectable()
export class RequestTracker implements HttpInterceptor {
intercept(
httpRequest: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
const correlationId = uuid.v4();
const httpRequestClone = httpRequest.clone({
setHeaders: {
'Correlation-Id': correlationId
}
});
return next.handle(httpRequestClone).pipe(
filter((response) => response instanceof HttpResponse),
map((response: HttpResponse<any>) => {
const modifiedResponse = response.clone({
headers: response.headers.set('Correlation-Id', correlationId)
});
return modifiedResponse;
})
);
}
}
In Request Headers, the Correlation-Id is getting appended but not in Response Headers.
The response that you have posted, is from the network tab and it refers to the response sent from the server. You are attaching the header once Angular starts processing that response. So it won't be shown in the network tab. Try logging the response inside the code. And correlationId will be part of the response header.

You provided 'undefined' where a stream was expected. in token interceptor

I am trying to make an interceptor to refresh the token, but it throws me this error and I don't know why
ERROR TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
token-interceptor.service.ts
import { Injectable } from '#angular/core';
import { AuthService } from './auth.service';
import { HttpClient, HttpErrorResponse, HttpHandler, HttpInterceptor, HttpRequest } from '#angular/common/http';
import { environment } from 'src/environments/environment';
import { catchError, map} from 'rxjs/operators';
import { throwError } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class TokenInterceptorService implements HttpInterceptor {
constructor(
private auth: AuthService,
private http: HttpClient
) { }
intercept(req: HttpRequest<any>, next: HttpHandler) {
return next.handle(req).pipe(
catchError((err: any) => {
if (err instanceof HttpErrorResponse) {
if (err.url.includes('signin') || err.url.includes('refreshToken')) {
return next.handle(req)
}
//if error is not about authorization
if (err.status !== 401) {
return next.handle(req)
}
this.renewToken(req).subscribe(request => {
return next.handle(request)
})
} else {
return throwError(err)
}
})
)
}
renewToken(req: HttpRequest<any>) {
return this.http.get(`${environment.API_URL}/refreshToken`, { withCredentials: true }).pipe(
map((res: any) => {
//update access token
this.auth.setToken(res.token)
return req.clone({
setHeaders: {
authorization: `Bearer ${res.token}`
}
})
})
)
}
}
Ignore this: It looks like your post is mostly code; please add some more details. It looks like your post is mostly code; please add some more details.
this piece of code is wrong:
this.renewToken(req).subscribe(request => {
return next.handle(request)
})
istead it should be:
return this.renewToken(req).pipe(switchMap(request => next.handle(request)));
you are just returning nothing in your variant, that is why it doesn't work.
also the whole logic of token interpceptor seems weird to me. I believe you should rethink about how you want it to work. for now as I see you sending request without token and in almost all cases you are sending it again unmodified, and the one that I fixed above will send it again with token. Wouldn't it be right to add token every time, and only send it 2nd time if token is outdated?

Setting default requests header from ionic storage using http interceptor - Angular 5 - Ionic 3

I'm trying to set a token value in all request headers using angular 5 new HTTP client. Below is my code:
import {Injectable} from '#angular/core';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from '#angular/common/http';
import {Observable} from "rxjs/Observable";
import { Storage } from '#ionic/storage';
import {Globals} from '../globals/globals';
#Injectable()
export class Interceptor implements HttpInterceptor {
token: string;
constructor(private storage: Storage, private global: Globals){
this.storage.get('token').then((val) => {
this.token = val;
});
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
console.log(this.token) //undefined "only for first time on app start"
req = req.clone({
setHeaders: {
'Token': this.token,
'Version': this.global.version,
}
});
return next.handle(req);
}
}
While adding the token in request header works, but there is a bad exception. It doesn't work for the first time. The problem is with js async nature, req.clone gets executed before getting token from the storage. Because Ionic storage returns promise, so how to handle this situation for the first time?
You can merge both async request (getting the token and handling the request) to execute the later when the token is ready (instead of getting it in the constructor):
// -------------------------------------------------------------------------
// Please note that I'm using lettable/pipeable operators (RxJS > 5.5.x)
// https://github.com/ReactiveX/rxjs/blob/master/doc/pipeable-operators.md
// -------------------------------------------------------------------------
import { Injectable } from '#angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '#angular/common/http';
import { Observable } from "rxjs/Observable";
import { Storage } from '#ionic/storage';
import { Globals } from '../globals/globals';
// New imports!
import { fromPromise } from 'rxjs/observable/fromPromise';
import { mergeMap } from 'rxjs/operators/mergeMap';
#Injectable()
export class Interceptor implements HttpInterceptor {
constructor(private storage: Storage, private global: Globals){ }
getToken(): Promise<any> {
return this.storage.get('token');
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return fromPromise(this.getToken()).pipe(
mergeMap(token => {
// Use the token in the request
req = req.clone({
setHeaders: {
'Token': token,
'Version': this.global.version,
}
});
// Handle the request
return next.handle(req);
}));
}
}

ng2-smart-table's ServerDataSource not sending credentials to web api for windows authentication

This is going to be a long question.
For windows authentication to work with angular I have wrapper for the http calls as shown below
import { Injectable } from '#angular/core';
import { Http, Response, RequestOptions, Headers, RequestOptionsArgs } from '#angular/http';
import { Config } from '../_helpers/config';
import { Observable } from 'rxjs/Observable';
#Injectable()
export class HTTPUtility {
public baseApiUrl: string;
constructor(private http: Http, private config: Config) {
this.baseApiUrl = this.config.getByKey('baseApiUrl') || '';
}
public getApiUrl(url) {
return this.baseApiUrl + url;
}
public get(url: string, options?: RequestOptions) {
if (!options) {
options = this.getDefaultHeaders();
}
return this.http.get(this.getApiUrl(url), options)
.catch(this.handleError);
}
private getDefaultHeaders() {
let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
headers.append('Accept', 'application/json');
return new RequestOptions({ headers, withCredentials: true });
}
public handleError(response: Response) {
return Observable.throw(JSON.parse(response.json().Message) || 'Server error');
}
}
If you observe new RequestOptions({ headers, withCredentials: true }); is allowing browser to send credentials to server for windows authentication.
And it's working great for everything.
Now coming to the issue, I have sampleComponent in which i'm using ServerDataSource as shown below:
import { Component, OnInit, NgZone } from '#angular/core';
import { Http, RequestOptions } from '#angular/http';
import { Ng2SmartTableModule, ServerDataSource } from 'ng2-smart-table';
#Component({
selector: 'criteria',
templateUrl: './criteria.component.html',
styles: [require('./criteria.scss')],
})
export class SampleComponent implements OnInit {
Source: ServerDataSource;
settings: any;
constructor(
private http: Http) {
this.Source = new ServerDataSource(http, { endPoint: 'https://xxxxxx.org/yyy/GetCriterias'});
}
ngOnInit(): void {
// this.settings = {}// assigning the settings.
}
}
As you can see ServerDataSource is accepting Http instance and I have checked there documentation and haven't found any way to pass to RequestOptions. So the web api call made by ng2-smart-table fails with 401 status as credentials is not passed.
To resolve this issue I have made changes directly to ng2-smart-table source file to be specific 'server.data-source.js' and here is the change
ServerDataSource.prototype.createRequestOptions = function () {
var requestOptions = {withCredentials : true}; // this where I have added the withCredntials flag
requestOptions.params = new URLSearchParams();
requestOptions = this.addSortRequestOptions(requestOptions);
requestOptions = this.addFilterRequestOptions(requestOptions);
return this.addPagerRequestOptions(requestOptions);
};
With this change everything is working fine as of now.
But I could have issue in future, if we upgrade the package in that case I have to again make changes.
So if any one can help me to fix the issue in some other way please let me know.
Links: https://github.com/akveo/ng2-smart-table/blob/master/src/app/pages/examples/server/advanced-example-server.component.ts
Thanks.

How to consume REST API with Angular2?

This is my demo code:
products.service.ts
getProducts(){
this.headers = new Headers();
this.headers.append("Content-Type", 'application/json');
this.headers.append("Authorization", 'Bearer ' + localStorage.getItem('id_token'));
return this.http.get('http://mydomain.azurewebsites.net/api/products',{headers:headers}).map(res => res.json().data);
}
products.component.ts
constructor(private productsService: ProductsService) { }
ngOnInit() {
this.productsService.getProducts().subscribe((res) => {
console.log(res);
});
}
Is it nescessary to import something in the ngModule decorator to consume a REST API or my code is wrong? I can get the desired data with Postman Chrome Extension but not with Angular 2 code.
I hope to have explained my problem well.
Update
These are the errors i get:
Sorry for making you waste your time.
This was the problem:
app.module.ts
providers: [
ProductsService,
// { provide: XHRBackend, useClass: InMemoryBackendService }, // in-mem server
// { provide: SEED_DATA, useClass: InMemoryDataService } // in-mem server data
]
After commenting the in-mem server and and the in-mem server data the problem dissapeared.
You're not setting the headers in the request. You declare the Headers object but you don't actually do anything with it.
You need to set them in the get function like this:
return this.http
.get('http://mydomain.azurewebsites.net/api/products', { headers: headers })
.map(res => res.json().data);
I'd suggest you use ngx-rest-ex: https://www.npmjs.com/package/ngx-rest-ex
npm i -S ngx-rest-ex
It's convenient, you just need to specify the corresponding decorator on top of the method and the return type, it will replace your method body. The return type can be either Promise or Observable depending on the HTTP METHOD annotation that you specified.
My demo code for your case:
import { Injectable, Injector } from '#angular/core';
import { BaseUrl, GET, RESTClient } from 'ngx-rest-ex';
import { Product } from './models';
#Injectable({
providedIn: 'root'
})
#BaseUrl('http://mydomain.azurewebsites.net/api/')
export class ApiService extends RESTClient {
constructor(injector: Injector) { super(injector); }
protected getDefaultHeaders() {
return {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.getItem('id_token')
};
}
#GET('products')
getProducts(): Promise<Product[]> {
return;
}
}

Categories

Resources