Prolog: Kopi, Tantangan Baru, dan Amplify Gen 2
Suatu pagi, di tengah kesibukan harian, sebuah notifikasi masuk ke mejaku:
"Tim butuh endpoint REST API baru untuk menampilkan daftar transaksi. Tapi, ini harus di-deploy pakai Amplify Gen 2, dan yang paling penting: semua harus didefinisikan secara code-first, tanpa intervensi CLI manual!"
Melihat tantangan ini, semangatku langsung terpacu. Secangkir kopi hangat menemaniku, playlist lo-fi mengalun, dan aku siap memulai petualangan di dunia Amplify Gen 2.
Bab 1: Kenalan Dulu Sama Amplify Gen 2
Dulu, bikin backend di AWS Amplify itu identik sama CLI: amplify init, amplify add function, dan kawan-kawan. Tapi sekarang, di Amplify Gen 2, semua resource didefinisikan langsung di TypeScript. Gak ada lagi CLI scaffoldingβsemua serba deklaratif, mirip CDK.
"Jadi, semua resource kayak Lambda, API Gateway, SQS, EventBridge, sampai custom domain, didefinisikan di file TypeScript."
Referensi: Amplify Gen 2 Docs
Bab 2: Struktur Project β Semua Serba TypeScript
Project ini punya struktur kayak gini (dummy, bukan real):
amplify/
βββ backend.ts
βββ functions/
β βββ dummy-api/
β βββ handler.ts
β βββ resource.ts
β βββ types.ts
βββ API/
β βββ dummy-api.ts
β βββ shared/
β βββ api-config.ts
β βββ api-types.ts
βββ utils/
βββ domain-config.ts
Semua resource didefinisikan di amplify/backend.ts pakai defineBackend dari Amplify Gen 2.
Bab 3: Bikin Lambda Function β Gak Ada CLI, Semua di Kode
Dulu, aku biasa bikin Lambda pakai CLI. Sekarang, cukup satu fungsi di TypeScript:
// amplify/functions/dummy-api/resource.ts
import { defineFunction } from '@aws-amplify/backend';
export const DummyListResource = (env: any) => {
return defineFunction({
name: 'DummyList',
entry: './handler.ts',
runtime: 22, // Node.js 22.x
environment: { ...env }
});
};
Handler-nya juga full TypeScript, siap diisi logika bisnis:
// amplify/functions/dummy-api/handler.ts
export const handler = async (event) => {
// Validasi, otorisasi, query database, dll
return {
statusCode: 200,
body: JSON.stringify({ data: [] })
};
};
Bab 4: Definisikan HTTP API β CDK Style, Multi-Endpoint
Di Amplify Gen 2, API Gateway HTTP API didefinisikan langsung di TypeScript, bukan lewat CLI:
// amplify/API/dummy-api.ts
import { Stack } from 'aws-cdk-lib';
import { HttpApi, HttpMethod } from 'aws-cdk-lib/aws-apigatewayv2';
import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations';
import { HttpLambdaAuthorizer } from 'aws-cdk-lib/aws-apigatewayv2-authorizers';
import { getResourceNaming } from '../utils/environment';
import { API_CONFIG } from './shared/api-config';
import { RestDummyApiLambdas } from './shared/api-types';
const DUMMY_CONFIG = {
ENDPOINTS: {
LIST: '/dummy-data/list',
// Future: '/dummy-data/detail', '/dummy-data/export', dst.
}
};
export const DummyAPI = (
stack: Stack,
lambdas: RestDummyApiLambdas
): HttpApi => {
const { createApiName } = getResourceNaming();
const apiName = createApiName('Dummy-API');
const authorizer = new HttpLambdaAuthorizer('DummyAuthorizer', lambdas.auth, {
identitySource: ['$request.header.Authorization'],
resultsCacheTtl: API_CONFIG.AUTH_CACHE_TTL
});
const httpApi = new HttpApi(stack, 'DummyHttpApi', {
apiName,
description: 'HTTP API for dummy data operations',
corsPreflight: {
allowHeaders: API_CONFIG.CORS_HEADERS,
allowMethods: API_CONFIG.CORS_METHODS,
allowOrigins: API_CONFIG.CORS_ORIGINS,
maxAge: API_CONFIG.CORS_MAX_AGE
}
});
const listIntegration = new HttpLambdaIntegration('DummyListIntegration', lambdas.dummyList);
httpApi.addRoutes({
path: DUMMY_CONFIG.ENDPOINTS.LIST,
methods: [HttpMethod.GET],
integration: listIntegration,
authorizer
});
return httpApi;
};
Referensi: CDK HTTP API Docs
Bab 5: Lambda Authorizer β Satu Token untuk Semua
Supaya endpoint REST ini aman, aku pakai Lambda authorizer yang sama dengan GraphQL. JWT token divalidasi di Lambda, dan context user dilempar ke handler.
const authorizer = new HttpLambdaAuthorizer('DummyAuthorizer', lambdas.auth, {
identitySource: ['$request.header.Authorization'],
resultsCacheTtl: API_CONFIG.AUTH_CACHE_TTL
});
Referensi: Lambda Authorizer Docs
Bab 6: Custom Domain & Route53 β Biar Keren dan Mudah Diingat
Biar endpoint-nya nggak pakai URL random, aku setup custom domain pakai Route53 dan ACM. Semua diatur otomatis lewat CDK:
// amplify/utils/domain-config.ts
// ... fungsi getCertificateForService, createDnsRecord, dst.
Di API config:
if (domainConfig) {
setupRestApiDomain(stack, httpApi, domainConfig);
}
Referensi: Custom Domain Docs
Bab 7: Backend Orchestration β Semua Resource Saling Terkoneksi
Semua resource didefinisikan dan dihubungkan di amplify/backend.ts:
import { defineBackend } from '@aws-amplify/backend';
import { AuthResource } from './functions/auth/resource';
import { DummyListResource } from './functions/dummy-api/resource';
import { DummyAPI } from './API/dummy-api';
const asm = await getASMData();
const backendResources = {
auth: AuthResource(asm),
dummyList: DummyListResource(asm),
// ...resource lain
};
const POSBackend = defineBackend(backendResources);
const POSStack = POSBackend.stack;
const dummyAPI = DummyAPI(POSStack, {
auth: POSBackend.auth.resources.lambda,
dummyList: POSBackend.dummyList.resources.lambda,
});
Bab 8: Troubleshooting β Drama Kecil di Tengah Jalan
8.1. CORS Error
Frontend teriak: "has been blocked by CORS policy". Solusi: pastikan CORS diatur di API config.
8.2. Lambda Authorizer Error
Kadang context user nggak kebaca di handler. Ternyata, format context di HTTP API beda sama AppSync. Solusi: parsing context sesuai event source.
8.3. Custom Domain Gagal
Kalau domain nggak muncul, cek environment variable HOSTED_ZONE_ID dan CERTIFICATE_ARN sudah benar.
Bab 9: Lessons Learned β Apa yang Aku Dapat Hari Ini
Bab 10: Referensi Penting
Epilog: Kopi Habis, Endpoint Jadi
Satu pagi, satu endpoint REST API, dan satu gelas kopi. Sekarang giliran kamu: modif handler, sambung ke database, dan bikin bos kamu senyum. Kalau error, jangan panik β debugging itu bagian dari petualangan!
Appendix: Checklist Cepat
Penutup
Kalau kamu baca sampai sini, selamat! Kamu sudah siap bikin REST API serverless di AWS Amplify Gen 2 tanpa drama. Jangan lupa, semua contoh di atas pakai dummy data. Ganti dengan punyamu, dan⦠selamat ngoprek!