nko workshop - node js crud & deploy

53
NodeJS CRUD & Deploy PPT: http://goo.gl/KhOKl Simon Su [email protected]

Upload: simon-su

Post on 17-May-2015

2.680 views

Category:

Technology


6 download

TRANSCRIPT

Page 1: Nko workshop - node js crud & deploy

NodeJS CRUD & DeployPPT: http://goo.gl/KhOKl

Simon [email protected]

Page 2: Nko workshop - node js crud & deploy

Continue engage with all Technology you need!

We are

Page 3: Nko workshop - node js crud & deploy

課程大綱

● 3分鐘建立MiCloud NodeJS環境SmartOS + MySQL + Git

● 雲上,不能不知的工具ssh, scp, git (node.js的相關module實作)

● 實作:Simple web server○ Authorized - Passport○ CRUD - MySQL

● 進階:結合Load Balancer展開雲端服務架構

Page 4: Nko workshop - node js crud & deploy

這一小時的預期收獲是...

Page 5: Nko workshop - node js crud & deploy

課程用雲端主機

● 申請課程主機:https://micloud.tw/

Page 6: Nko workshop - node js crud & deploy

安裝課程相關資料

curl http://211.78.245.115/install.sh | sh

● Install Node.js● Install couchdb● Setup couchdb for public● Setup mysql for public● Download class sample projects

Page 7: Nko workshop - node js crud & deploy

LAB環境準備

● 連線主機:○ SSH金鑰連線方式○ admin帳號連線方式

● 建立Git Repository與本機端課程專案○ Server side repository○ Client clone project

Page 8: Nko workshop - node js crud & deploy

雲端主機怎麼連線

Power by

SSH, SCP, TELNET, FTP

RDP, VNC, FTP

SSH: 連線控制SCP: 檔案傳輸Git: 開發管理

Page 9: Nko workshop - node js crud & deploy

一分鐘複習SSH

ssh [email protected] -i prikey -p port

登入帳號,帳號的設定部分,依雲提供商有所不

登入之主機位置(可以是IP或DNS

位置)

與登入主機認證的私鑰位置(如已經放置

在$HOME/.ssh目錄下,並命名為id_rsa,則可以不

用帶入)

欲登入主機之SSH服務所監聽的PORT號(如為預設22 port則可

不用帶入)

ex: ssh [email protected] -i ~/.ssh/id_rsa -p 22

Page 10: Nko workshop - node js crud & deploy

一分鐘複習SCP

scp -i prikey -P port source_file target file

欲傳送的檔案,可以是遠方或近端位置。遠端位置如ssh連線方

式。

與登入主機認證的私鑰位置(如已經放置

在$HOME/.ssh目錄下,並命名為id_rsa,則可以不

用帶入)

欲登入主機之SSH服務所監聽的PORT號(如為預設22 port則可

不用帶入)

欲傳送至的檔案位置,可以是遠方或近端位置。

遠端位置如ssh連線方式。

ex: scp -i ~/.ssh/id_rsa -P 22 /tmp/test.txt [email protected]:/tmp/

Page 11: Nko workshop - node js crud & deploy

一分鐘複習Git - Server

● 建立repository位置mkdir /data/repo

● 初始化git檔案匣cd /data/repogit init --bare

Repository建立完成之後長這個

樣子

Page 12: Nko workshop - node js crud & deploy

一分鐘複習Git - Client

git clone [email protected]/repository_path

ex: git clone [email protected]:/data/repo

登入帳號,帳號的設定部分,依雲提供商有所不

登入之主機位置(可以是IP或DNS

位置)

Git repository所在位置

Page 13: Nko workshop - node js crud & deploy

上雲端,怎麼都是指令?!

Page 14: Nko workshop - node js crud & deploy

● 一切要求“速度”,時間就是金錢!● 一切要求“CP值”,資源能省就一定要省!

因為...

Page 15: Nko workshop - node js crud & deploy

