Merhaba,

 

Bu yazıda AWS teknolojilerinden olan Lambda, DynamoDB, API Gateway ve CloudWatch ile Rest API yapımından bahsedeceğim.

 

Örnek uygulamamızda bu teknolojileri şu amaçla kullanacağız;

  • Lambda ile Rest API fonksiyonumuzu yazacağız,
  • DynamoDB ile verilerimizi saklayacağız,
  • API Gateway ile Rest API route'larımızı oluşturup bunları Lambda fonksiyonumuza bağlayacağız ve uygulamayı ayağa kaldıracağız,
  • CloudWatch ile de API isteklerine ait log'ları görüntüleyeceğiz.

 

Uygulamamızda film ekleme, düzenleme, listeleme ve silme (CRUD) işlemleriyle ilgili API'lar bulunacak.

 

İlk olarak elbette buradan AWS web sitesine girip konsolda oturum açıyoruz. Sonrasında search kısmından DynamoDB servisini bulup ilgili sayfaya gidiyoruz. Create table butonuna basıyoruz. Tablo adımızın movies olacağını, Primary key olarak da id adında bir veri kullanacağımızı ve bu verinin tipinin Number olacağını belirtiyoruz. Diğer kısımları olduğu şekilde bırakıp Create butonuna basıyoruz.

 

Şimdi de Lambda fonksiyonumuzu oluşturalım. Bu kez search kısmından Lambda servisini bulup ilgili sayfaya gidiyoruz. Create function butonuna basıyoruz. Fonksiyon adı olarak movies-function girip, Runtime olarak Node.js 14.x'i seçiyoruz. Permissions kısmında Lambda fonksiyonumuzun DynamoDB ve CloudWatch'a erişimlerini aktif edebilmek adına yeni bir rol oluşturmak istediğimizi belirtiyoruz. Bu yüzden Change default execution role kısmından Create a new role from AWS policy templates'i seçip rol adı olarak movies-role giriyoruz. Son olarak da Create function butonuna basıyoruz.

 

Rol oluştururken DynamoDB ve CloudWatch erişimlerini aktif etmekten bahsetmiştik. Bununla ilgili olarak search kısmından IAM servisini bulup ilgili sayfaya gidiyoruz. Soldaki Roles kısmına girip movies-role'e tıklıyoruz. Attach policies butonuna basıyoruz. AmazonDynamoDBFullAccess ve CloudWatchLogsFullAccess'i bulup ekliyoruz ve son durumda Permissions kısmı şu şekilde oluyor.

 

Şimdi de API Gateway'e geçelim. Yine search kısmından API Gateway servisini bulup ilgili sayfaya gidiyoruz. Create API butonuna basıyoruz. REST API kısmından Build butonuna basıyoruz. API adı olarak movies-api girip Create API'a basıyoruz.

 

Actions kısmından Create Resource'e basıyoruz. Resource adı olarak movies girip, Enable API Gateway CORS özelliğini aktif ediyoruz. Böylece CORS hatasını engellemiş olacağız. Sonrasında da Create Resource butonuna basıyoruz.

 

/movies seçiliyken Actions kısmından Create Method'a basıp GET metodunu seçiyoruz. Integration type olarak Lambda Function'ı seçiyoruz. Use Lamdba Proxy integration özelliğini aktif ediyoruz. Lambda Function kısmına oluşturduğumuz fonksiyon olan movies-function'ı yazıyoruz. Lambda Region ve Use Default Timeout kısımlarını olduğu gibi bırakıyoruz. Save butonuna basıp ardından gelen Add Permission to Lambda Function uyarısı için OK butonuna basıyoruz.

Aynı işlemleri POST, PATCH ve DELETE metodları için de yapıyoruz. Son durumda ortaya şu şekilde bir görüntü çıkıyor.

 

Son olarak da “/” seçiliyken Actions kısmından Deploy API'a basıyoruz. Deployment stage olarak [New Stage] seçip Stage name olarak da prod giriyoruz ve Deploy'a basıyoruz.

 

API'ımızı deploy ettik. Invoke URL kısmında API isteklerimizi yapacağımız URL'i görebiliriz.

 

