AngularJS : $http, $resource et REST APIs

Front-end 07/04/2026 14:00:00 Mezgani said
Angularjs Http Rest-Api Resource Javascript
AngularJS : $http, $resource et REST APIs

Maîtrisez $http et $resource AngularJS 1.x pour consommer des REST APIs : interceptors, promises, ngResource et patterns avancés.

$http : introduction et configuration

$http est le service built-in d'AngularJS pour effectuer des requêtes HTTP. Il encapsule XMLHttpRequest et retourne des promises (objets $q) que vous chaînez avec .then() et .catch().

Contrairement à fetch() natif ou axios, $http intègre automatiquement le cycle $digest d'AngularJS : toute réponse HTTP déclenche une mise à jour de l'UI sans appel manuel à $scope.$apply().

// Injection de $http dans un service ou controller
angular.module('monApp')
  .service('ApiService', function($http) {
    // $http est prêt à l'emploi, aucune configuration minimale requise
    // Par défaut : Content-Type: application/json, XSRF protection activée

    this.ping = function() {
      return $http.get('/api/health');
      // Retourne une promise : { data, status, headers, config, statusText }
    };
  });

Configuration globale de $http

// Configurer $http globalement dans la phase config()
angular.module('monApp')
  .config(function($httpProvider) {
    // Ajouter un header Authorization à toutes les requêtes
    $httpProvider.defaults.headers.common['Authorization'] =
      'Bearer ' + localStorage.getItem('token');

    // Désactiver le cache par défaut (utile en développement)
    $httpProvider.defaults.cache = false;

    // Timeout global de 10 secondes pour toutes les requêtes
    $httpProvider.defaults.timeout = 10000;

    // Activer les credentials CORS (cookies cross-domain)
    $httpProvider.defaults.withCredentials = true;
  });

Méthodes GET, POST, PUT, DELETE

$http expose des méthodes de raccourci pour chaque verbe HTTP. Chaque méthode retourne une promise résolue avec un objet de réponse contenant data, status, headers et config.

GET — Lire des données

// Récupère la liste des articles avec paramètres de requête
angular.module('monApp')
  .service('ArticleService', function($http) {

    this.getAll = function(page, limit) {
      return $http.get('/api/articles', {
        // params est converti automatiquement en query string
        // → /api/articles?page=1&limit=20
        params: { page: page, limit: limit }
      }).then(function(response) {
        // response.data contient le corps de la réponse parsé
        return response.data;
      });
    };

    // Récupère un article par son slug
    this.getBySlug = function(slug) {
      return $http.get('/api/articles/' + slug)
        .then(function(res) { return res.data; });
    };
  });

POST — Créer une ressource

// Crée un nouvel article avec les données envoyées en JSON
this.create = function(articleData) {
  return $http.post('/api/articles', articleData)
    // angularJS sérialise automatiquement l'objet en JSON
    .then(function(response) {
      // response.status === 201 (Created)
      return response.data; // l'article créé avec son ID
    })
    .catch(function(error) {
      // error.status = code HTTP (400, 401, 500...)
      // error.data = corps de la réponse d'erreur
      console.error('Erreur création:', error.status, error.data);
      return Promise.reject(error);
    });
};

PUT / PATCH — Mettre à jour

// PUT remplace la ressource complète
this.update = function(id, data) {
  return $http.put('/api/articles/' + id, data)
    .then(function(res) { return res.data; });
};

// PATCH met à jour partiellement (envoie seulement les champs modifiés)
this.patch = function(id, changes) {
  return $http.patch('/api/articles/' + id, changes)
    .then(function(res) { return res.data; });
};

DELETE — Supprimer

// Supprime un article par son ID
this.remove = function(id) {
  return $http.delete('/api/articles/' + id)
    .then(function(response) {
      // response.status === 204 (No Content) si suppression réussie
      return true;
    });
};

L'objet de configuration $http

Au lieu des méthodes de raccourci, vous pouvez utiliser $http(config) directement pour un contrôle total sur la requête.