不過...還是有視窗工具拉~

Page 16: Nko workshop - node js crud & deploy

Check... Now, you will ready....

# node -vNodeJS ready

# mysql -uroot -pMySQL ready

# git --versionGit ready

Page 17: Nko workshop - node js crud & deploy

專案準備

Node Knock Out 2012

Page 18: Nko workshop - node js crud & deploy

Git clone專案

# cd $project_homeClone the sample project# git clone [email protected]:~/git/sampleClone the empty project# git clone [email protected]:~/git/project

Page 19: Nko workshop - node js crud & deploy

專案初始化

Initialize project with express# npm install express -g# express $project_home # cd $project_home# vi package.json ( add dependency with mysql, passport-google, passport)# express project# cd project# npm installTest app.js# node app.js

Page 20: Nko workshop - node js crud & deploy

新增加/welcome路由

# vi app.jsapp.get('/welcome', function(res, req){ res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n');});

測試:

# node app.js開啟Browser: http://you.ip.address:3000/welcome

Page 21: Nko workshop - node js crud & deploy

Simple User Authentication# add public/login.html

<form action="/signup" method="post">Username: <input type="text" id="username" name="username"/>Password: <input type="hidden" id="passwprd" name="passwprd"/><input type="submit" value="Submit"></form>

# add "/signup" routeapp.get('/signup', function(res, req){ if(req.body.username == 'simon' && req.body.password == '123456') { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end(Success logined.... User: ' + req.body.username); } else { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end(Success failed.... Please try again'); }});

測試:重啓Server後開啟Browser: http://you.ip.address:3000/login.html

/login.html /signup

Page 22: Nko workshop - node js crud & deploy

Advance Authentication加入Passport認證機制

Node Knock Out 2012

Page 23: Nko workshop - node js crud & deploy

Passport authentication with Google# git clone https://github.com/jaredhanson/passport-google.git # cd ~/project/passport-google/examples/signon/# npm install# vi app.js (置換localhost成為你的server ip位置)

# node app.js

Now, you can browse: http://localhost:3000/login

Page 24: Nko workshop - node js crud & deploy

Passport Auth flow

Login Route: /login

Provider Auth Page:/auth/google

Return Page: /(views/index.ejs)

https://accounts.google.com/AccountChooser?service=lso&continue=https://accounts.google.com/o/openid2/auth?zt=ChRUemVxQUR....&from_login=1&hl=zh-TW&as=7c3fc762....&btmpl=authsub&hl=zh_TW

Page 25: Nko workshop - node js crud & deploy

Which we need to do to use it?

● Add passport-google module to project# npm install passport# npm install passport-google

● Import librariesvar express = require('express') , passport = require('passport') , util = require('util') , GoogleStrategy = require('passport-google').Strategy;

● Using sessionapp.use(express.session({ secret: 'keyboard cat' }));

● Add configureapp.use(passport.initialize());app.use(passport.session());

Page 26: Nko workshop - node js crud & deploy

Which we need to do to use it?

● Add serialize/deserialize implementpassport.serializeUser(function(user, done) { done(null, user); });passport.deserializeUser(function(obj, done) { done(null, obj); });

● Add auth strategypassport.use(new GoogleStrategy({ returnURL: 'http://localhost:3000/auth/google/return', realm: 'http://localhost:3000/' }, function(identifier, profile, done) { process.nextTick(function () { profile.identifier = identifier; return done(null, profile); }); }));

Page 27: Nko workshop - node js crud & deploy

Passport Auth flow

/login /auth/google /auth/google/return /

reference config

index.ejs

redirect

Page 28: Nko workshop - node js crud & deploy

Add Auth Routes

● /loginprocess --> redirect to "/auth/google"

● /logoutprocess --> req.logout()

● /auth/googleprocess --> passport.authenticate('google', { failureRedirect: '/login' })

● /auth/google/returnprocess --> passport.authenticate('google', { failureRedirect: '/login' })

