ในบทความนี้จะเป็นวิธีการสร้าง Restful API ที่มีหน้าที่ให้ Front-end (Angular) เรียกใช้งานเพื่อเข้าถึงฐานข้อมูลในรูปแบบการทำงานต่างๆ
ซึ่งไฟล์หลักๆที่จะกล่าวถึงในบทความนี้ก็คือ app.js และ api.js (/routes/api.js)
app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser')
var logger = require('morgan');
var favicon = require('serve-favicon');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var apiRouter = require('./routes/api').router;
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(bodyParser.text())
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(favicon(__dirname + '/public/images/favicon.ico'));
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/api', apiRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
ไฟล์นี้จะเป็นไฟล์หลักในการทำงานของ Express (เฉพาะการประกาศการใช้งาน router และ module ต่างๆที่จำเป็น)จะเห็นได้ว่า มีการประกาศตัวแปรที่ชื่อว่า app ซึ่งเป็น express object และเมื่อเราทำการนำ module ต่างๆ เช่น bodyParser, cookieParser ใส่ลงไป app แล้วส่วนต่อไปจะเป็นการใส่ router ที่ใช้ในการ Handling APIต่างๆที่สร้างขึ้นมา
โดย /routes/api.js ก็คือไฟล์หลักที่กำหนด path Restful API ที่ใช้ในระบบ NBLOGIC
api.js
ส่วนแรกจะเป็นส่วนของการ Import Module เข้ามาใช้งานภายในไฟล์นี้var express = require('express');
var router = express.Router();
const request = require('request')
const {PythonShell} = require('python-shell');
var cors = require('cors');
var mysql = require('mysql');
const nblogic_node = '/home/ec2-user/nblogic/routes/nblogic_node.py';
var _ = require('lodash');
require('dotenv').config()
ส่วนต่อไปจะเป็นส่วนที่กำหนด option ของ MySQL ที่เราจะทำการสร้าง Connection แบบ Pool ไว้var connection = mysql.createPool({
localAddress: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASS,
database: "nblogic",
port: 3306,
socketPath: '/var/lib/mysql/mysql.sock',
multipleStatements: true
});
ต่อไปจะเป็นตัวอย่างของ ส่วนการทำงาน (Function) ที่ขอข้อมูลของนักศึกษา (Student)
const sqlQuery = (query, data) => {
return new Promise((resolve, reject) => {
data?connection.query(query, data, (error, result) => {
queryHandle(resolve, reject, result, error)
}):connection.query(query, (error, result) => {
queryHandle(resolve, reject, result, error)
})
})
}
const getUserData = (username) => {
return sqlQuery(`SELECT * FROM student WHERE student.Student_ID = ${username}`)
}
const getUserAttemps = (username) => {
return sqlQuery(`SELECT attemps.Course_id, Name, Year, Semester, Grade FROM attemps INNER JOIN course
ON course.Course_id = attemps.Course_id WHERE attemps.Student_ID = ${username}
`)
}
router.get('/db/user/:userId', cors(), (req, res, next) => {
var userId = req.params.userId;
getUserData(userId).catch(error => {
res.status(500).send(error)
}).then(data_result => {
return data_result
}).then(data_result => {
getUserAttemps(userId).catch(error => {
res.status(500).send(error)
}).then(attemp_result => {
res.send({"User_Bio": data_result[0], "Attemps": attemp_result});
})
})
});
ก่อนที่จะพูดถึงในส่วนของ function ของการ login ต่อไปจะกล่าวการเขียนสคริปต์ Python
ซึ่งเป็นการเขียนสคริปต์ เพื่อเรียกใช้ module NBLOGIC ของ Python เพื่อที่จะใช้งานในส่วนการเข้าสู่ระบบของ KLOGIC ซึ่งจะได้มาซึ่งข้อมูลของนักศึกษาเกือบทั้งหมด
import sys
import json
import nblogic
nb = nblogic.KLOGIC(apiMode=True)
args = sys.argv
username = args[1]
password = args[2]
mode = args[3]
if(nb.authentication(username, password)):
if mode == "authen":
nb.get_bio()
nb.get_information()
nb.get_program_course()
print(json.dumps(json.loads(nb.json(language="EN"))))
sys.stdout.flush()
หลังจากได้รับข้อมูลจาก Python(PythonShell) ผ่าน sys.stdout.flush() แล้วก็จะถูกนำไปใช้ในไฟล์ api.js ต่อไป ดังโค้ด
router.post('/klogic', cors(), function(req, res, next) {
let username = req.body.username;
let password = req.body.password;
let api_mode = req.body.api_mode;
let options = {
args: [username, password, "authen"],
pythonPath: '/usr/bin/python3.7',
}
console.log(req.body)
if (username && password) {
PythonShell.run(nblogic_node, options, function (err, results) {
if (err) {
res.status(500).send(err);
}
console.log('nblogic_node finished.');
console.log(results)
results_json = JSON.parse(results);
if (results_json !== null) {
api_mode ? res.send(results_json) : res.render('profile', { title: "NBLOGIC", data: results_json['User_Bio'] });
let user_bio = results_json['User_Bio']
var full_course = results_json['User_Summary'];
sqlQuery("INSERT INTO student SET ?", user_bio).then(result => {
console.log("INSERT STUDENT SUCCESS");
return sqlQuery(`UPDATE student SET GPAX = ${user_bio.GPAX} WHERE Student_ID = "${user_bio.Student_ID}"`)
}).catch(errorHandle).then(result => {
console.log("UPDATE GPAX SUCCESS");
return sqlQuery("INSERT IGNORE INTO course (Name, Course_id, Credit_points) VALUES ?", [full_course.all_course.map(course =>
[course.Name, course.Course_id, course.Credit_points])])
}).catch(errorHandle).then(result => {
console.log("INSERT COURSE SUCCESS")
return sqlQuery("INSERT IGNORE INTO attemps (Student_id, Course_id, Year, Semester, Grade) VALUES ?", [full_course.attemp.map(attemp =>
[attemp.Student_id, attemp.Course_id, attemp.Year, attemp.Semester, attemp.Grade])])
}).catch(errorHandle).then(result => {
console.log("INSERT Attemps SUCCESS")
return sqlQuery("INSERT IGNORE INTO contains (Program_id, Course_id) VALUES ?", [full_course.all_course.map(course_ =>
[full_course.User_info.Program_ID, course_.Course_id])])
}).catch(errorHandle).then(result => {
console.log("INSERT Contains SUCCESS")
results_json = null;
}).catch(errorHandle)
}
else {
res.status(500).send('Something broke!')
}
});
} else {
res.status(401).send("Unauthorize!")
}
});
