J'utilise Angular 6 avec un intercepteur HTTP configuré pour appliquer un jeton de support aux requêtes sortantes.
Dans la version de développement (ng serve
), le jeton est appliqué et tout fonctionne correctement. :-)
Dans la version de production (ng serve --prod
), la demande est envoyée sans jeton de support. :-(
Dans la construction de prod, j'ai vérifié que l'en-tête est appliqué, en vidant les en-têtes sur la console après les avoir appliqués.
Je ne sais pas pourquoi ils sont exclus de la requête http.
Il n'y a AUCUNE différence dans mes fichiers environment
.
Que devrais-je regarder d'autre?
Que puis-je faire pour résoudre ce problème?
Au début, j’imaginais que c’était un problème entre mon environnement local et mon environnement de transfert, puis j’ai essayé d’exécuter ng serve --prod
localement et j’ai obtenu les mêmes résultats.
Tout cela pour dire, tout est identique sauf un étant une version de production et un étant une version de développement.
jwt-interceptor:
import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// add authorization header with jwt token if available
let currentUser = JSON.parse(localStorage.getItem('currentUser'));
if (currentUser && currentUser.token) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${currentUser.token}`
}
});
console.log('headers:', request.headers); // <---- I can see headers in console output
}
return next.handle(request);
}
}
Voici ce que je vois dans la console:
app.module.ts
import { HttpClientModule, HttpClient, HttpInterceptor } from '@angular/common/http';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { PortalModule } from '@angular/cdk/portal';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { JwtInterceptor } from './jwt-interceptor';
import { ENV } from '../environments/environment';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
...
import { myApiService } from './services/my-api.service';
import { myModalComponent } from './_components/my-modal/my-modal.component';
import { myModalService } from './services/my-modal.service';
import { AngularLaravelEchoModule, PusherEchoConfig, EchoInterceptor } from 'angular-laravel-echo/angular-laravel-echo';
export const echoConfig: PusherEchoConfig = {
userModel: 'App.User',
notificationNamespace: 'App\\Notifications',
options: {
broadcaster: 'pusher',
key: ENV.pusherConfig.key,
cluster: ENV.pusherConfig.cluster,
Host: ENV.apiRoot,
authEndpoint: ENV.apiRoot + '/broadcasting/auth',
}
};
@NgModule({
declarations: [
AppComponent,
...
],
imports: [
BrowserModule,
HttpClientModule,
BrowserModule,
AppRoutingModule,
FormsModule,
ReactiveFormsModule,
PortalModule,
AngularLaravelEchoModule.forRoot(echoConfig)
],
providers: [
myApiService,
myModalService,
{
provide: HTTP_INTERCEPTORS,
useClass: JwtInterceptor,
multi: true,
},
{
provide: HTTP_INTERCEPTORS,
useClass: EchoInterceptor,
multi: true
}
],
bootstrap: [AppComponent],
entryComponents: [
myModalComponent
]
})
export class AppModule {
}
J'ai écrit cette application dans StackBlitz, et tout fonctionne correctement lorsque je l'exécute localement avec ng serve --prod
.
https://stackblitz.com/edit/angular-yzckos
Téléchargez-le et lancez-le pour voir si vous obtenez toujours undefined
dans l'onglet Réseau. Si vous pouvez voir l'en-tête correctement envoyé, il y a certainement quelque chose de drôle dans votre code.
Essayez ci-dessous:
1- essayez d’exécuter `ng serve --port = aDifferentPort // like 2098
Peut-être que quelque chose tourne sur ce port et envoie un en-tête auth
2- Essayer avec AOT false, je ne vois pas pourquoi cela causerait des problèmes
3- Assurez-vous que votre navigateur n'a pas d'extension qui remplace l'en-tête Auth ou essayez d'autres navigateurs
4- Eteignez vos autres intercepteurs HTTP, peut-être que l'un d'entre eux fait quelque chose d'inattendu
5- Modifiez le nom de l'en-tête de Authorizaion
à MyAuthorization
, voyez si vous êtes toujours indéfini, sinon, il est remplacé par quelque chose, vérifiez votre package.json
et assurez-vous de ne rien exécuter d'autre le service de production.
6- Désactivez la variable JwtInterceptor
et essayez de joindre l'en-tête d'autorisation à votre demande HTTP
afin de voir si vous obtenez toujours undefined
.
7- Si rien ne vous aide, vous devez vraiment nous envoyer plus de code :)
J'ai une idée à ce sujet - mais je ne suis pas sûr que cela fonctionne ou non, veuillez vérifier
HttpHeaders
sont mutables, si vous ajoutez un en-tête, il met à jour celui existant et ajoute la valeur - cela me cause donc un problème pour ajouter un en-tête, donc j'ai suivi la méthode ci-dessous:
private getHeaders(): HttpHeaders {
let headers = new HttpHeaders();
headers = headers.append("Content-Type", "application/json");
return headers;
}
Depuis, j’ajoute les nouveaux en-têtes et attribue l’objet à l’objet d’origine et renvoie l’objet - Cela a très bien fonctionné pour moi, à la fois pour les versions prod et dev.
Mais dans votre cas, vous pouvez utiliser la même méthode que ci-dessus dans votre HttpInterceptor
ou essayer de changer la setheaders
avec headers
comme ci-dessous exemple mentionné
if (currentUser && currentUser.token) {
request = request.clone({
headers: new HttpHeaders({
Authorization: `Bearer ${currentUser.token}`
})
});
console.log('headers:', request.headers);
}
Je suis sûr que cela résoudra votre problème dans les deux versions - essayez de me le faire savoir si cela ne fonctionne pas - j'espère que cela fonctionnera grâce - codage heureux !!
Pouvez-vous essayer de définir l'en-tête dans l'appel de l'API? Comme, par exemple:
put(path: string, body: Object = {}): Observable<any> {
return this.http.put(`${environment.api_url}${path}`, body, { headers:
this.setHeaders() })
.map((res: Response) => {
return res;
});
}
private setHeaders(): HttpHeaders {
const headersConfig = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer ' + this.oauthService.getAccessToken()
};
return new HttpHeaders(headersConfig);
}
Et l'intercepteur aura juste le
request.clone()
Vous pouvez essayer de cloner les en-têtes manuellement dans votre méthode request.clone()
. C'est ce qui fonctionne pour moi:
export class HttpHeaderInterceptor implements HttpInterceptor {
// ...
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// ...
const clonedRequest = req.clone({
headers: req.headers.set('Authorization', 'Bearer ' + currentUser.token)
});
return next.handle(clonedRequest).pipe(
catchError(err => { /* Error handling here */ })
);
}
}
Espérons que cela aide un peu :-)
J'ai eu presque le problème similaire dans l'environnement de production où le serveur ignore complètement l'en-tête Authorization
. Angular 6 envoie correctement l'en-tête Authorization
mais le serveur se déshabille complètement (En raison des paramètres de sécurité d'hébergement partagé du serveur de production). Je sais que cela pourrait ne pas être la réponse que vous cherchez. Mais je voulais juste vous donner un indice.
Donc, enfin, pour que cela fonctionne, je devais utiliser un paramètre d'en-tête différent, tel que Php-Auth-Digest
, comme celui-ci.
request = request.clone({
setHeaders: {
"Php-Auth-Digest": `Bearer ${currentUser.token}`,
}
});
Pour résoudre ce problème, essayez de modifier le nom de votre paramètre d’en-tête.
À votre santé!