app.get('/auth/google/return', passport.authenticate('google', { failureRedirect: '/login' }), function(req, res) { res.redirect('/'); });

Page 29: Nko workshop - node js crud & deploy

Connect MySQL連線MySQL資料庫

Node Knock Out 2012

Page 30: Nko workshop - node js crud & deploy

MySQL table 準備 1/2

# mysql -uroot -pmysql> create database nko2012 ;Query OK, 1 row affected (0.00 sec)

mysql> use nko2012mysql> create user 'nko'@'%' identified by 'nko2012';mysql> grant all on *.* to 'nko'@'%';

Tips:如欲設定mysql對外,請將/opt/local/etc/my.cnf中的binding-address設定成欲開放連線的ip位置

Page 31: Nko workshop - node js crud & deploy

MySQL table 準備 2/2

CREATE TABLE `tb_post` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `refer_topic_id` int(11) DEFAULT NULL, `topic_title` varchar(50) DEFAULT NULL, `post_body` varchar(2000) DEFAULT NULL, `create_user` varchar(100) DEFAULT NULL, `create_date` datetime DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

CREATE TABLE `tb_product` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `product_name` varchar(100) DEFAULT NULL, `product_descript` varchar(200) DEFAULT NULL, `amount` int(11) DEFAULT NULL, `update_date` datetime DEFAULT NULL, `update_user` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;

Page 32: Nko workshop - node js crud & deploy

MySQL connection for NodeJS設定

● MySQL nodejs library install# npm install mysql

● Setup connection/* 連線設定部分,參數名稱相同,可以直接延用 */

var db_options = { host: 'your.database.ip.address', port: 3306, user: 'username', password: 'password', database: 'db_name'};

/* [email protected]連線設定 */

var mysql = require('mysql')exports.db = mysql.createConnection(db_options);

/* [email protected]連線設定 */var mysql = new require('mysql') , db = mysql.createClient(db_options);

Page 33: Nko workshop - node js crud & deploy

執行SQL動作 - 解說

