I have the heroes app from angular tutorial and i am trying to make it consume REST API. API is build in DRF. I removed the in memory providers from app.module.ts and added HTTP_PROVIDERS. Here is the app.module.ts file now.
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms';
import { HttpModule, HTTP_PROVIDERS } from '#angular/http';
import { AppComponent } from './app.component';
import { routing } from './app.routing';
import { HeroesComponent } from './heroes.component';
import { DashboardComponent } from './dashboard.component';
import { HeroDetailComponent } from './hero-detail.component';
import { HeroService } from './hero.service';
import { HeroSearchComponent } from './hero-search.component';
#NgModule({
imports: [
BrowserModule,
FormsModule,
routing,
HttpModule
],
declarations: [
AppComponent,
HeroesComponent,
DashboardComponent,
HeroDetailComponent,
HeroSearchComponent,
],
providers: [
HeroService,
HTTP_PROVIDERS,
],
bootstrap: [ AppComponent ]
})
export class AppModule {
}
In hero.service.ts i changed just the url.
import { Injectable } from '#angular/core'
import { Http, Headers, Response } from "#angular/http";
import 'rxjs/add/operator/toPromise'
import { Hero } from './hero'
#Injectable()
export class HeroService{
private heroesUrl = 'http://127.0.0.1/api/heroes/heroes/'; // URL to web api
constructor(private http: Http){}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error);
return Promise.reject(error.message || error);
}
private post(hero: Hero): Promise<Hero> {
let headers = new Headers({
'Content-Type': 'application/json'
});
return this.http
.post(this.heroesUrl, JSON.stringify(hero), {headers: headers})
.toPromise()
.then(res => res.json().data)
.catch(this.handleError)
}
private put(hero: Hero): Promise<Hero> {
let headers = new Headers();
headers.append('Content-Type', 'application.json');
let url = `${this.heroesUrl}/${hero.id}`;
return this.http
.put(url, JSON.stringify(hero), {headers: headers})
.toPromise()
.then(() => hero)
.catch(this.handleError)
}
delete(hero: Hero): Promise<Response> {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
let url = `${this.heroesUrl}/${hero.id}`;
return this.http
.delete(url, {headers: headers})
.toPromise()
.catch(this.handleError)
}
save(hero: Hero): Promise<Hero> {
if (hero.id) {
return this.put(hero);
} else {
return this.post(hero);
}
}
getHeroes(): Promise<Hero[]> {
return this.http.get(this.heroesUrl)
.toPromise()
.then(response => response.json().data as Hero[])
.catch(this.handleError);
}
getHero(id: number): Promise<Hero> {
return this.getHeroes().then(heroes => heroes.find(hero => hero.id === id))
}
}
As far as i can tell from google chrome developer tools i got the answer from django with no problem what so ever but its not showing on the page.
No errors in console also.
Headers from api request:
Request URL:http://127.0.0.1/api/heroes/heroes/
Request Method:GET
Status Code:200 OK
Remote Address:127.0.0.1:80
Allow:GET, POST, HEAD, OPTIONS
Connection:keep-alive
Content-Type:application/json
Date:Mon, 22 Aug 2016 11:01:39 GMT
Server:nginx/1.4.6 (Ubuntu)
Transfer-Encoding:chunked
Vary:Accept, Cookie
X-Frame-Options:SAMEORIGIN
Response:
[{"name":"noname","id":1},{"name":"noname3","id":2},{"name":"noname3","id":3},{"name":"noname2","id":4},{"name":"noname2","id":5},{"name":"noname2","id":6}]
Do not know if it is important or not but here are my nginx conf
server {
listen 80;
server_name team_up.org;
charset utf-8;
root /opt/team_up/team_up-web-client/;
index index.html;
location / {
try_files $uri$args $uri$args/ $uri/ /index.html =404;
}
}
remove HTTP_PROVIDERS from declarations. HTTP_PROVIDERS are deprecated and aren't needed when importing HttpModule.
Related
I'm setting up a Ionic 4 project using ngx-translate and a custom loader to load JSON translations from an external domain. I've been following this guys take on it: https://forum.ionicframework.com/t/ngx-translate-translatehttploader-with-external-url/99331/4
Stackblitz link: https://stackblitz.com/edit/ionic-v4-jdfbh6
So this is my custom loader (provider).
#Injectable()
export class TranslationProvider implements TranslateLoader {
constructor(private http: HttpClient) {
console.log('Hello TranslationProvider Provider');
}
getTranslation(lang: string): Observable<any> {
return Observable.create(observer => {
this.http.get<any>(Environment.base_api + '/static/translations/' + lang + 'json', {
headers: {'Content-Type': 'application/json'}}).subscribe((res: Response) => {
observer.next(res.json());
observer.complete();
});
});
}
}
and in my app.module.ts (imports):
imports: [
BrowserModule,
IonicModule.forRoot(App),
IonicStorageModule.forRoot(),
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: (TranslationProvider),
deps: [HttpClient]
}
})
],
The error message I receive is:
TypeError: Cannot set property 'http' of undefined at TranslationProvider (http://localhost:8100/build/main.js:1073:19)
I made a working sample app, here's the gist:
https://gist.github.com/olivercodes/a34be66e5b69edcd96038e5a4518b16e
You need to change #Injectable() to
#Injectable({
providedIn: 'root'
})
Also, make sure these are your import locations:
// In the service file
import { HttpClient } from '#angular/common/http';
import { TranslateLoader } from '#ngx-translate/core'
// in app.module
import { TranslateLoader } from '#ngx-translate/core'
import { HttpClient, HttpClientModule } from '#angular/common/http';
Use my provided gist and make sure your imports are right.
I have upgraded my app from ng4 to ng5 v-5.2.9. I have set the headers for every request. But on my app some request does not support headers, so how to disable headers from particular request not every request.
Previously with ng4 I was using http but now facing issues as its not supported any more in ng5
setHeader.ts
import { Injectable } from '#angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpErrorResponse } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
#Injectable()
export class AddHeaderInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let currentUser = JSON.parse(localStorage.getItem('currentUser'));
if (currentUser && currentUser.token) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${currentUser.token}`,
Ip:currentUser.Ip
}
});
}
return next.handle(request);
}
}
app.module.ts:-
import { HTTP_INTERCEPTORS } from '#angular/common/http';
#NgModule({
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: AddHeaderInterceptor,
multi: true,
}],
})
export class AppModule {}
Basically headers are used for token and for autorization nut some of the API doesn't need to be authorized and hence headers are not required, by using setHeader it applies to all api calls. I have got HttpErrorResponse on my browser console. where its not required
Thanks!
I have build an interceptor for making HTTP requests to a PHP backend.
This backend gives an JWT token to the app and I save this in the Ionic Storage.
But I want to get that token from Storage and add it as an header to the HTTP request.
Below is my interceptor with and hardcoded token.
This works and I get a response from the backend.
See update # bottom of this post
http-interceptor.ts
import { HttpInterceptor, HttpRequest } from '#angular/common/http/';
import {HttpEvent, HttpHandler} from '#angular/common/http';
import { AuthProvider } from "../providers/auth/auth";
import {Injectable} from "#angular/core";
import {Observable} from "rxjs/Observable";
import {Storage} from "#ionic/storage";
#Injectable()
export class TokenInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const changedReq = req.clone({headers: req.headers.set('Authorization', 'Bearer MY TOKEN')});
return next.handle(changedReq);
}
}
But how do I get the token from storage into the header.
I searched alot and most of the tutorials / examples are from the older HTTP module. If someone has an idea or has a up2date example ?
UPDATE
Oke below code send the token
intercept(req: HttpRequest<any>, next: HttpHandler) : Observable<HttpEvent<any>>{
return fromPromise(this.Auth.getToken())
.switchMap(token => {
const changedReq = req.clone({headers: req.headers.set('Authorization', 'Bearer ' + token )});
return next.handle(changedReq);
});
}
With 1 exception, namely the first time I access that page :)
You can save JWT token in, for example, localStorage
localStorage.setItem('myToken', res.token);
and then access it with
localStorage.getItem('myToken');
In your case something like this:
import { HttpInterceptor, HttpRequest } from '#angular/common/http/';
import {HttpEvent, HttpHandler} from '#angular/common/http';
import { AuthProvider } from "../providers/auth/auth";
import {Injectable} from "#angular/core";
import {Observable} from "rxjs/Observable";
import {Storage} from "#ionic/storage";
#Injectable()
export class TokenInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const changedReq = req.clone({headers: req.headers.set('Authorization', localStorage.getItem('myToken'))});
return next.handle(changedReq);
}
}
If you want to use Ionic Storage
import { HttpInterceptor, HttpRequest } from '#angular/common/http/';
import {HttpEvent, HttpHandler} from '#angular/common/http';
import { AuthProvider } from "../providers/auth/auth";
import {Injectable} from "#angular/core";
import {Observable} from "rxjs/Observable";
import {Storage} from "#ionic/storage";
#Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(public _storage: Storage) {
_storage.get('myToken').then((val) => {
console.log('Your age is', val);
});
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const changedReq = req.clone({headers: req.headers.set('Authorization', this.val)});
return next.handle(changedReq);
}
}
Caching the token in the interceptor is a bad idea because if the token changes the interceptor will not be aware of those changes.
// Don't do this.
token: string;
constructor(private storage: Storage) {
this.storage.get('token').then((res) => {
this.token = res;
})
}
If you want to use Ionic Storage and the interceptor together you can do so by using Observable.flatMap like so...
app.module.ts
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true},
SecurityStorageService
]
AuthInterceptor.ts
#Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(
private securityStorageService: SecurityStorageService
) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// This method gets a little tricky because the security token is behind a
// promise (which we convert to an observable). So we need to concat the
// observables.
// 1. Get the token then use .map to return a request with the token populated in the header.
// 2. Use .flatMap to concat the tokenObservable and next (httpHandler)
// 3. .do will execute when the request returns
const tokenObservable = this.securityStorageService.getSecurityTokenAsObservable().map(token => {
return request = request.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
});
return tokenObservable.flatMap((req) => {
return next.handle(req).do((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
// do stuff to the response here
}
}, (err: any) => {
if (err instanceof HttpErrorResponse) {
if (err.status === 401) {
// not authorized error .. do something
}
}
});
})
}
security-storage-service.ts
You technically don't need this service, but you shouldn't have Ionic Storage logic in your interceptor.
#Injectable()
export class SecurityStorageService {
constructor(private storage: Storage) {
}
getSecurityToken() {
return this.storage.get(StorageKeys.SecurityToken)
.then(
data => { return data },
error => console.error(error)
);
}
getSecurityTokenAsObservable() {
return Observable.fromPromise(this.getSecurityToken());
}
}
storage-keys.ts
export class StorageKeys {
public static readonly SecurityToken: string = "SecurityToken";
}
For anyone who comes across this like me and is using rxjs >=5.5.0 then you can just do:
auth-interceptor.ts
#Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private authService: AuthService) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return from(this.authService.getToken()).pipe(mergeMap((token) => {
const changedReq = req.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
return next.handle(changedReq);
}));
}
auth-service.ts
public async getToken() {
return await this.storage.get('ACCESS_TOKEN');
}
I used Http Restful API at Angular2, but appear the following warning message.
Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
Please tell me how to do that.
http_restful_service.ts
import { Injectable } from '#angular/core';
import { Http, Headers, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
#Injectable()
export class HTTPRestfulService {
constructor(private _http: Http) {}
getAllProjectName() {
var headers = new Headers();
headers.append('Content-Type','charset=uft-8');
return
this._http.get('http://localhost/api/database/',
{headers: headers})
.map(res => res.json());
}
}
backstage_view.component.ts
import { Component, OnInit } from '#angular/core';
import { HTTPRestfulService } from './../../../service/http_restful_service';
#Component({
moduleId: module.id,
selector: 'backstage_view',
templateUrl: './backstage_view.component.html',
styleUrls: ['./backstage_view.component.css']
})
export class BackstageViewComponent implements OnInit {
allProjects: string;
constructor(private _restfulapi: HTTPRestfulService) {}
ngOnInit() {
this._restfulapi.getAllProjectName()
.subscribe(
data => this.allProjects = data,
error => console.log(error),
);
}
}
Why can't you pass the content-type as 'application/json' format,
let url= `http://localhost/api/database/`;
let headers = new Headers();
headers.append('Content-Type','application/json');
let params = new URLSearchParams;
params.append('id', id);
params.append('user_id', user_id);
return this.authHttp.post( url, { headers:headers, search:params })
.map(res => res.json());
I am trying to get a product from a local server using an angular2 rest service. When I do the GET I get the following error. I can get the item from the server using the Insomnia rest client so I know the issue is not with the server. i've also checked the url and made sure there's no errors there. Any idea what else I can check? i'm using ng-cli to run the app...
my error:
http://10.60.160.34/BRMServices/WebEnquiry//POSEnquiry/293
Failed to load resource: net::ERR_CONNECTION_RESET
app.component.ts:32
failureServer error
my rest service:
import { Injectable } from '#angular/core';
import { Http, Headers, Response, RequestOptions } from "#angular/http";
import { Observable } from "rxjs/Rx";
import { ProductModel } from "../models/product.model";
//import 'rxjs/add/operator/map';
//import 'rxjs/add/operator/catch';
//import 'rxjs/add/observable/throw'
#Injectable()
export class RestService {
public API_URL: string = "http://10.60.160.34/BRMServices/WebEnquiry/";
private headers: Headers;
private options: RequestOptions;
constructor(private http: Http){
this.init();
}
init() {
this.headers = new Headers({ 'Content-Type': 'application/json' });
this.options = new RequestOptions({ headers: this.headers });
}
getProduct(barcode: string): Observable<ProductModel> {
return this.http.get(this.API_URL + "/POSEnquiry/" + barcode, this.options)
.map((res: Response) => res.json())
.catch((error: any) => Observable.throw(error.json().error || 'Server error'));
}
}
my app.component.ts:
import { Component } from '#angular/core';
import { RestService } from "./services/rest.service";
import { ProductModel } from "./models/product.model";
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
product: ProductModel;
constructor(private restService: RestService){}
submitBarcode(barcode: HTMLInputElement){
this.restService.getProduct(barcode.value)
.subscribe((res) => {
//product = res;
console.log(res);
}, (res) => {
console.log("failure" + res);
});
//console.log("product: " + product);
}
}
It turned out to be the RequestOptions variable. When I replaced options with headers in the get request it worked with no issues...