Her şeyi yaptık ama ortada API fonksiyonumuz yok :) Şimdi Lambda'da oluşturduğumuz fonksiyona geri dönelim. movies-function içindeki index.js'i şu şekilde dolduruyoruz (Koda bazı yorum satırları ekledim ancak zaten incelediğiniz zaman ne kadar anlaşılır olduğunu göreceksiniz diye düşünüyorum):

// gerekli değişken tanımlamaları
const AWS = require('aws-sdk');
const db = new AWS.DynamoDB.DocumentClient();
const table = 'movies';

// API'a gelen isteklere standart bir json objesi olarak dönüş yapmak adına oluşturduğumuz fonksiyonumuz
function jsonResponse(statusCode, body) {
  return {
    statusCode: statusCode,
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(body)
  };
}

// API'a gelen istekleri karşıladığımız kısım
exports.handler = async function(event) {
  // CloudWatch'da bu log'lara bakacağız :)
  console.log('Event: ', event);
  
  // Gelen Http isteğine göre ilgili fonksiyona yönlendiriyoruz
  let response;
  switch (event.httpMethod) {
    case 'GET':
      response = await getMovies();
      break;
    case 'POST':
      response = await saveMovie(JSON.parse(event.body));
      break;
    case 'PATCH':
      let body = JSON.parse(event.body);
      response = await updateMovie(body.id, body.key, body.value);
      break;
    case 'DELETE':
      response = await deleteMovie(JSON.parse(event.body).id);
      break;
    default:
      response = jsonResponse(404 ,'404 Not Found');
      break;
  }
  
  return response;
}

// film listeleme fonksiyonumuz
async function getMovies() {
  const params = {
    TableName: table
  }
  
  return await db.scan(params).promise().then((response) => {
    const body = {
      operation: 'list',
      message: 'success',
      data: response
    };
    
    return jsonResponse(200, body);
  }, (error) => {
    console.log('Error: ', error);
  });
}

// film kaydetme fonksiyonumuz
async function saveMovie(requestBody) {
  const params = {
    TableName: table,
    Item: requestBody
  };
  
  return await db.put(params).promise().then(() => {
    const body = {
      operation: 'save',
      message: 'success',
      data: requestBody
    };
    
    return jsonResponse(200, body);
  }, (error) => {
    console.log('Error: ', error);
  });
}

// film güncelleme fonksiyonumuz
async function updateMovie(id, key, value) {
  const params = {
    TableName: table,
    Key: {
      'id': id
    },
    UpdateExpression: `set ${key} = :value`,
    ExpressionAttributeValues: {
      ':value': value
    },
    ReturnValues: 'UPDATED_NEW'
  };
  
  return await db.update(params).promise().then((response) => {
    const body = {
      operation: 'update',
      message: 'success',
      data: response
    };
    
    return jsonResponse(200, body);
  }, (error) => {
    console.log('Error: ', error);
  })
}

// film silme fonksiyonumuz
async function deleteMovie(id) {
  const params = {
    TableName: table,
    Key: {
      'id': id
    },
    ReturnValues: 'ALL_OLD'
  };
  
  return await db.delete(params).promise().then((response) => {
    const body = {
      operation: 'delete',
      message: 'success',
      data: response
    };
    
    return jsonResponse(200, body);
  }, (error) => {
    console.log('Error: ', error);
  })
}

Deploy butonuna basarak değişiklikleri kaydediyoruz.

 

Artık Postman üzerinden testlerimizi yapabiliriz:

 

Önce birkaç film ekleyelim;

 

Eklediğimiz filmleri listeleyelim;

 

Bir tane filmi güncelleyelim;

Ve bir filmi de silelim;

 

Son olarak da CloudWatch üzerinden log'lara bakalım. Search kısmından CloudWatch servisini bulup ilgili sayfaya gidiyoruz. Soldan Log groups kısmına tıklayıp /aws/lambda/movies-function'ı seçiyoruz. Log streams kısmından ilkine tıklayıp bakıyoruz.

 

Umarım yararlı olmuştur.

 

İyi çalışmalar.