// Requête complète avec tous les paramètres disponibles
$http({
  method: 'POST',
  url: '/api/upload',

  // Corps de la requête (object, string, FormData...)
  data: formData,

  // Headers spécifiques à cette requête (surcharge les defaults)
  headers: {
    'Content-Type': undefined, // undefined = AngularJS choisit (FormData auto)
    'X-Custom-Header': 'valeur',
  },

  // Paramètres query string
  params: { version: '2', debug: true },

  // Timeout en ms (annule la requête si dépassé)
  timeout: 30000,

  // Réponse en ArrayBuffer, Blob, Document, JSON (défaut), text
  responseType: 'blob',

  // Téléchargement : notifie la progression
  eventHandlers: {
    progress: function(event) {
      var percent = Math.round(event.loaded / event.total * 100);
      console.log('Upload:', percent + '%');
    }
  },

}).then(function(response) {
  console.log('Succès:', response.status, response.data);
}).catch(function(error) {
  console.error('Échec:', error.status, error.statusText);
});

Interceptors $http

Les interceptors permettent d'intercepter toutes les requêtes et réponses HTTP de l'application. Ils sont idéaux pour l'authentification, le logging, la gestion d'erreurs globale et l'affichage d'un indicateur de chargement.

// Interceptor complet : auth + loading + retry
angular.module('monApp')
  .factory('HttpInterceptor', function($q, $injector) {
    var pendingRequests = 0;

    return {
      // Intercepte chaque requête sortante
      request: function(config) {
        pendingRequests++;

        // Ajoute le token JWT à chaque requête vers notre API
        var token = localStorage.getItem('auth_token');
        if (token && config.url.indexOf('/api/') !== -1) {
          config.headers['Authorization'] = 'Bearer ' + token;
        }

        // Active un spinner de chargement global
        $injector.get('LoadingService').show();

        return config; // toujours retourner config (ou une promise)
      },

      // Intercepte les réponses réussies
      response: function(response) {
        pendingRequests--;
        if (pendingRequests === 0) {
          $injector.get('LoadingService').hide();
        }
        return response;
      },

      // Intercepte les erreurs HTTP
      responseError: function(rejection) {
        pendingRequests--;
        if (pendingRequests === 0) {
          $injector.get('LoadingService').hide();
        }

        // Token expiré → redirige vers la page de connexion
        if (rejection.status === 401) {
          $injector.get('$state').go('login');
          return $q.reject(rejection);
        }

        // Serveur indisponible → message d'erreur
        if (rejection.status === 503) {
          $injector.get('NotifService').error('Serveur temporairement indisponible');
        }

        return $q.reject(rejection); // toujours rejeter pour propager l'erreur
      },
    };
  })
  // Enregistrement de l'interceptor
  .config(function($httpProvider) {
    $httpProvider.interceptors.push('HttpInterceptor');
  });

ngResource et $resource

ngResource est un module optionnel d'AngularJS qui fournit $resource, une abstraction de haut niveau pour les API RESTful. Il génère automatiquement les méthodes CRUD à partir d'un pattern d'URL.

// Installation (en plus d'angular.js)
// <script src="angular-resource.js"></script>

// Déclaration du module avec ngResource
angular.module('monApp', ['ngResource']);
// Définition d'une ressource REST
angular.module('monApp')
  .factory('Article', function($resource) {
    return $resource(
      '/api/articles/:id',  // pattern URL avec paramètre :id
      { id: '@id' },        // valeur par défaut de :id (depuis l'objet)
      {
        // Méthodes personnalisées (en plus des méthodes par défaut)
        update: { method: 'PUT' },       // $resource n'a pas PUT par défaut
        patch:  { method: 'PATCH' },
        search: {
          method: 'GET',
          url: '/api/articles/search',   // URL différente pour la recherche
          isArray: true,                 // la réponse est un tableau
        },
      }
    );
    // $resource génère automatiquement :
    // Article.query()      → GET /api/articles         (tableau)
    // Article.get({id:1})  → GET /api/articles/1       (objet)
    // Article.save(data)   → POST /api/articles        (créer)
    // Article.delete({id}) → DELETE /api/articles/:id  (supprimer)
  });

CRUD complet avec $resource

