IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Angular Discussion :

Erreur cross origin : Uncaught (in promise): HttpErrorResponse


Sujet :

Angular

  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2012
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2012
    Messages : 92
    Par défaut Erreur cross origin : Uncaught (in promise): HttpErrorResponse
    Bonjour,

    je développe une appli de gestion de produits sur angular 6 et spring boot 2.

    J'ai créé mon service qui appelle la liste de mes produits côté angular et côté spring boot le contrôleur associé avec l'annotation cross origin pour permettre mon front d'atteindre mon back.

    Malheureusement , quand je tape l'url : http://localhost:4200/produit, j'ai une erreur sur la console de mon navigateur : chrome, firefox, safari :

    Error: Uncaught (in promise): HttpErrorResponse: {"headers":{"normalizedNames":{},"lazyUpdate":null,"headers":{}},"status":0,"statusText":"Unknown Error","url":null,"ok":false,"name":"HttpErrorResponse","message":"Http failure response for (unknown url): 0 Unknown Error","error":{"isTrusted":true}}
    at resolvePromise (zone.js:831)
    at resolvePromise (zone.js:788)


    voici mon service côté angular :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    export const API_URLS = {
        PRODUITS_URLS : 'http://localhost:8080/api/produit'
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
     
    import { Injectable } from "@angular/core";
    import { HttpClient, HttpHeaders } from "@angular/common/http";
    import { Observable } from "rxjs";
     
    import { API_URLS } from '../config/api.url.config';
    import { Produit } from "../shared/produit";
     
    const httpOptions = {
        headers: new HttpHeaders({ 'Content-Type': 'application/json' })
      };
     
    @Injectable()
    export class ProduitService {
     
        constructor(private http : HttpClient) {
     
        }
     
        getPoduits():Observable<any>{
            /*return this.http.get(API_URLS.PRODUITS_URLS);*/
            return this.http.get('/api/produit');
        }
     
        addProduit(produit : Produit):Observable<any>{
            return this.http.post('/api/produit',produit);
        }
     
        updateProduit(produit : Produit):Observable<any>{
            /*return this.http.put(API_URLS.PRODUITS_URLS,produit);*/
            return this.http.put('/api/produit',produit);
        }
     
        deleteProduit(id : number):Observable<any>{
            return this.http.delete(`/api/produit/${id}`);
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
     
    import { Component, OnInit } from '@angular/core';
    import { Produit } from '../shared/produit';
    import { FormGroup, FormBuilder, Validators } from '@angular/forms';
    import { ProduitService } from './produit.service';
    import { ActivatedRoute } from '@angular/router';
     
    @Component({
      selector: 'app-produit',
      templateUrl: './produit.component.html',
      styleUrls: ['./produit.component.css']
    })
    export class ProduitComponent  implements OnInit {
     
      produitForm : FormGroup;
     
      products:Produit[];
     
      operation : string = 'add';
     
      selectedProduit : Produit;
     
      constructor(private produitService:ProduitService, private fb : FormBuilder,
        private route : ActivatedRoute) {
        this.createForm();
      }
     
      ngOnInit() {
        /*this.products = this.produitService.getPoduits();*/
        this.initProduit();
       // this.loadProduits();
        this.products = this.route.snapshot.data.produits;
      }
     
      createForm(){
        this.produitForm = this.fb.group({
          ref:['', Validators.required],
          quantite:'',
          prixUnitaire:''
        });
      }
     
      loadProduits() {
        this.produitService.getPoduits().subscribe(
          data => { this.products = data},
          error => { console.log("An error was occured.")},
          () => { console.log("loading products")}
        )
      }
     
      addProduit(){
        const p = this.produitForm.value;
        console.log("produit envoye ");
        console.log(p);
        this.produitService.addProduit(p).subscribe(
          res => {
            this.initProduit();
            this.loadProduits();
          }
        );
      }
     
      updateProduit(){
        this.produitService.updateProduit(this.selectedProduit).subscribe(
          res => {
            this.initProduit();
            this.loadProduits();
          }
        );
      }
     
      initProduit(){
        this.selectedProduit =  new Produit();
        this.createForm();
      }
     
      deleteProduit(){
        this.produitService.deleteProduit(this.selectedProduit.id).subscribe(
          res => {
            this.loadProduits();
          }
        );
      }
     
     
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
     
    <!-- <h3>Hello produits</h3>
    <ul >
        <li *ngFor="let product of products">
            Ref : {{product.ref}}
            Quantité : {{product.quantite}}
            Prix unitaire : {{product.prixUnitaire}}
        </li>
    </ul> -->
    <h3>Produits</h3>
    <div class="container">
        <div class="row">
            <div class="col-lg-7">
                <table class="table table-hover">
                    <thead>
                        <tr>
                            <th>Référence</th>
                            <th>Quantité</th>
                            <th>Prix Unitaire</th>
                            <th><button class="btn btn-outlet-primary"
                                    (click)="operation = 'add';initProduit();">ADD</button></th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr *ngFor="let produit of products">
                            <td>{{produit.ref}}</td>
                            <td>{{produit.quantite}}</td>
                            <td>{{produit.prixUnitaire}}</td>
                            <td><button class="btn btn-outlet-primary"
                                    (click)="operation = 'edit'; selectedProduit = produit">Edit</button></td>
                            <td><button class="btn btn-outlet-danger" (click)="operation = 'remove'; selectedProduit = produit">Remove</button></td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <div class="col-lg-5">
                <div class="card">
                    <div class="card-header bg-info text-white">
                        {{operation == 'add' ? 'Ajouter produit':
                        operation == 'edit' ? 'Modifier produit':
                        operation == 'remove' ? 'Supprimer produit':''}}
                    </div>
                    <div class="card-body">
                        <div *ngIf="operation == 'add' || operation == 'edit'">
                            <form [formGroup]="produitForm">
                                <div class="form-group">
                                    <label>Réference : </label>
                                    <input type="text" class="form-control" formControlName="ref"
                                        [(ngModel)]="selectedProduit.ref" />
                                </div>
                                <div class="alert alert-danger" *ngIf="produitForm.controls['ref'].invalid && 
                                        (produitForm.controls['ref'].dirty || produitForm.controls['ref'].touched)">
                                    Réference est obligatoire !
                                </div>
                                <div class="form-group">
                                    <label>Quantité : </label>
                                    <input type="number" class="form-control" formControlName="quantite"
                                        [(ngModel)]="selectedProduit.quantite" />
                                </div>
                                <div class="form-group">
                                    <label>Prix unitaire : </label>
                                    <input type="number" class="form-control" formControlName="prixUnitaire"
                                        [(ngModel)]="selectedProduit.prixUnitaire" />
                                </div>
                                <button class="btn btn-success"
                                    (click)="operation == 'add' ? addProduit() : updateProduit()"
                                    [disabled]="(produitForm.prestine || produitForm.invalid)">
                                    {{operation == 'add' ? 'Ajouter' : operation == 'edit' ? 'Modifier' : ''}}</button>
                            </form>
                        </div>
                        <div *ngIf="operation == 'remove'">
                            <p class="card-title">Réference : {{selectedProduit.ref}}</p>
                            <p class="card-title">Voulez-vous supprimer ce produit ?</p>
                            <button class="btn btn-success" [disabled]="!selectedProduit.ref" (click)="deleteProduit()">Confirmez</button>
                        </div>
     
                    </div>
                    <div class="card-footer">
     
                    </div>
                </div>
            </div>
        </div>
    </div>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
     
    import { NgModule } from '@angular/core';
    import { RouterModule, Routes } from '@angular/router';
    import { ProduitComponent } from './produit/produit.component';
    import { DashboardComponent } from './dashboard/dashboard.component';
    import { ProduitResolver } from './produit/produit.resolver';
     
    export const appRoutes : Routes = [
        {
            path:'produit',
            component:ProduitComponent,
            resolve:{
                produits : ProduitResolver    
            }
        },
        {
            path:'dashboard',
            component:DashboardComponent
        },
        {
            path:'',
            redirectTo:'/dashboard',
            pathMatch:'full'
     
        }
    ]
     
    @NgModule({
        imports : [
            RouterModule.forRoot(
                appRoutes,
                {enableTracing:true}
            )
        ],
        exports : [RouterModule],
        providers : [ProduitResolver]
    })
     
    export class AppRoutingModule {
     
    }

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    import { Injectable } from "@angular/core";
    import { Resolve } from "@angular/router";
    import { ProduitService } from "./produit.service";
     
    @Injectable()
    export class ProduitResolver implements Resolve<any> {
     
        constructor(private produitService : ProduitService) {
     
        }
     
        resolve() {
            return this.produitService.getPoduits();
        }
    }

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
     
     
    {
      "name": "gestion-stock",
      "version": "0.0.0",
      "scripts": {
        "ng": "ng",
        "start": "ng serve --proxy-config proxy.conf.json",
        "build": "ng build",
        "test": "ng test",
        "lint": "ng lint",
        "e2e": "ng e2e"
      },
      "private": true,
      "dependencies": {
        "@angular/animations": "^6.1.0",
        "@angular/common": "^6.1.0",
        "@angular/compiler": "^6.1.0",
        "@angular/core": "^6.1.0",
        "@angular/forms": "^6.1.0",
        "@angular/http": "^6.1.0",
        "@angular/platform-browser": "^6.1.0",
        "@angular/platform-browser-dynamic": "^6.1.0",
        "@angular/router": "^6.1.0",
        "core-js": "^2.5.4",
        "rxjs": "~6.2.0",
        "zone.js": "~0.8.26",
        "bootstrap": "^4.0.0-beta",
        "font-awesome": "^4.7.0",
        "jquery": "^3.2.1",
        "popper.js": "^1.12.5"
      },
      "devDependencies": {
        "@angular-devkit/build-angular": "~0.8.0",
        "@angular/cli": "~6.2.5",
        "@angular/compiler-cli": "^7.2.5",
        "@angular/language-service": "^6.1.0",
        "@types/jasmine": "~2.8.8",
        "@types/jasminewd2": "~2.0.3",
        "@types/node": "~8.9.4",
        "codelyzer": "~4.3.0",
        "jasmine-core": "~2.99.1",
        "jasmine-spec-reporter": "~4.2.1",
        "karma": "^4.0.0",
        "karma-chrome-launcher": "~2.2.0",
        "karma-coverage-istanbul-reporter": "~2.0.1",
        "karma-jasmine": "~1.1.2",
        "karma-jasmine-html-reporter": "^0.2.2",
        "protractor": "~5.4.0",
        "ts-node": "~7.0.0",
        "tslint": "~5.11.0",
        "typescript": "~3.1.1"
      }
    }
    et côté back end : java spring boot 2

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
     
    package com.gestion.stock.controller;
     
    import java.util.List;
     
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.CrossOrigin;
    import org.springframework.web.bind.annotation.DeleteMapping;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.PutMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
     
    import com.gestion.stock.entity.Produit;
    import com.gestion.stock.service.IProduitService;
     
    @RestController
    @RequestMapping("/api/produit")
    //@CrossOrigin
    @CrossOrigin(origins = "http://localhost:4200")
    public class ProduitController {
    	@Autowired
    	private IProduitService produitService;
     
    	@GetMapping
    	public List<Produit> getProduits() {
    		return produitService.getProduits();
    	}
     
    	@PostMapping
    	public void addProduit(@RequestBody Produit produit) {
    		produitService.addProduit(produit);
    	}
     
    	@PutMapping
    	public void updateProduit(@RequestBody Produit produit) {
    		produitService.updateProduit(produit);
    	}
     
    	@DeleteMapping("{/id}")
    	public void deletedProduit(@PathVariable Long id) {
    		produitService.deleteProduit(id);
    	}
    }

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
     
     
    spring.jpa.hibernate.ddl-auto=create
    spring.datasource.url=jdbc:mysql://localhost:3306/stock_produits?zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=UTC
    spring.datasource.username=root
    spring.datasource.password=root
    je n'arrive pas à trouver la solution après multiple recherche sur le net.

  2. #2
    Expert confirmé
    Avatar de Marco46
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2005
    Messages
    4 419
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2005
    Messages : 4 419
    Par défaut
    Est-ce que tu as bien une requête OPTIONS qui part du navigateur et est-ce que cette requête est bien reçue par ton backend ?

    Pourrais-tu copier coller les headers http de tes requêtes ?

    Les problèmes de CORS sont toujours des problèmes côté backend. C'est le backend qui pose les bons headers http sur les requêtes. Côté front le mécanisme est implémenté par le navigateur, il n'y a rien à faire côté code applicatif front.

    Tu as donc plus de chances d'obtenir une réponse dans la section Java appropriée.

  3. #3
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2012
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2012
    Messages : 92
    Par défaut
    Bonjour,

    Voici les headers que j'ai pu recupérer côté network de la console de mon navigateur :

    Request URL: http://localhost:4200/api/produit
    Request Method: GET
    Status Code: 302 Found
    Remote Address: 127.0.0.1:4200
    Referrer Policy: no-referrer-when-downgrade

    Response Headers
    Access-Control-Allow-Origin: *
    cache-control: no-cache, no-store, max-age=0, must-revalidate
    connection: close
    content-length: 0
    date: Sun, 24 Feb 2019 15:17:58 GMT
    expires: 0
    location: http://localhost:8080/login
    pragma: no-cache
    x-content-type-options: nosniff
    x-frame-options: DENY
    X-Powered-By: Express
    x-xss-protection: 1; mode=block

    Request Headers
    Accept: application/json, text/plain, */*
    Accept-Encoding: gzip, deflate, br
    Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7
    Connection: keep-alive
    Host: localhost:4200
    Referer: http://localhost:4200/produit
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36

  4. #4
    Expert confirmé
    Avatar de Marco46
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2005
    Messages
    4 419
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2005
    Messages : 4 419
    Par défaut
    Apparemment tu as une réponse du serveur qui te dit qu'il trouve la ressource mais pas sur cette url (302) et effectivement on a une ligne location: http://localhost:8080/login.

    Ptet lié à ton système d'authentification ?

    En résumé tu demandes les produits avec un GET sur http://localhost:4200/produit et ton serveur te répond qu'il a bien une URL mais c'est http://localhost:8080/login. Autre truc marrant c'est ce header : X-Powered-By: Express. C'est une signature de Express (de Node.js) or tu disais tourner en back avec spring boot.

    Autre remarque dans ton code côté front on a http://localhost:8080/api/produit et dans tes logs http http://localhost:4200/api/produit.

    Ça aussi c'est quand même bien bizarre.

    Bref, t'as quand même pas mal de bizarreries à clarifier !

  5. #5
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2012
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2012
    Messages : 92
    Par défaut
    Bonjour,

    Pour clarifier, mon back tourne sur eclipse :


    . ____ _ __ _ _
    /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
    ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
    \\/ ___)| |_)| | | | | || (_| | ) ) ) )
    ' |____| .__|_| |_|_| |_\__, | / / / /
    =========|_|==============|___/=/_/_/_/
    :: Spring Boot :: (v2.1.3.RELEASE)

    2019-02-24 16:17:02.395 INFO 712 --- [ main] com.gestion.stock.DemoApplication : Starting DemoApplication on MacBook-Pro-de-Moi.local with PID 712 (/Users/Moi/eclipse-workspace/demo/target/classes started by Moi in /Users/Moi/eclipse-workspace/demo)
    2019-02-24 16:17:02.397 INFO 712 --- [ main] com.gestion.stock.DemoApplication : No active profile set, falling back to default profiles: default
    2019-02-24 16:17:03.109 INFO 712 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode.
    2019-02-24 16:17:03.183 INFO 712 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 62ms. Found 1 repository interfaces.
    2019-02-24 16:17:03.591 INFO 712 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$c2770b36] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2019-02-24 16:17:03.615 INFO 712 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.hateoas.config.HateoasConfiguration' of type [org.springframework.hateoas.config.HateoasConfiguration$$EnhancerBySpringCGLIB$$41f75868] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2019-02-24 16:17:04.021 INFO 712 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
    2019-02-24 16:17:04.047 INFO 712 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
    2019-02-24 16:17:04.048 INFO 712 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.16]
    2019-02-24 16:17:04.054 INFO 712 --- [ main] o.a.catalina.core.AprLifecycleListener : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [/Users/JR/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.]
    2019-02-24 16:17:04.141 INFO 712 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
    2019-02-24 16:17:04.141 INFO 712 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1705 ms
    2019-02-24 16:17:04.390 INFO 712 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
    2019-02-24 16:17:04.604 INFO 712 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
    2019-02-24 16:17:04.740 INFO 712 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [
    name: default
    ...]
    2019-02-24 16:17:04.816 INFO 712 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {5.3.7.Final}
    2019-02-24 16:17:04.817 INFO 712 --- [ main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found
    2019-02-24 16:17:04.985 INFO 712 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.4.Final}
    2019-02-24 16:17:05.133 INFO 712 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
    2019-02-24 16:17:05.846 INFO 712 --- [ main] o.h.t.schema.internal.SchemaCreatorImpl : HHH000476: Executing import script 'org.hibernate.tool.schema.internal.exec.ScriptSourceInputNonExistentImpl@8840c98'
    2019-02-24 16:17:05.849 INFO 712 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
    2019-02-24 16:17:06.741 INFO 712 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
    2019-02-24 16:17:06.795 WARN 712 --- [ main] aWebConfiguration$JpaWebMvcConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
    2019-02-24 16:17:07.175 INFO 712 --- [ main] .s.s.UserDetailsServiceAutoConfiguration :

    Using generated security password: 314b1f55-784a-4cfa-9681-79ef9639265d

    2019-02-24 16:17:07.343 INFO 712 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: any request, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@295b07e0, org.springframework.security.web.context.SecurityContextPersistenceFilter@696174d3, org.springframework.security.web.header.HeaderWriterFilter@7de5871d, org.springframework.security.web.csrf.CsrfFilter@2cea921a, org.springframework.security.web.authentication.logout.LogoutFilter@58aa5c94, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@2905b568, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@25fd6d1e, org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@55053f81, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@52cb52bd, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@577f9dfd, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@39a7eca5, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@1fee4278, org.springframework.security.web.session.SessionManagementFilter@4948daec, org.springframework.security.web.access.ExceptionTranslationFilter@1214d23c, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@5df64b2a]
    2019-02-24 16:17:07.475 INFO 712 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
    2019-02-24 16:17:07.478 INFO 712 --- [ main] com.gestion.stock.DemoApplication : Started DemoApplication in 5.374 seconds (JVM running for 6.242)
    2019-02-24 16:17:58.287 INFO 712 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
    2019-02-24 16:17:58.287 INFO 712 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
    2019-02-24 16:17:58.313 INFO 712 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 26 ms
    et mon front sur visual studio code et je fais un npm start qui lance mon serveur.
    MacBook-Pro-de-Moi:gestionStock Moi$ npm start

    > gestion-stock@0.0.0 start /Users/Moi/Documents/AngularProject/gestionStock
    > ng serve --proxy-config proxy.conf.json

    ** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **

    Date: 2019-02-24T15:17:24.732Z
    Hash: cbdc17e4d27383854031
    Time: 8434ms
    chunk {main} main.js, main.js.map (main) 48.3 kB [initial] [rendered]
    chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 241 kB [initial] [rendered]
    chunk {runtime} runtime.js, runtime.js.map (runtime) 6.22 kB [entry] [rendered]
    chunk {scripts} scripts.js, scripts.js.map (scripts) 166 kB [rendered]
    chunk {styles} styles.js, styles.js.map (styles) 205 kB [initial] [rendered]
    chunk {vendor} vendor.js, vendor.js.map (vendor) 3.87 MB [initial] [rendered]
    ℹ 「wdm」: Compiled successfully.
    ℹ 「wdm」: Compiling...

    Date: 2019-02-25T10:14:46.718Z - Hash: c2667e249248c0b738e7 - Time: 795ms
    5 unchanged chunks
    chunk {main} main.js, main.js.map (main) 51.2 kB [initial] [rendered]
    ℹ 「wdm」: Compiled successfully.
    ℹ 「wdm」: Compiling...

    Date: 2019-02-25T10:15:22.409Z - Hash: 629e363a703e13c0184f - Time: 620ms
    5 unchanged chunks
    chunk {main} main.js, main.js.map (main) 54.1 kB [initial] [rendered]
    ℹ 「wdm」: Compiled successfully.
    ℹ 「wdm」: Compiling...

    Date: 2019-02-25T10:17:01.676Z - Hash: 3aa8f33f7e1b4d65761d - Time: 167ms
    5 unchanged chunks
    chunk {main} main.js, main.js.map (main) 55 kB [initial] [rendered]
    ℹ 「wdm」: Compiled successfully.
    ℹ 「wdm」: Compiling...

    Date: 2019-02-25T10:17:53.274Z - Hash: 6f1ebb200d48de715401 - Time: 115ms
    5 unchanged chunks
    chunk {main} main.js, main.js.map (main) 54.1 kB [initial] [rendered]
    ℹ 「wdm」: Compiled successfully.
    ℹ 「wdm」: Compiling...

    Date: 2019-02-25T10:18:43.054Z - Hash: 0ea8a92a186fae17007d - Time: 140ms
    5 unchanged chunks
    chunk {main} main.js, main.js.map (main) 55 kB [initial] [rendered]
    ℹ 「wdm」: Compiled successfully.
    ℹ 「wdm」: Compiling...

    Date: 2019-02-25T10:19:24.444Z - Hash: 4c391554d599678f5fa2 - Time: 119ms
    5 unchanged chunks
    chunk {main} main.js, main.js.map (main) 54.1 kB [initial] [rendered]
    ℹ 「wdm」: Compiled successfully.
    ℹ 「wdm」: Compiling...

    Date: 2019-02-25T10:21:34.218Z - Hash: de2c08d3879a77ab0d5e - Time: 191ms
    5 unchanged chunks
    chunk {main} main.js, main.js.map (main) 54.6 kB [initial] [rendered]
    ℹ 「wdm」: Compiled successfully.

  6. #6
    Expert confirmé
    Avatar de Marco46
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2005
    Messages
    4 419
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2005
    Messages : 4 419
    Par défaut
    > ng serve --proxy-config proxy.conf.jsonFaudrait voir la conf du proxy de Angular CLI et check que la conf est correcte par rapport à ton backend.

    Du coup tes calls front devraient taper sur le proxy (port 4200) et pas direct sur ton backend (port 8080), et la conf de ton proxy devrait faire le routage vers ton back. Avec ce fonctionnement tu n'as plus besoin de config CORS en mode développement.

    Donc tu pourrais faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    export const API_URLS = {
        PRODUITS_URLS : 'http://localhost:4200/api/produit'
    }
    au lieu de

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    export const API_URLS = {
        PRODUITS_URLS : 'http://localhost:8080/api/produit'
    }
    et si la conf de proxy.conf.json est correcte ça sera routé sur ton backend.

  7. #7
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2012
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2012
    Messages : 92
    Par défaut
    Bonjour,

    merci encore et je te prie ne me lâche pas , je pense qu'on est presque vers la fin.

    Mais , l'erreur persiste encore

    voici l'erreur :

    Access to XMLHttpRequest at 'http://localhost:8080/login' (redirected from 'http://localhost:4200/api/produit') from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
    core.js:1673 ERROR Error: Uncaught (in promise): HttpErrorResponse: {"headers":{"normalizedNames":{},"lazyUpdate":null,"headers":{}},"status":0,"statusText":"Unknown Error","url":null,"ok":false,"name":"HttpErrorResponse","message":"Http failure response for (unknown url): 0 Unknown Error","error":{"isTrusted":true}}
    at resolvePromise (zone.js:831)
    at resolvePromise (zone.js:788)
    at zone.js:892
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
    at Object.onInvokeTask (core.js:3811)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422)
    at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)
    at drainMicroTaskQueue (zone.js:601)
    at ZoneTask.push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (zone.js:502)
    at invokeTask (zone.js:1744)
    et le code de mon backend (contrôleur)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    package com.gestion.stock.controller;
     
    import java.util.List;
     
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.CrossOrigin;
    import org.springframework.web.bind.annotation.DeleteMapping;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.PutMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
     
    import com.gestion.stock.entity.Produit;
    import com.gestion.stock.service.IProduitService;
     
    @RestController
    @RequestMapping("/api/produit")
    //@CrossOrigin
    //@CrossOrigin(origins = "http://localhost:4200")
    //@RequestMapping("/api")
    //@CrossOrigin("*")
    @CrossOrigin(origins = "http://localhost:4200")
    public class ProduitController {
    	@Autowired
    	private IProduitService produitService;
     
    	@GetMapping
    	// @GetMapping("/produits")
    	public List<Produit> getProduits() {
    		return produitService.getProduits();
    	}
     
    	@PostMapping
    	// @PostMapping("/produit")
    	public void addProduit(@RequestBody Produit produit) {
    		produitService.addProduit(produit);
    	}
     
    	@PutMapping
    	// @PutMapping("/produit")
    	public void updateProduit(@RequestBody Produit produit) {
    		produitService.updateProduit(produit);
    	}
     
    	@DeleteMapping("{/id}")
    	// @DeleteMapping("/produit/{id}")
    	public void deletedProduit(@PathVariable("id") Long id) {
    		produitService.deleteProduit(id);
    	}
    }

    côté front,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    export const API_URLS = {
        /*PRODUITS_URLS : 'http://localhost:8080/api/produit'*/
        PRODUITS_URLS : 'http://localhost:4200/api/produit'
    }
    proxy.conf.json
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    {
        "/api": {
          "target": "http://localhost:8080/",
          "secure":false,
          "changeOrigin": true
        }
      }
    et je lance bien mon serveur de la manière suivante :

    ng serve --proxy-config proxy.conf.json


    mais l'erreur ci-haut perdure.

    j'ai bien suivi la conf que tu m'as envoyé en lien pour la mise en place du fichier proxy.conf.json

    https://github.com/angular/angular-c...ories/proxy.md

    peux tu jeter un coup d'oeil et me dire la où ça pèche.
    merci

  8. #8
    Expert confirmé
    Avatar de Marco46
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2005
    Messages
    4 419
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2005
    Messages : 4 419
    Par défaut
    Essaie plutôt cette config :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    const PROXY_CONFIG = [
        {
            context: [
                "/api/login",
                "/api/produit",
                "/autre-endpoint"
            ],
            target: "http://localhost:8080",
            secure: false
        }
    ]
     
    module.exports = PROXY_CONFIG;
    Il faut adapter la propriété context pour y lister les endpoints de ton backend.

    N'oublie pas de renommer l'extension de ton fichier de .json en .js et de changer l'appel lors du ng-serve.

    Il reste un point à éclaircir avec ton backend c'est son système d'authentification, manifestement quand tu appelles une API il te renvoie vers le endpoint de login, donc tu as probablement plusieurs problèmes imbriqués.

    Mais bon déjà quand on aura éliminé CORS on y verra plus clair.

    On pourrait aussi procéder différemment en désactivant CORS tout de suite au lancement de ton browser (en le lançant en ligne de commande avec l'option --disable-web-security) pour voir si y a pas un autre problème derrière (à mon avis oui).

    Enfin il te restera un problème et pas des moindre c'est comme déployer tout ça dans un environnement qui n'est pas ta machine de dev. Normalement tu devrais avoir du support dans ta boite avec les Ops sur ce qu'ils attendent comme livrable.

    Bref, prenons les choses dans l'ordre

Discussions similaires

  1. [5.6] erreur Cross-Origin Request
    Par cobos dans le forum Laravel
    Réponses: 5
    Dernier message: 04/08/2018, 16h39
  2. Réponses: 1
    Dernier message: 07/06/2018, 17h02
  3. Réponses: 6
    Dernier message: 30/05/2016, 10h06
  4. Réponses: 2
    Dernier message: 22/09/2007, 17h34
  5. erreur : crosses initialization
    Par parano dans le forum C++
    Réponses: 2
    Dernier message: 23/03/2007, 02h42

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo