Angular’ın HttpClient Modülü: Temellerden İleri Seviyeye Kapsamlı Bir Giriş
Angular, modern web uygulamaları geliştirmek için güçlü ve kapsamlı bir çerçevedir. Bu uygulamaların çoğu, verileri arka uç sunucularından almak, göndermek, güncellemek veya silmek için HTTP istekleri yapmak zorundadır. İşte tam bu noktada Angular’ın HttpClient modülü devreye girer. HttpClient, Angular uygulamalarında sunucu ile iletişim kurmak için tasarlanmış modern, güçlü ve esnek bir API sağlar. Bu makalede, HttpClient‘ın ne olduğunu, neden kullanılması gerektiğini, temel kullanımından ileri seviye özelliklerine kadar her yönünü detaylı bir şekilde inceleyeceğiz.
HttpClient Nedir ve Neden Kullanmalıyız?
Web uygulamaları, genellikle bir veri kaynağına (API) ihtiyaç duyar. Bu veri kaynağı ile iletişim kurmak için HTTP protokolü kullanılır. Geleneksel JavaScript’te bu işlemler XMLHttpRequest veya daha modern fetch API ile yapılabilir. Ancak bu yöntemlerin her biri, hata yönetimi, istek/cevap dönüşümleri, kesişim noktaları (interceptors) ve test edilebilirlik gibi konularda geliştiricilere ek yükler getirir.
Angular’ın HttpClient modülü, bu zorlukları aşmak ve HTTP iletişimini daha kolay, güvenli ve yönetilebilir hale getirmek için tasarlanmıştır. @angular/common/http paketinin bir parçası olan HttpClient, aşağıdaki temel avantajları sunar:
* RxJS Entegrasyonu: HttpClient, istekleri Observable olarak döndürür. Bu, RxJS’in güçlü operatörlerini kullanarak asenkron veri akışlarını kolayca yönetmenizi, dönüştürmenizi ve hataları ele almanızı sağlar.
* Tip Güvenliği: TypeScript ile tam entegrasyon sayesinde, istek ve cevap verileri için güçlü tip güvenliği sağlayabilirsiniz. Bu, geliştirme sırasında hataları yakalamaya yardımcı olur.
* Interceptor Desteği: İstek ve cevapları merkezi bir noktadan yakalayıp değiştirmeye olanak tanıyan interceptor’lar (kesiciler) sayesinde, kimlik doğrulama token’ı ekleme, hata yönetimi veya loglama gibi işlemleri kolayca yapabilirsiniz.
* Gelişmiş Hata Yönetimi: HTTP hatalarını (örneğin, 404 Not Found, 500 Internal Server Error) ve ağ hatalarını daha tutarlı bir şekilde ele almak için güçlü mekanizmalar sunar.
* Test Edilebilirlik: HttpClientTestingModule ve HttpTestingController gibi araçlar sayesinde HTTP isteklerini kolayca mock’layabilir ve bileşenlerinizi veya servislerinizi test edebilirsiniz.
* İstek İptali: RxJS’in gücü sayesinde, devam eden bir HTTP isteğini kolayca iptal edebilirsiniz. Bu, özellikle kullanıcı navigasyonu veya hızlı arama çubukları gibi senaryolarda kaynak israfını önler.
Bu avantajlar, HttpClient‘ı Angular uygulamalarında sunucu ile etkileşim kurmak için vazgeçilmez bir araç haline getirir.
HttpClient Kurulumu ve Temel Kullanım
HttpClient‘ı kullanmaya başlamak oldukça basittir. İlk adım, modülü Angular uygulamanızın ana modülüne (genellikle AppModule) dahil etmektir.
HttpClientModule’ü Dahil Etme
src/app/app.module.ts dosyanızı açın ve HttpClientModule‘ü imports dizisine ekleyin:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http'; // Burayı ekleyin
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule // Burayı da ekleyin
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Bu adım, HttpClient servisinin uygulamanızın herhangi bir yerinde enjekte edilebilir hale gelmesini sağlar.
HttpClient Servisini Enjekte Etme
HttpClient‘ı kullanmak istediğiniz herhangi bir bileşen veya serviste, servisi constructor’ına enjekte etmeniz yeterlidir:
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
interface Post {
userId: number;
id: number;
title: string;
body: string;
}
@Component({
selector: 'app-data',
template:
Veri Listesi
- {{ post.title }}
{{ error }}
})
export class DataComponent implements OnInit {
posts: Post[] = [];
error: string | null = null;
private apiUrl = 'https://jsonplaceholder.typicode.com/posts';
constructor(private http: HttpClient) { }
ngOnInit(): void {
this.getPosts();
}
getPosts(): void {
this.http.get(this.apiUrl)
.subscribe({
next: (data) => {
this.posts = data;
},
error: (err) => {
console.error('API Hatası:', err);
this.error = 'Veriler yüklenirken bir hata oluştu.';
}
});
}
}
Yukarıdaki örnekte, DataComponent‘ın constructor’ına HttpClient enjekte edilmiştir. getPosts() metodu, HttpClient‘ın get() metodunu kullanarak bir HTTP GET isteği yapar. subscribe() metodu, Observable’dan gelen veriyi dinlemek için kullanılır.
Temel HTTP Metotları
HttpClient, yaygın olarak kullanılan tüm HTTP metotlarını destekler:
GET İstekleri
Veri almak için kullanılır. En basit haliyle, bir URL’ye istek gönderir ve cevabı döndürür.
// Tüm gönderileri al
this.http.get(this.apiUrl).subscribe(data => this.posts = data);
// Belirli bir gönderiyi ID ile al
this.http.get(${this.apiUrl}/1).subscribe(post => console.log(post));
// Query parametreleri ile
this.http.get(this.apiUrl, { params: { userId: '1' } })
.subscribe(data => console.log('User 1 posts:', data));
// HTTP Başlıkları ile
const headers = new HttpHeaders().set('Authorization', 'Bearer my-auth-token');
this.http.get(this.apiUrl, { headers: headers })
.subscribe(data => console.log('Posts with custom headers:', data));
get ifadesi, cevabın Post arayüzüne sahip bir dizi olacağını belirtir, bu da tip güvenliği sağlar.
POST İstekleri
Yeni bir kaynak oluşturmak için kullanılır. İstek gövdesinde (request body) oluşturulacak veriyi gönderir.
import { HttpClient, HttpHeaders } from '@angular/common/http';
// ...
const newPost: Post = {
userId: 1,
id: 0, // Sunucu tarafından atanacak
title: 'Yeni Başlık',
body: 'Bu yeni bir gönderinin içeriği.'
};
this.http.post(this.apiUrl, newPost)
.subscribe(response => {
console.log('Yeni gönderi oluşturuldu:', response);
});
PUT İstekleri
Mevcut bir kaynağı tamamen güncellemek için kullanılır. İstek gövdesinde güncellenmiş veriyi gönderir.
const updatedPost: Post = {
userId: 1,
id: 1,
title: 'Güncellenmiş Başlık',
body: 'Bu gönderi içeriği güncellendi.'
};
this.http.put(${this.apiUrl}/1, updatedPost)
.subscribe(response => {
console.log('Gönderi güncellendi:', response);
});
DELETE İstekleri
Belirli bir kaynağı silmek için kullanılır.
this.http.delete(${this.apiUrl}/1)
.subscribe(() => {
console.log('Gönderi başarıyla silindi.');
});
delete kullanılması, silme işleminden sonra sunucudan genellikle bir içerik dönmediğini (boş cevap) belirtir.
RxJS ve HttpClient İlişkisi
HttpClient‘ın en güçlü yönlerinden biri, RxJS (Reactive Extensions for JavaScript) ile olan derin entegrasyonudur. HttpClient metodları, doğrudan bir değer döndürmek yerine, bir Observable döndürür. Bir Observable, zamanla birden fazla değer yayabilen veya tek bir değer yaydıktan sonra tamamlanabilen bir veri akışını temsil eder. HTTP istekleri durumunda, Observable genellikle tek bir değer (sunucu cevabı) yayar ve ardından tamamlanır.
Observable’ı dinlemek için subscribe() metodunu kullanırız. subscribe() metodu, next, error ve complete olmak üzere üç geri çağırma (callback) fonksiyonu alabilir:
* next: Observable yeni bir değer yaydığında çağrılır (HTTP cevabı geldiğinde).
* error: Observable bir hata yaydığında çağrılır (HTTP isteği başarısız olduğunda).
* complete: Observable tamamlandığında çağrılır (HTTP isteği başarılı bir şekilde tamamlandığında).
this.http.get(this.apiUrl)
.subscribe({
next: (data) => console.log('Veriler geldi:', data),
error: (err) => console.error('Hata oluştu:', err),
complete: () => console.log('İstek tamamlandı.')
});
pipe() ve RxJS Operatörleri
RxJS’in asıl gücü, Observable’ları dönüştürmek, filtrelemek veya birleştirmek için kullanılan operatörlerde yatar. pipe() metodu, bir Observable üzerinde birden fazla operatörü zincirleme imkanı sunar.
map() Operatörü
Observable’dan gelen her değeri dönüştürmek için kullanılır. Örneğin, API’den gelen verinin belirli bir kısmını almak veya formatını değiştirmek isteyebilirsiniz.
import { map } from 'rxjs/operators';
this.http.get(this.apiUrl)
.pipe(
map(posts => posts.filter(post => post.userId === 1)) // Sadece userId 1 olan gönderileri filtrele
)
.subscribe(filteredPosts => console.log('Filtrelenmiş gönderiler:', filteredPosts));
catchError() Operatörü
Observable zincirindeki hataları yakalamak ve işlemek için kullanılır. Bu, hata durumunda bir fallback değeri döndürmek veya hatayı yeniden atmak için idealdir.
import { catchError } from 'rxjs/operators';
import { throwError, of } from 'rxjs';
this.http.get(this.apiUrl)
.pipe(
catchError(error => {
console.error('İstek sırasında bir hata oluştu:', error);
// Hatanın kullanıcıya gösterilebilecek bir versiyonunu döndür
return throwError(() => new Error('Veriler yüklenemedi, lütfen tekrar deneyin.'));
// Veya boş bir dizi gibi bir fallback değeri döndür
// return of([]);
})
)
.subscribe({
next: (data) => console.log(data),
error: (err) => console.error('Hata yakalandı ve işlendi:', err.message)
});
tap() Operatörü
Observable akışını etkilemeden yan etkiler (side effects) gerçekleştirmek için kullanılır. Örneğin, bir isteğin başlangıcında bir yükleme göstergesi göstermek veya loglama yapmak için idealdir.
import { tap } from 'rxjs/operators';
this.http.get(this.apiUrl)
.pipe(
tap(() => console.log('API isteği başladı...')),
tap(data => console.log('API cevabı alındı:', data))
)
.subscribe();
finalize() Operatörü
Observable tamamlandığında veya bir hata ile sonlandığında çalışan bir callback fonksiyonudur. Genellikle bir yükleme göstergesini kapatmak gibi temizlik işlemleri için kullanılır.
import { finalize } from 'rxjs/operators';
this.http.get(this.apiUrl)
.pipe(
tap(() => console.log('Yükleniyor...')),
finalize(() => console.log('Yükleme tamamlandı veya hata oluştu, spinner kapatıldı.'))
)
.subscribe();
retry() Operatörü
Bir hata durumunda Observable’ı belirli bir sayıda yeniden denemek için kullanılır.
import { retry } from 'rxjs/operators';
this.http.get(this.apiUrl)
.pipe(
retry(3) // Hata durumunda 3 kez daha dene
)
.subscribe();
Hata Yönetimi
HTTP isteklerinde hata yönetimi kritik bir konudur. HttpClient, HttpErrorResponse nesnesi aracılığıyla detaylı hata bilgisi sağlar.
HttpErrorResponse nesnesi, aşağıdaki gibi önemli özellikler içerir:
* error: Hatanın ayrıntıları (genellikle sunucudan gelen JSON hata mesajı).
* headers: Hataya ait HTTP başlıkları.
* message: Hatanın kullanıcı dostu mesajı.
* name: Hatanın adı.
* ok: İstek başarılı mıydı (her zaman false bir hata durumunda).
* status: HTTP durum kodu (örneğin, 404, 500).
* statusText: HTTP durum metni (örneğin, “Not Found”, “Internal Server Error”).
* url: Hatanın oluştuğu URL.
Hatalar genellikle iki kategoriye ayrılır:
1. Sunucu Tarafı Hataları (Backend Errors): Sunucu, isteği işlerken bir sorunla karşılaşır ve 4xx veya 5xx durum kodları ile cevap verir (örneğin, 404 Not Found, 500 Internal Server Error).
2. İstemci Tarafı Hataları (Client-side Errors): Ağ hataları (internet bağlantısı yok), CORS politikası ihlalleri veya istek gönderilmeden önce oluşan hatalar (örneğin, bir JSON objesini seri hale getirememek).
catchError operatörü, bu hataları yakalamak ve işlemek için en yaygın ve etkili yöntemdir.
import { HttpErrorResponse } from '@angular/common/http';
import { throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
handleError(error: HttpErrorResponse) {
let errorMessage = '';
if (error.error instanceof ErrorEvent) {
// İstemci tarafı veya ağ hatası
errorMessage = Bir hata oluştu: ${error.error.message};
} else {
// Sunucu tarafı hatası
errorMessage = Sunucu hatası - Kod: ${error.status}, Mesaj: ${error.message};
// error.error nesnesinde sunucudan gelen detaylı hata mesajı olabilir
if (error.error && error.error.message) {
errorMessage += Detay: ${error.error.message};
}
}
console.error(errorMessage);
return throwError(() => new Error(errorMessage)); // Hata mesajını yeniden fırlat
}
// Kullanım örneği
this.http.get(this.apiUrl)
.pipe(
catchError(this.handleError)
)
.subscribe({
next: (data) => console.log(data),
error: (err) => alert(err.message) // Kullanıcıya hata mesajını göster
});
Bu merkezi handleError fonksiyonu, hata yönetimini uygulamanız genelinde tutarlı hale getirmenize yardımcı olur.
HTTP Interceptor’lar
HTTP Interceptor’lar, Angular’ın HttpClient modülünün en güçlü ve kullanışlı özelliklerinden biridir. Interceptor’lar, bir HTTP isteği gönderilmeden önce veya bir HTTP cevabı alındıktan sonra istekleri veya cevapları yakalama ve değiştirme yeteneği sağlar. Bu, uygulamanız genelinde tekrarlayan görevleri merkezi bir yerden yönetmek için mükemmel bir yoldur.
Kullanım senaryoları şunları içerir:
* Kimlik Doğrulama (Authentication): Her giden isteğe bir kimlik doğrulama token’ı (örneğin, JWT) eklemek.
* Loglama: Tüm giden istekleri ve gelen cevapları konsola veya bir loglama servisine kaydetmek.
* Hata Yönetimi: Belirli HTTP hata kodlarını (örneğin, 401 Unauthorized) yakalayıp kullanıcıyı giriş sayfasına yönlendirmek gibi global hata işleme mantığı uygulamak.
* Yükleme Göstergeleri (Loading Spinners): İstek başlamadan önce bir yükleme göstergesi göstermek ve cevap geldiğinde veya hata oluştuğunda bu göstergeyi gizlemek.
* API URL Ön Eki: Tüm isteklerin başına belirli bir API URL ön eki eklemek.
Interceptor Oluşturma Adımları
1. HttpInterceptor Arayüzünü Uygulayın: Yeni bir TypeScript sınıfı oluşturun ve HttpInterceptor arayüzünü implement edin. Bu arayüz, intercept() adında tek bir metot tanımlar.
2. intercept() Metodunu Uygulayın: Bu metot, HttpRequest ve HttpHandler olmak üzere iki parametre alır.
* HttpRequest: Giden isteği temsil eder. İstek objesi readonly olduğu için, onu değiştirmek isterseniz request.clone() metodunu kullanarak yeni bir kopya oluşturmanız gerekir.
* HttpHandler: İsteği bir sonraki interceptor’a veya son olarak sunucuya göndermekten sorumludur. handle() metodu, bir Observable döndürür.
3. Interceptor’ı Sağlayın: Interceptor’ınızı Angular’ın dependency injection sistemine kaydetmek için HTTP_INTERCEPTORS token’ını kullanın.
Örnek: Kimlik Doğrulama Interceptor’ı
// src/app/auth.interceptor.ts
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor() {}
intercept(request: HttpRequest, next: HttpHandler): Observable> {
// LocalStorage'dan token'ı al
const authToken = localStorage.getItem('access_token');
// Eğer token varsa, isteğe Authorization başlığını ekle
if (authToken) {
request = request.clone({
setHeaders: {
Authorization: Bearer ${authToken}
}
});
}
// Değiştirilmiş isteği bir sonraki işleyiciye gönder
return next.handle(request);
}
}
Interceptor’ın Sağlanması
AppModule‘de, providers dizisine interceptor’ınızı eklemeniz gerekir:
// src/app/app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { AppComponent } from './app.component';
import { AuthInterceptor } from './auth.interceptor'; // Interceptor'ı import et
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true // Birden fazla interceptor'ı desteklemek için 'multi: true' olmalı
}
],
bootstrap: [AppComponent]
})
export class AppModule { }
multi: true ayarı, birden fazla interceptor’ın aynı HTTP_INTERCEPTORS token’ı için sağlanabileceğini belirtir. Interceptor’lar, providers dizisindeki sırayla yürütülür.
Diğer Gelişmiş Özellikler ve En İyi Uygulamalar
HttpClient, temel işlevselliğinin ötesinde, daha karmaşık senaryoları ele almak için çeşitli gelişmiş özellikler sunar.
İstek Başlıkları (HttpHeaders)
HttpHeaders sınıfı, HTTP isteklerine özel başlıklar eklemek için kullanılır. Bu, kimlik doğrulama token’ları, içerik tipi veya özel API anahtarları göndermek için yaygın olarak kullanılır.
import { HttpHeaders } from '@angular/common/http';
const headers = new HttpHeaders()
.set('Content-Type', 'application/json')
.set('X-Custom-Header', 'MyValue');
this.http.post(this.apiUrl, body, { headers: headers })
.subscribe(response => console.log(response));
Query Parametreleri (HttpParams)
URL’ye query parametreleri eklemek için HttpParams sınıfı kullanılır. Bu, GET isteklerinde filtreleme, sıralama veya sayfalama bilgisi göndermek için idealdir.
import { HttpParams } from '@angular/common/http';
let params = new HttpParams()
.set('page', '1')
.set('limit', '10')
.set('sort', 'title');
this.http.get(this.apiUrl, { params: params })
.subscribe(data => console.log('Filtered data:', data));
İstek İptali (Cancelling Requests)
RxJS’in gücü sayesinde, devam eden bir HTTP isteğini iptal etmek mümkündür. Bu, özellikle kullanıcı hızlıca bir sayfadan diğerine geçtiğinde veya arama kutusuna sürekli yeni değerler girdiğinde önceki gereksiz istekleri durdurmak için önemlidir. takeUntil() veya unsubscribe() metotları bu amaçla kullanılır.
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
// ...
private destroy$ = new Subject();
getPosts(): void {
this.http.get(this.apiUrl)
.pipe(
takeUntil(this.destroy$) // destroy$ yayımladığında isteği iptal et
)
.subscribe({
next: (data) => this.posts = data,
error: (err) => console.error(err)
});
}
ngOnDestroy(): void {
this.destroy$.next(); // Component yok edildiğinde iptal sinyali gönder
this.destroy$.complete();
}
İstek İlerlemesi (Progress Events)
HttpClient, dosya yüklemeleri gibi durumlarda isteğin ilerlemesini izlemek için ilerleme olaylarını (progress events) destekler. reportProgress: true seçeneği ile bu özellik etkinleştirilir.
this.http.post(this.uploadUrl, formData, {
reportProgress: true,
observe: 'events' // Tüm HTTP olaylarını gözlemle
})
.subscribe(event => {
if (event.type === HttpEventType.UploadProgress) {
const percentDone = Math.round(100 * event.loaded / event.total!);
console.log(Dosya yükleniyor: ${percentDone}%);
} else if (event.type === HttpEventType.Response) {
console.log('Yükleme tamamlandı!', event.body);
}
});
Request Options: observe
observe seçeneği, HTTP cevabının hangi kısmının Observable tarafından döndürüleceğini kontrol etmenizi sağlar:
* 'body' (varsayılan): Sadece cevap gövdesini döndürür.
* 'response': Tam HttpResponse nesnesini döndürür (başlıklar, durum kodu dahil).
* 'events': Tüm HTTP olaylarını (yükleme ilerlemesi dahil) Observable olarak döndürür.
// Tam HttpResponse nesnesini almak için
this.http.get(this.apiUrl, { observe: 'response' })
.subscribe(response => {
console.log('Status:', response.status);
console.log('Headers:', response.headers.get('Content-Type'));
console.log('Body:', response.body);
});
Servis Yapısı ve Tip Güvenliği
En iyi uygulama olarak, HttpClient doğrudan bileşenlerde kullanılmamalıdır. Bunun yerine, API çağrılarını yönetmek için ayrı servisler oluşturulmalıdır. Bu, kodun daha düzenli, test edilebilir ve yeniden kullanılabilir olmasını sağlar. Ayrıca, veri yapılarını tanımlamak için TypeScript arayüzleri veya sınıfları kullanarak tip güvenliğini sağlamak önemlidir.
// src/app/post.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
export interface Post {
userId: number;
id: number;
title: string;
body: string;
}
@Injectable({
providedIn: 'root'
})
export class PostService {
private apiUrl = 'https://jsonplaceholder.typicode.com/posts';
constructor(private http: HttpClient) { }
getPosts(): Observable {
return this.http.get(this.apiUrl)
.pipe(
catchError(this.handleError)
);
}
getPostById(id: number): Observable {
return this.http.get(${this.apiUrl}/${id})
.pipe(
catchError(this.handleError)
);
}
createPost(post: Post): Observable {
return this.http.post(this.apiUrl, post)
.pipe(
catchError(this.handleError)
);
}
private handleError(error: HttpErrorResponse): Observable {
let errorMessage = '';
if (error.error instanceof ErrorEvent) {
errorMessage = İstemci hatası: ${error.error.message};
} else {
errorMessage = Sunucu hatası - Kod: ${error.status}, Mesaj: ${error.message};
}
console.error(errorMessage);
return throwError(() => new Error('Bir şeyler ters gitti; lütfen tekrar deneyin.'));
}
}
Bileşende kullanımı:
// src/app/post-list/post-list.component.ts
import { Component, OnInit } from '@angular/core';
import { PostService, Post } from '../post.service';
@Component({
selector: 'app-post-list',
templateUrl: './post-list.component.html',
styleUrls: ['./post-list.component.css']
})
export class PostListComponent implements OnInit {
posts: Post[] = [];
errorMessage: string | null = null;
constructor(private postService: PostService) { }
ngOnInit(): void {
this.postService.getPosts()
.subscribe({
next: (data) => this.posts = data,
error: (err) => this.errorMessage = err.message
});
}
}
Mocklama ve Test Etme
Angular’ın HttpClientTestingModule ve HttpTestingController‘ı, HTTP isteklerini bir arka uç sunucusuna gerçekten göndermeden test etmenizi sağlar. Bu, birim testlerinizi hızlı ve güvenilir hale getirir.
// src/app/post.service.spec.ts
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { PostService, Post } from './post.service';
describe('PostService', () => {
let service: PostService;
let httpTestingController: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [PostService]
});
service = TestBed.inject(PostService);
httpTestingController = TestBed.inject(HttpTestingController);
});
afterEach(() => {
httpTestingController.verify(); // Bekleyen istek kalmadığından emin ol
});
it('should be created', () => {
expect(service).toBeTruthy();
});
it('should retrieve posts from the API via GET', () => {
const dummyPosts: Post[] = [
{ userId: 1, id: 1, title: 'Test Post 1', body: 'Body 1' },
{ userId: 1, id: 2, title: 'Test Post 2', body: 'Body 2' },
];
service.getPosts().subscribe(posts => {
expect(posts.length).toBe(2);
expect(posts).toEqual(dummyPosts);
});
const req = httpTestingController.expectOne('https://jsonplaceholder.typicode.com/posts');
expect(req.request.method).toBe('GET');
req.flush(dummyPosts); // Mock cevabı gönder
});
});
Güvenlik Konuları
Web uygulamalarında HTTP iletişimi yaparken bazı güvenlik konularını göz önünde bulundurmak önemlidir:
* CORS (Cross-Origin Resource Sharing): Tarayıcıların farklı kaynaklardan (domain, protokol, port) kaynaklara erişimini kısıtlayan bir güvenlik mekanizmasıdır. Eğer API’niz farklı bir domain’de ise, sunucu tarafında CORS başlıklarını doğru yapılandırmanız gerekir.
* XSRF (Cross-Site Request Forgery): Saldırganın, kullanıcının kimliğini kullanarak istemci adına istenmeyen eylemler gerçekleştirmesini sağlayan bir saldırı türüdür. HttpClient, withXsrfHeader: true seçeneğiyle XSRF korumasını otomatik olarak sağlar (Angular’ın kendi XSRF token mekanizması ile birlikte).
* Sanitization: Sunucudan gelen verileri (özellikle HTML içeriği) doğrudan DOM’a eklerken dikkatli olun. Güvenlik açığı yaratabilecek komut dosyası enjeksiyonlarını önlemek için Angular’ın yerleşik sanitization mekanizmalarını kullanın veya verileri temizleyin.
Sonuç
Angular’ın HttpClient modülü, modern web uygulamalarında sunucu ile iletişim kurmak için güçlü, esnek ve geliştirici dostu bir araç setidir. RxJS ile entegrasyonu, güçlü tip güvenliği, interceptor desteği ve kapsamlı hata yönetimi yetenekleri sayesinde, HttpClient karmaşık HTTP tabanlı işlemleri bile basit ve yönetilebilir hale getirir.
Bu makalede, HttpClient‘ın temel kurulumundan, farklı HTTP metotlarının kullanımına, RxJS operatörleriyle veri akışlarını yönetmeye, merkezi hata yönetimine ve interceptor’larla istek/cevapları özelleştirmeye kadar birçok yönünü ele aldık. Ayrıca, en iyi uygulamalar ve güvenlik konuları hakkında da bilgi edindik.
HttpClient‘ı doğru bir şekilde anlamak ve kullanmak, Angular uygulamalarınızın performansını, güvenliğini ve sürdürülebilirliğini önemli ölçüde artıracaktır. Artık, Angular projelerinizde güvenle HTTP istekleri yapmaya hazırsınız.