Bu provider' lar http isteği yapılırken istenen koşul sağlanırsa çalışıyorlar. AuthService her istekte kullanacak token' ı döndürmek için HttpErrorHandler hata durumlarını ve dönüşlerini yönetmek için kullanılıyor.import cümlelerinden de görebileceği gibi bu provider' ların olduğu dosyalar şöyle

Blog sitemi yapım serüvenimi anlattığım yazı serimin 2. yazısında API bağlantısını nasıl yaptığımı ve AWS Lambda' ya nasıl gönderdiğimi anlatacağım.
- WebSite - 1: Şablon & Angular Kurulum & Component' lerin oluşturulması
- WebSite - 2: API Bağlantısı & AWS Lambda ile Yayına Alma
- Azure AKS ile .Net Core API
- Veri tabanı & MongoDB Atlas
API Bağlantısı
Bu bağlantıyı gerçekleştirmek için StacBiltz HttpClient Example örnek uygulamasını inceledim. Bu örnekteki api sonucu taklit eden HttpClientInMemoryWebApi modülünü kullanmadım. Aynı işlevi görecek kendi yazdığım HttpClientInMemoryWebApi HttpInterceptor' ünü kullandım. Ondan daha sonra bahsedeceğim. Şimdi bu örnek uygulamadan hangi kısımları ne için aldığımı anlatayım.
app.modules.ts
İlk önce app.module.ts' den bu imports kısmını
HttpClientModule,
HttpClientXsrfModule.withOptions({
cookieName: 'My-Xsrf-Cookie',
headerName: 'My-Xsrf-Header',
}),Buradaki HttpClientModule asıl ihtiyacım olan modül. Üzerinden get-post vs gibi metotlar ile api isteklerini yapacağım HttpClient değişkenini sağlıyor. HttpClientXsrfModule de Cross Site Request Forgery (CSRF) den korunmak için kullanılıyor.Yine app.modules.ts' den providers' dan şu kısmı aldım
AuthService,
HttpErrorHandler,
MessageService,
{ provide: RequestCache, useClass: RequestCacheWithMap },
httpInterceptorProviders- auth-service.ts
- http-error-handler.service.ts
- message.service.ts
- request-cache.service.ts
- http-interceptors klasörü
httpInterceptorProviders
httpInterceptorProviders' ı atlamayayım. Buradaki provide' lar bir http isteğini ve sonucunu düzenlemek için kullanılıyor. Bazılarının ne yaptıklarını kısaca anlatayım
- custom-json-interceptor: İsteğin sonucu json türündeyse bu değeri CustomJsonParser ile kontrollü bir şekilde json objesine dönüştürmek için kullanılıyor.
- ensure-https-interceptor: İsteğin daha güvenli yani https li halde gönderildiğinden emin olmak için kullanılıyor.
- retry-interceptor: İstekte hata olduğunda isteğin tekrarlanmasını sağlıyor.
- trim-name-interceptor: İsteğin body' sindeki white-space' leri kaldırmak için kullanılıyor.
- upload-interceptor: İstek "/upload/file" adresine yapılmışsa cevabı geçikmeli olarak döndürmek için kullanılıyor. Api isteğinde bulunmak için örnek projeden aldığım kısımlar bu kadardı.
Tabi dosyaların içindeki comment' ler de incelenebilir. Burada bir isteği nasıl yaptığımı örnek ile göstereyim. src/app/pages/blog-list/blog-list.service.ts dosyasında da görebileceğiniz gibi
getPage = (currentPage: Page): Observable<Pager<BlogPost>> => {
const params = new HttpParams()
.set('pageIndex', currentPage.PageIndex)
.set('pageSize', currentPage.PageSize);
const options = {
params
};
return this.http
.get<Pager<BlogPost>>(this.listUrl, options)
.pipe(
catchError(this.handleError('getBlogPosts', getEmptyPager<BlogPost>()))
);
}http (HttpClient) nesnesinin istenen http verb metodunu çağırarak kolayca api isteğinde bulunabliyorum. Burada rxjs reactive programming kullanımını incelemenizi tavsiye ederim. Javascript' in asenkron kullanımını "Observables" lar ile keyifli bir hale getiriyor.Yine bu kodda dikkatinizi çekmiştirPager<BlogPost> gibi bir tanımlama var. Bu tanımla sayfalama listeleri dönüşlerini belirtmek için kullandığım bir interface. Ayrıca bu tarz api istekleri dışında kalan birçok isteğin sonucunu karşılamak için kullandığım APIResult şeklinde de bir interface tanımlamam var. Bunun içerisinde sadece "Message", "MessageType" ve "Result<T>" (işlem sonucu) özellikleri bulunuyor.
Statik API (Mock a Backend)
API tarafını tamamlamadan önce Angular ile yaptıklarımı statik bir api ile görebilmek için HttpClient kullanımını bozmadan api sonucunu taklit edecek bir yapıya ihtiyaç duydum. HttpClientModule' ünü aldığım örnek yeterli olmadığı için başka bir arayışa gittim ve ufak bir araştırmadan sonra bu ihtiyacı karşılayabileceğim şöyle bir yazıyı inceledim. Bu yazıdan aldığım kod ile de custom-response-interceptor' ı HttpInterceptors' ını yazdım. Bu provider ile "/api/blogposts/" ve "api/blogposts/[id]" adreslerine gelen isteklere statik json array' inden ilgili kısmı alarak cevap verebilir oldum.
CORS & Proxy, pathRewrite
Statik api kullanılmazsa ve herhangi bir yönlendirme olmadan backend için hazırlanan api' ye bağlanılmaya çalışılırsa muhtemelen Cross Origin Resource Sharing CORS hatası alınır. Bu hatanın sebebi bulunan alan adından farklı bir alan adına erişmeye çalışıldığında olabilecek bir güvenlik probleminin önüne geçmek. Angular ise bu duruma kendi içerisinde uygulamanın alan adı altından proxy ayarları ile api' ye erişerek bir çözüm bulmuş. Tanımlamasını da şu şekilde yaptım.
- src/app/setup/proxy.dev.conf.json dosyasında
"target" değeri api' nizin adresi olabilir. Buarada incelemek isterseniz "pathReWrite" için şöyle bir doküman bulunuyor.{ "/api": { "target": "http://localhost/hayrihabip.com/api/", "secure": false, "logLevel": "debug" } } - Daha sonra bu ayarların olduğu json dosyasını angular.json dosyasında "projects/hayrihabip.com/architect" içerisinde şöyle referans gösterdim.
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"browserTarget": "hayrihabip.com:build:production",
"proxyConfig": "src/app/setup/proxy.prod.conf.json"
},
"development": {
"browserTarget": "hayrihabip.com:build:development",
"proxyConfig": "src/app/setup/proxy.dev.conf.json"
}
},
"defaultConfiguration": "development"
},AWS Lambda ile Yayına Alma
Bu yazının bir diğer önemli başlığı olan AWS Lambda' yı kullanabilmek için uygulamaya server-side rendering SSR özelliği kazandırmak gerekiyor. Ayrıca bu sayede uygulama SEO için de daha uygun bir hale geliyor. Bunu nasıl yaptığımı bir önceki yazımda bahsetmiştim. Bu yazıdaki adımlar takip edildiğinde AWS Lambda tanımlamaları büyük ölçüde halledilmiş olunuyor. Ben nelere dikkat ettim ve neleri değiştirdim. Onları anlatmak istiyorum.
Serverless FrameWork
Öncelikle uygulamanın AWS' e gönderilmesini sağlayan serverless framework de bir kullanıcı açtım. Daha sonra https://app.serverless.com/[kullanıcı-adı]/settings/providers?providerId=new&provider=aws adresindeki adımları takip ederek serverless ve AWS hesaplarımı birbirine bağladım. Buradaki kodları konsoldan "serverless" komutlarını çağırırken kullanmak üzere not aldım.Bir başka ilgilendiğim konu ise bu lambda fonksiyonunu kendi alan adıma bağlamaktı bunun için de How to Set Up a Custom Domain for AWS’s API Gateway dokümanındaki adımları takip ettim. Burada şöyle bir not düşeyim "subfolder" gibi farklı link yapıları kullananlar için Angular' daki base-tag ve deploy-url özelliklerini anlamakta fayda var. Bunun için şöyle bir resmi doküman var.
lambda.js & serverless.yml
Uygulamayı AWS Lambda üzerinde denerken resimlerin gözükmediğini fark ettim ve bu durumu araştırırken awsServerlessExpress ile uygulamayı sunarken bazı dosyaların ve özellikle resimler için mime-type tanımlaması yapılması gerektiğini öğrendim. Buyüzden lambda.js dosyasında şu güncellemeyi yaptım.
const binaryMimeTypes = [
'application/javascript',
'application/json',
'application/octet-stream',
'application/x-font-ttf',
'application/xml',
'image/gif',
'image/jpeg',
'image/png',
'image/svg+xml',
'image/x-icon',
'text/comma-separated-values',
'text/css',
'text/html',
'text/javascript',
'text/plain',
'text/text',
'text/xml'
];
const serverProxy = awsServerlessExpress.createServer(app.server, null, binaryMimeTypes);Ve serverless' ın binary sunumunu yapabilmesi için serverless.yml dosyasına da şu eklemeyi yaptım.
plugins:
- serverless-apigw-binary
custom:
apigwBinary:
types:
- '*/*'Yazıyı bitirmeden önce debug ve deploy komutlarından da bahsedeyim. Bu komutların tanımlamaları package.json dosyasında "script" özelliğinde yapılmış durumda. Bunlardan dev:sls i komut satırında
npm rum dev:slskomutu ile çalıştırabilirsiniz. Bu komut http://localhost:3000 adresinde yeni bir uygulama başlatacaktır. Yayına alma içinse
npm rum deploykomutunu çalıştırmanız yeterli.Buraya kadar uygulamanın client tarafını tamamlamış oldum. Bu yazım burada bitiyor ancak yazı serim devam ediyor. Azure AKS ile .Net Core API yazımda görüşmek üzere.