// Controller utilisant $resource pour un CRUD complet
angular.module('monApp')
  .controller('ArticleCtrl', function($scope, Article) {

    // READ — charge tous les articles
    $scope.articles = Article.query(); // retourne un tableau vide, rempli async

    // READ ONE — charge un article par ID
    $scope.loadArticle = function(id) {
      $scope.current = Article.get({ id: id });
    };

    // CREATE — crée un nouvel article
    $scope.create = function(formData) {
      var article = new Article(formData);
      article.$save(function(saved) {
        // Succès : $save appelle POST /api/articles
        $scope.articles.push(saved);
        $scope.formData = {}; // reset du formulaire
      }, function(error) {
        // Erreur : afficher un message
        $scope.error = 'Erreur lors de la création : ' + error.data.message;
      });
    };

    // UPDATE — met à jour un article existant
    $scope.update = function(article) {
      article.$update(function() {
        // $update appelle PUT /api/articles/:id
        console.log('Article mis à jour');
      });
    };

    // DELETE — supprime un article
    $scope.remove = function(article) {
      article.$delete(function() {
        // $delete appelle DELETE /api/articles/:id
        var idx = $scope.articles.indexOf(article);
        $scope.articles.splice(idx, 1);
      });
    };

    // CUSTOM ACTION — recherche d'articles
    $scope.search = function(query) {
      $scope.results = Article.search({ q: query });
    };
  });

Gestion des erreurs

// Service de gestion d'erreurs centralisé
angular.module('monApp')
  .service('ErrorHandler', function($q, NotifService) {

    // Traite une erreur HTTP et retourne un message lisible
    this.handle = function(error) {
      var message;

      switch (error.status) {
        case 400:
          // Erreur de validation : afficher les détails
          message = error.data.message || 'Données invalides';
          if (error.data.errors) {
            message += ' : ' + Object.values(error.data.errors).join(', ');
          }
          break;
        case 401:
          message = 'Session expirée. Veuillez vous reconnecter.';
          break;
        case 403:
          message = 'Vous n\'avez pas les droits pour cette action.';
          break;
        case 404:
          message = 'La ressource demandée est introuvable.';
          break;
        case 422:
          message = 'Données incorrectes : ' + (error.data.message || '');
          break;
        case 429:
          message = 'Trop de requêtes. Veuillez patienter.';
          break;
        case 500:
          message = 'Erreur serveur. Notre équipe a été notifiée.';
          break;
        default:
          message = error.status === -1
            ? 'Pas de connexion internet.'
            : 'Erreur inattendue (' + error.status + ')';
      }

      NotifService.error(message);
      return $q.reject(error); // propage l'erreur après traitement
    };
  });

Migration vers HttpClient Angular

HttpClient remplace $http en Angular. La différence principale est que HttpClient retourne des Observables (RxJS) au lieu de Promises, ce qui ouvre la voie à des opérateurs puissants comme retry, debounceTime, switchMap.

AngularJS $httpAngular HttpClient
$http.get(url)this.http.get<T>(url)
$http.post(url, data)this.http.post<T>(url, data)
.then(fn).subscribe(fn) ou pipe(map(fn))
.catch(fn)pipe(catchError(fn))
Interceptors via $httpProviderHttpInterceptorFn (fonctionnel)
$resource (ngResource)httpResource() (Angular 21)
Promises ($q)Observables (RxJS)
// Équivalent HttpClient Angular 21 avec interceptor fonctionnel
import { HttpInterceptorFn } from '@angular/common/http';
import { inject } from '@angular/core';
import { catchError, throwError } from 'rxjs';
import { AuthService } from './auth.service';
import { Router } from '@angular/router';

// Interceptor fonctionnel (Angular 15+) — remplace la classe
export const authInterceptor: HttpInterceptorFn = (req, next) => {
  const auth = inject(AuthService);
  const router = inject(Router);

  // Clone la requête pour ajouter le header Authorization
  const authReq = auth.token()
    ? req.clone({ setHeaders: { Authorization: 'Bearer ' + auth.token() } })
    : req;

  return next(authReq).pipe(
    catchError(error => {
      if (error.status === 401) {
        router.navigate(['/login']);
      }
      return throwError(() => error);
    })
  );
};
httpResource() en Angular 21 : La nouvelle API httpResource() remplace avantageusement $resource — elle retourne des signals réactifs qui s'actualisent automatiquement quand les paramètres changent, sans subscribe explicite.

Partager