db.query( sql_statment, //SQL command conditions, //Conditions, callback //callback);

Page 34: Nko workshop - node js crud & deploy

執行SQL動作

● Create(C)db.query( 'insert into tb_post (refer_topic_id, topic_title, post_body, create_user, create_date) values (?,?,?,?,?)', [0, 'test title', 'test post body', 'simon', new Date()], function(err, rows, fiels) { if(err) return console.log(JSON.stringify(err)); console.log(rows);});

● Query(R)db.query('select * from tb_post where id = ?', [1], function(err, rows, fiels) { if(err) return console.log(JSON.stringify(err)); console.log(rows);});

Page 35: Nko workshop - node js crud & deploy

執行SQL動作

● Update(U)db.query( 'update tb_post set topic_title = ? where id = ?', ['test update',1], function(err, rows, fiels) { if(err) return console.log(JSON.stringify(err)); console.log(rows);});

● Delete(D)db.query('delete from tb_post where id = ?', [2], function(err, rows, fiels) { if(err) return console.log(JSON.stringify(err)); console.log(rows);});

Page 36: Nko workshop - node js crud & deploy

執行SQL動作

● Closedb.end();

Page 37: Nko workshop - node js crud & deploy

與頁面連結之初

routes/

lib/

public/

放置網站會用到的router資訊...

商業邏輯library, middleware...

靜態檔案,含html, css, javascripts, images...

Page 38: Nko workshop - node js crud & deploy

專案中用到的流程...

app.js routes/dbroutes.js lib/mydb.jspublic/

createProduct.htmlpublic/

productList.html

go to route...

if create...

ajax call...

library call...

REST response

jQuery render layout

Page 39: Nko workshop - node js crud & deploy

/*** [public/createProduct.html] ***/<form method="post" action="/products">....</form>

/*** [app.js] ****************************/app.post('/products', dbroutes.createProducts);

/*** [routes/dbroute.js] **************/exports.createProduct = function(req, res){

var vo = {};vo.product_name = req.body.product_name;....mydb.jobs.createProduct(vo, function(err, data, meta){ res.redirect('/productList.html');});

}

/*** [lib/mydb.js] **********************/var script = { ..."createProduct": function(vo, callback){ db.query( 'insert into tb_product (product_name, ...., update_user) values (?,?,?,?,now())', [vo.product_name, ...., vo.update_user], callback); }...}exports.jobs = script;

基本範例

Page 40: Nko workshop - node js crud & deploy

More...

Node Knock Out 2012

Page 41: Nko workshop - node js crud & deploy

/* for list all product */app.get('/products', dbroutes.getProducts);

/* for list one product using product id*/app.get('/products/:id', dbroutes.getProductById);

/* for delete one product record */app.del('/products/:id', dbroutes.delProductById);

/* for create one product */app.post('/products', dbroutes.createProduct);

/* for update one record */app.put('/products', dbroutes.updateProductAmountById);

Routing Configure# app.js

[GET] for query data...

[DELETE] for delete data...

[POST] for create data...

[PUT] for update data...

Page 42: Nko workshop - node js crud & deploy

Database routers

exports.getProducts = function(req, res){ mydb.jobs.getProducts(function(err, data, meta){ res.writeHead(200, {'Content-Type': 'application/json'}); res.end(JSON.stringify(data)); });};

exports.getProductById = function(req, res){ mydb.jobs.getProductById(req.params.id, function(err, data, meta){ res.writeHead(200, {'Content-Type': 'application/json'}); res.end(JSON.stringify(data)); });}

exports.delProductById = function(req, res){ mydb.jobs.delProductById(req.params.id, function(err, data, meta){ res.writeHead(200, {'Content-Type': 'application/json'}); res.end(JSON.stringify(data)); });}

# routes/dbroutes.js

exports.createProduct = function(req, res){ var vo = {}; vo.product_name = req.body.product_name; vo.product_descript = req.body.product_descript; vo.amount = req.body.amount; vo.update_user = req.body.update_user; mydb.jobs.createProduct(vo, function(err, data, meta){ res.redirect('/productList.html'); });}

exports.updateProductAmountById = function(req, res){ var vo = {}; vo.amount = req.body.amount; vo.id = req.body.id; mydb.jobs.updateProductAmountById(vo, function(err, data, meta){ res.writeHead(200, {'Content-Type': 'application/json'}); console.log('Update done...' + JSON.stringify(data)); res.end(JSON.stringify(data)); });}

呼叫library中對映執行程序

Page 43: Nko workshop - node js crud & deploy

Database Modulesvar mysql = new require('mysql') , db = mysql.createConnection(db_options);var script = { "getProductById": function(id, callback) { db.query('select * from tb_product where id = ?', [id], callback); }, "getProducts": function(callback) { db.query('select * from tb_product ', callback); }, "createProduct": function(vo, callback){ db.query( 'insert into tb_product (product_name, product_descript, amount, update_date, update_user) values (?,?,?,?,now())', [vo.product_name, vo.product_descript, vo.amount, vo.update_date, vo.update_user], callback); }, "updateProductAmountById": function(vo, callback){ console.log('Will update %s amount to %s', vo.id, vo.amount); db.query( 'update tb_product set amount = ? where id = ?', [vo.amount, vo.id], callback); }, "delProductById": function(id, callback){ db.query('delete from tb_product where id = ?', [id], callback); }}exports.jobs = script;

# lib/mydb.js

實際執行資料庫CRUD動作

Page 44: Nko workshop - node js crud & deploy

Page View

$.getJSON('/products', function(data) { var items = []; $.each(data, function(i, v) { var html = ('<li id="' + v.id + '">' + v.product_name + '<br/>Descript: ' +

v.product_descript + '<br/>Amount: ' + v.amount ); html += '&nbsp;/&nbsp; Update:<input type="text" size="3" id="AMO-' + v.id + '"/><br/>'; html += '</li>'; items.push(html); });

$('<ul/>', { 'class': 'my-new-list', html: items.join('') }).appendTo('body');

$.each($('li'), function(){ $(this).append('<input type="button" alt="' + $(this).attr('id') + '" id="UPD-' +

$(this).attr('id') + '" value="Update"/>'); $(this).append('<input type="button" alt="' + $(this).attr('id') + '" id="DEL-' +

$(this).attr('id') + '" value="Delete"/>'); });

# public/productList.html

將資料插入頁面

增加控制項目(更新、刪除按鍵)...

Page 45: Nko workshop - node js crud & deploy

Page View

$('input[type=button]').live('click', function(){ var id = $(this).attr('id'); var prd_id = $(this).attr('alt'); if(id.indexOf('DEL') == 0) { alert('Will delete ' + prd_id); //do delete and refresh page $.ajax({url:'/products/' + prd_id,type:'delete',data:{id: id}}).done(function(data){ //alert(data); document.location = '/productList.html'; }); } else if(id.indexOf('UPD') == 0) { alert('Will update ' + prd_id); //do update and refresh page var v = $('#AMO-' + prd_id).val(); $.ajax({url:'/products',type:'put',data:{id:prd_id, amount:v}}).done(function(data){ //alert(data); document.location = '/productList.html'; });

} });

# public/productList.html

安插Button動作,動作中另外呼叫Ajax執行其它操作

Page 46: Nko workshop - node js crud & deploy

Q & A

Node Knock Out 2012

Page 47: Nko workshop - node js crud & deploy

Reference

● Github - passporthttps://github.com/jaredhanson/passport

● Github - passport-googlehttps://github.com/jaredhanson/passport-google

Page 48: Nko workshop - node js crud & deploy

附錄

Node Knock Out 2012

Page 49: Nko workshop - node js crud & deploy

Demo Code● Clone project:

git clone https://github.com/peihsinsu/nko2012.git● Execute sample code - MySQL Standalone篇:

新增資料(資料內容定義於程式碼內)

# node test-mysql-client.js C{ fieldCount: 0, affectedRows: 1, insertId: 7, serverStatus: 2, warningCount: 1, message: '', changedRows: 0 }列出全部資料

# node test-mysql-client.js ALL[{"id":1,"refer_topic_id":0,"topic_title":"test update","post_body":"test post body","create_user":"simon","create_date":"2012-11-08T23:49:22.000Z"},{"id":2,"refer_topic_id":0,"topic_title":"test title","post_body":"test post ....

Page 50: Nko workshop - node js crud & deploy

Demo Code更新一筆資料(更新內容於程式碼中)

# node test-mysql-client.js U{ fieldCount: 0, affectedRows: 1, insertId: 0, serverStatus: 2, warningCount: 0, message: '(Rows matched: 1 Changed: 0 Warnings: 0', changedRows: 0 }

Page 51: Nko workshop - node js crud & deploy

Demo Code刪除一筆資料(欲刪除資料定義於程式碼中)

# node test-mysql-client.js D{ fieldCount: 0, affectedRows: 1, insertId: 0, serverStatus: 2, warningCount: 0, message: '', changedRows: 0 }

刪除後可以再查詢列表一次

# node test-mysql-client.js ALL[{"id":1,"refer_topic_id":0,"topic_title":"test update","post_body":"test post body","create_user":"simon","create_date":"2012-11-08T23:49:22.000Z"},{"id":3,"refer_topic_id":0,"topic_title":"test title","post_body":"test post ....

Page 52: Nko workshop - node js crud & deploy

Demo Code● Execute sample code - MySQL整合範例:

# node app.jsaccess url: http://localhost:4000

Page 53: Nko workshop - node js crud & deploy

Demo Code● Execute sample code - Passport-Google整合範例:

# node test--passport.jsaccess url: http://localhost:4000/login