JavaScript ile API Çağrıları Yapmak
API (Application Programming Interface), açılımından da anlaşılacağı üzere, uygulamaların yazılım arayüzleridir. Yani mevcut bir uygulamanın altyapısını kullanarak, o uygulamaya ek fonksiyon kazandırma ya da o uygulamayı kullanan başka uygulamalar türetmek için gerekli kod altyapısına API diyoruz?
Ne zaman lazım olur?
Eğer tüm hayatımız boyunca, her yaptığımız uygulamayı baştan aşağı kendimiz yazacak olsak, bu inanılmaz bir zaman kaybı olurdu. Bazı durumlarda bu mümkün bile olmazdı. Örneğin sitemizdeki müşterilerle konuşan ve ürünlerimizi anlatan bir yapay zeka botunu sıfırdan yazmak seneler alabilecekken, chatgpt alt yapısı ile bu işlem bir kaç günden uzun sürmezdi.
Elbette her API altyapısı, chatgpt gibi tuzlu olmayabilir. Tamamen ücretsiz ya da amatör seviyede ücretsiz kullanım hakkı olan ve yazılımlarımızda kullanabileceğimiz sayısız API altyapısı var. Bugün birlikte temel bir API bağlantısı nasıl kurulur onu inceleyeceğiz.
Ön hazırlık aşaması
Öncelikle her api altyapısının kendine has kodları, çağırma tekniği ve sonuç bilgisi olduğu için, ulaşmamız gereken ilk şey açıklayıcı bir dökümantasyon. Bu örnekte, bölgeye has hava durumu üzerine çalıştığım için, tam bir pinti gibi “free weather api without membership” gibi arama yaparak, üyeliksiz doğrudan kullanabileceğim bir sistem olup olmadığını kontrol ettim.
Bingo! https://open-meteo.com/ tam da aradığımız gibi bir yer. Open-Meteo, her iyi servis sağlayıcı gibi, API işlemlerini kolaylaştırmak için TypeScripte özel bir hazır api arayüzü çıkarmış ama bugün daha genel bir ders niteliğinde olması için, hazır API kullanmak yerine, genel requestler ile devam edeceğiz. Zira bu şekilde OpenMeteo ile kendimizi sınırlamayıp, herhangi bir API için istekte bulunabileceğiz.
API İstek Cinsi
API istekleri GET, POST, PUT vs gibi farklı http altyapıları ile çalışıyor olabilir. Bunlardan en çok kullanılanları GET ve POST ‘dur. İkisi arasındaki en temel fark, değişkenlerimizi API ‘ya nasıl yolladığımız ile ilgilidir. GET zaten sana çok tanıdık gelecektir. Bildiğin URL encoded text. Herhangi bir siteye girdiğimizde, http://sitem.com/blog?id=15 şeklinde yazan URL aslında webservera yaptığımız bir GET türü istektir. Bu istek türünde web temel url adresine ? simgesinden sonra degisken_adi1=degisken_deger1i°isken_adi2=degisken_degeri2 formatında istekler gönderiyoruz.
POST ise, verilerin JSON ya da FormData gibi alanlarda listelenmiş, ekstra daha olarak yollanılan bir iletişim biçimi. İkisini de bu yazıda inceleyeceğiz.
Open-Meteo GET Request
Open-Meteo dökümanını incelediğimde, çok doğrudan bir altyapısı olduğunu gönderdim. Basitçe API adresine longitude, latitude konum bilgilerini gönderip, serverdan istediğimiz hava durumu bilgilerini soruyoruz. Konum bilgilerine Google Maps ‘den ulaşabilirsin. Örneğin ben aşağıdaki URL adresinde, Samsun Atakum ‘un enlem ve boylamlarını girdim.
https://api.open-meteo.com/v1/forecast?latitude=41.33&longitude=36.27¤t=temperature_2m,wind_speed_10m,weather_code
Yukarıdaki url adresinde, current değişkenine temperature_2m,wind_speed_10m,weather_code verilerini girdim. API dökümanına göre, bu istek ile birlikte, havanın şu andaki durumunun değerlerini istiyorum. temperature_2m bana havanın yerden 2 metre yükseklikteki sıcaklığını verecek, wind_speed_10m bana yerden 10 metre yükseklikteki rüzgar hızını ve weather_code ise genel hava durumunun rakamsal göstergesini döndürecek.
Bu bir GET API ‘si olduğu için, basitçe linke tıklayarak browserında sonuçları görüntüleyebilirsin. Dönen veri aşağıdaki gibi;
{
"latitude": 41.3125,
"longitude": 36.3125,
"generationtime_ms": 0.034928321838378906,
"utc_offset_seconds": 0,
"timezone": "GMT",
"timezone_abbreviation": "GMT",
"elevation": 15,
"current_units": {
"time": "iso8601",
"interval": "seconds",
"temperature_2m": "°C",
"wind_speed_10m": "km/h",
"weather_code": "wmo code"
},
"current": {
"time": "2023-11-16T16:00",
"interval": 900,
"temperature_2m": 13.7,
"wind_speed_10m": 9.2,
"weather_code": 61
}
}
JSON datası içerisinde, bulunduğumuz yere ait zaman, yükseklik vs gibi bazı bilgilerin yanında, asıl işimize yarayacak current datası ve current_units dataları bulunuyor. Units bölümü, birimleri barındırıyor. Örneğin sıcaklık 13.7 ve birimi santigrat gibi.. Burada insan okumasından aciz olan tek veri weather_code verisi. Bize 61 gibi bir değer döndürmüş. Dökümantasyonu incelediğimde, her bir kodun kendine has bir havayı temsil ettiğini görüyorum.
Hava kodlarının tanımladığı hava durumları listesi de bu şekilde. Bence çalışmaya gemeye artık başlayabiliriz.
GET API İsteği
Öncelikle işe, dilediğimiz konuma göre bir URL adresi oluşturmak ile başlayalım.
const params = {
"latitude": 41.33,
"longitude": 36.27,
};
params değişkeni, kolayca değiştirebileceğimiz enlem ve boylam bilgilerimizi tutsun ve API isteğimizi yapacak fonksiyonumuz fetch ile kodlamaya başlayalım.
const callApi = async() => {
let url = `https://api.open-meteo.com/v1/forecast?` //URL 'nin değişmeyen taban adresilet fd = new FormData()
fd.append("latitude",(params.latitude).toString()) //enlem
fd.append("longitude",(params.longitude).toString()) //boylam
fd.append("current","temperature_2m,wind_speed_10m,weather_code") //apiden istediğimiz bilgiler
const sp = new URLSearchParams(fd)
url += sp.toString()
console.log(`API ${url} üzerinden cagiriliyor...`) //Debug için oluşturduğumuz url değerini görelimlet res = await fetch(url,{method:"GET",
})
let weather = await res.json()
console.log(`Hava: ${weatherCode(weather.current.weather_code)} (${weather.current.weather_code})`)
console.log(`Sıcaklık: ${weather.current.temperature_2m} ${weather.current_units.temperature_2m}`)
console.log(`Rüzgar hızı: ${weather.current.wind_speed_10m} ${weather.current_units.wind_speed_10m}`)
return weather
}
callApi fonksiyonu içerisinde, url tabanına ek olarak, params objesinde tanımladığımız latitude ve longitude parametrelerine göre bir url oluşturduk. Bu parametreleri GET isteğine çevirmek için bir çok yol kullanılabilir. Ben yukarıda basitçe, bir FormData objesi içerisine bütün değişkenlerimi yığdım ve sonra URLSearchParams objesi ile bunları encoded halde URL adresine çevirip tabanım ile birleştirdim.
Bu şekilde ilerlememin sebebi, FormData objesini POST sınıfı verilerde de kullanacağımız için, heşir neşir olmanda fayda gördüğüm için. Dilersek farklı bir şekilde de yapabiliriz. Örneğin;
let url = https://api.open-meteo.com/v1/forecast?latitude=${params.latitude}&longitude=${params.longitude}¤t=temperature_2m,wind_speed_10m,weather_code
Yukarıdaki gibi basitçe bir string içerisinde de aynı sonuca ulaşabilirsin.
Eğer fark ettiyken, console.log bölümünde, henüz yazmadığım bir fonksiyonu çağırıyorum. Bize dönen weather_code rakamını, bir yazıya çevirmek için basit bir fonksiyon kullanacağım. Bu fonksiyonu, API dökümanından elde ettiğim fonksiyon ışığında aşağıdaki gibi yazabilirim;
const weatherCode = (code) => {
switch(code) {
default:
return "Mavi Gökyüzü";
case 1 || 2 || 3:
return "Parçalı Bulutlu"
case 45 || 48:
return "Sisli"
case 51 || 53 || 55 || 56 || 57:
return "Çiğseliyor"
case 61 || 63 || 65 || 66 || 67:
return "Yağmurlu"
case 71 || 73 || 75 || 77 || 85 || 86:
return "Karlı"
case 80 || 81 || 82:
return "Sağanak Yaışlı"
case 95 || 96 || 99:
return "Fırtına"
}
}
Bütün bölümlerimiz hazır olduğuna göre kodları aşağıdaki gibi birleştirelim.
const params = {
"latitude": 41.33,
"longitude": 36.27,
};
const callApi = async() => {
let url = `https://api.open-meteo.com/v1/forecast?`let fd = new FormData()
fd.append("latitude",(params.latitude).toString())
fd.append("longitude",(params.longitude).toString())
fd.append("current","temperature_2m,wind_speed_10m,weather_code")
const sp = new URLSearchParams(fd)
url += sp.toString()
console.log(`API ${url} üzerinden cagiriliyor...`)
let res = await fetch(url,{
method:"GET",
})
let weather = await res.json()
console.log(`Hava: ${weatherCode(weather.current.weather_code)} (${weather.current.weather_code})`)
console.log(`Sıcaklık: ${weather.current.temperature_2m} ${weather.current_units.temperature_2m}`)
console.log(`Rüzgar hızı: ${weather.current.wind_speed_10m} ${weather.current_units.wind_speed_10m}`)
return weather
}
const weatherCode = (code) => {
switch(code) {
default:
return "Mavi Gökyüzü";
case 1 || 2 || 3:
return "Parçalı Bulutlu"case 45 || 48:
return "Sisli"case 51 || 53 || 55 || 56 || 57:
return "Çiğseliyor"case 61 || 63 || 65 || 66 || 67:
return "Yağmurlu"case 71 || 73 || 75 || 77 || 85 || 86:
return "Karlı"case 80 || 81 || 82:
return "Sağanak Yağışlı"case 95 || 96 || 99:
return "Fırtına"
}
}
callApi()
Kaydettiğim test.js dosyasını node test.js olarak çağırdığımda, aşağıdaki sonucu alıyorum
ozcan@ostation:~/Documents/Lessons/API_CALLS$ node test.js
API https://api.open-meteo.com/v1/forecast?latitude=41.33&longitude=36.27¤t=temperature_2m%2Cwind_speed_10m%2Cweather_code üzerinden cagiriliyor...
Hava: Yağmurlu (61)
Sıcaklık: 13.6 °C
Rüzgar hızı: 7.4 km/h
Sonuç başarılı! API bilgilerini isteğim gibi alıp, yorumlayabiliyorum.
POST API isteği
Peki ya aynı API POST türünden bir istek kabul etseydi? O zaman kodumuzu biraz değiştirmemiz yeterli olacaktı.
const callApi = async() => {
let url = https://api.open-meteo.com/v1/forecastlet fd = new FormData()
fd.append("latitude",(params.latitude).toString())
fd.append("longitude",(params.longitude).toString())
fd.append("current","temperature_2m,wind_speed_10m,weather_code")
console.log(API ${url} üzerinden cagiriliyor...)
let res = await fetch(url,{
method:"POST",
body:fd
})
let weather = await res.json()
console.log(Hava: ${weatherCode(weather.current.weather_code)} (${weather.current.weather_code}))
console.log(Sıcaklık: ${weather.current.temperature_2m} ${weather.current_units.temperature_2m})
console.log(Rüzgar hızı: ${weather.current.wind_speed_10m} ${weather.current_units.wind_speed_10m})
return weather
}
Yukarıdaki değiştirilmiş fonksiyon, aynı verilere POST türünden bir istek yapıyor. Yalnızca bir kaç yerinde oynama yaptım.
Öncelikle URL adresinin sonundaki ? kaldırarak başladım. Zira POST türünde, bu şekilde url kodlamalarına ihtiyaç yok. Sadece base url yeterli.
Daha sonra, URL adresini hiç değiştirmeden doğrudan fetch işlemine giriştim. Fetch ‘in method bölümünü GET ‘den POST ‘a çevirdim ve body alanı ekleyerek bunu fd değişkenime atadım.
Sonuç
Ders notlarına github üzerinden buraya tıklayarak ulaşabilirsin. JavaScript bize fetch haricinde axios gibi başka araçlar da sunmakta, bunlara da bakılabilir. Bu derste fetch sorgularunda async fonksiyonları da kullandık. Eğer bu konuda kafan karıştırsa, ilgili bloğumu buradan okuyabilirsin.