Go to IAM Console → Roles → Create role
Trusted entity type:
Add permissions:
AWSLambdaVPCAccessExecutionRoleAWSLambdaBasicExecutionRoleRole details:
daivietblood-lambda-roleClick Create role
mkdir -p nodejs
cd nodejs
npm init -y
npm install mysql2
cd ..
zip -r mysql2-layer.zip nodejs
Go to Lambda Console → Layers → Create layer
Configure:
mysql2-layermysql2-layer.zipClick Create
Go to Lambda Console → Functions → Create function
Basic information:
daivietblood-get-usersdaivietblood-lambda-roleClick Create function
Add Layer:
mysql2-layerConfigure VPC:
daivietblood-vpcdaivietblood-lambda-sgAdd Environment Variables:
DB_HOST = daivietblood-db.xxxx.ap-southeast-1.rds.amazonaws.com
DB_PORT = 3306
DB_NAME = daivietblood
DB_USER = admin
DB_PASSWORD = YourSecurePassword123!
Add code in Code tab:
const mysql = require('mysql2/promise');
let connection;
const getConnection = async () => {
if (!connection) {
connection = await mysql.createConnection({
host: process.env.DB_HOST,
port: process.env.DB_PORT,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME
});
}
return connection;
};
exports.handler = async (event) => {
try {
const conn = await getConnection();
const [rows] = await conn.execute('SELECT * FROM users');
return {
statusCode: 200,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify(rows)
};
} catch (error) {
console.error('Error:', error);
return {
statusCode: 500,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify({ error: 'Internal server error' })
};
}
};
daivietblood-create-userconst mysql = require('mysql2/promise');
let connection;
const getConnection = async () => {
if (!connection) {
connection = await mysql.createConnection({
host: process.env.DB_HOST,
port: process.env.DB_PORT,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME
});
}
return connection;
};
exports.handler = async (event) => {
try {
const body = JSON.parse(event.body);
const { email, name, blood_type, phone } = body;
if (!email || !name || !blood_type) {
return {
statusCode: 400,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify({ error: 'Missing required fields' })
};
}
const conn = await getConnection();
const [result] = await conn.execute(
'INSERT INTO users (email, name, blood_type, phone) VALUES (?, ?, ?, ?)',
[email, name, blood_type, phone || null]
);
return {
statusCode: 201,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify({
id: result.insertId,
email,
name,
blood_type,
phone
})
};
} catch (error) {
console.error('Error:', error);
if (error.code === 'ER_DUP_ENTRY') {
return {
statusCode: 409,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify({ error: 'Email already exists' })
};
}
return {
statusCode: 500,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify({ error: 'Internal server error' })
};
}
};
daivietblood-emergency-requestsconst mysql = require('mysql2/promise');
let connection;
const getConnection = async () => {
if (!connection) {
connection = await mysql.createConnection({
host: process.env.DB_HOST,
port: process.env.DB_PORT,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME
});
}
return connection;
};
exports.handler = async (event) => {
const conn = await getConnection();
const method = event.httpMethod;
try {
if (method === 'GET') {
const [rows] = await conn.execute(
'SELECT * FROM emergency_requests WHERE status = "open" ORDER BY urgency DESC, created_at DESC'
);
return {
statusCode: 200,
headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' },
body: JSON.stringify(rows)
};
}
if (method === 'POST') {
const body = JSON.parse(event.body);
const { requester_name, blood_type, units_needed, hospital, urgency } = body;
const [result] = await conn.execute(
'INSERT INTO emergency_requests (requester_name, blood_type, units_needed, hospital, urgency) VALUES (?, ?, ?, ?, ?)',
[requester_name, blood_type, units_needed, hospital, urgency || 'normal']
);
return {
statusCode: 201,
headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' },
body: JSON.stringify({ id: result.insertId, message: 'Emergency request created' })
};
}
return {
statusCode: 405,
headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' },
body: JSON.stringify({ error: 'Method not allowed' })
};
} catch (error) {
console.error('Error:', error);
return {
statusCode: 500,
headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' },
body: JSON.stringify({ error: 'Internal server error' })
};
}
};