接下來這篇就會比較偏 server 設定了!
nginx 是一套伺服器軟體,和 apache 並駕齊驅
(其實我覺得 nginx >>> apache XD)
主要是 nginx 清量快速
我們要拿他幫 nodejs 處理接收 request 的部分,再將 request 導往 nodejs
所以感覺就會如下圖:
可以讓 nginx 當作是 load balancer,
透過 reverse proxy 的方式轉發 request 給 nodejs, 讓 nginx 承受流量
這就是我們今天要做的事情,
所以首先,我們就要先裝 nginx,因此就先進虛擬機吧!
$ sudo apt-get update && sudo apt-get upgrade -y $ sudo apt-get install nginx 這樣就會安裝一個 nginx 了!
Nginx 的設定檔都是放在 /etc/nginx/ 底下
個別網站的設定放在 /etc/nginx/sites-available
如果要讓該網站上線,則會將 /etc/nginx/sites-available 的設定檔 link 到 /etc/nginx/sites-enable
Github link
今天要處理刪除
其實超簡單的
只是想偷懶一下 XD
一樣將下列程式碼新增到 RestApi class:
func deleteTodoList(completionHandler: ((NSDictionary!, NSError!) -> Void)!, todoId: String) { var session = NSURLSession.sharedSession() var request = NSMutableURLRequest(URL: NSURL(string: "http://192.168.1.158:3000/user/kerkerj/todos/\(todoId)")!) request.HTTPMethod = "DELETE" var err: NSError? request.addValue("application/json", forHTTPHeaderField: "Content-Type") request.addValue(self.API_key, forHTTPHeaderField: "API-Key") let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in if (error != nil) { return completionHandler(nil, error) } var error: NSError? let json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary println(json) if (error !
Github 參考
接下來兩天要講 deploy 的部分
由於 deploy 的 script 其實非常的麻煩,因此我們就不提 deploy 的 script 了
我們只專注在 server 上需要什麼東西
今天要來看看 forever 這個套件
這個套件可以幫助 nodejs 的 server 遇上無預警的 server 掛掉時
會幫你自動重新啟動 nodejs 的 server
也就是說
假設說 nodejs 寫的 server 某個 route 有問題,
送 request 後會因為某些因素造成 server error 造成程式碼 crash 時
forever 的 monitor 會偵測到,並幫你自動重啟 server
至少不會造成其他正常存取 server 的使用者遭遇到 server down 的問題
這個套件可以選擇裝在 global 或是 project
在這邊我是選擇裝成 global
進到虛擬機
$ npm install -g forever p.
Github link
昨天做了 get list
今天就來做 新增和儲存吧!
可能有人會問說,那讀取一筆 todo 的 API 呢?
因為在這邊資料量少,所有的東西都可以從最外層的 list 拿到
所以雖然有換頁的動作,但是節省流量可以不需要實做這件事
在實際開發中也會如此,case by case,有些情況一次拿完回來處理最好
不過有些則不是~
離題了,
以下是新增 todo 的程式碼:
先到 RestApi.swift 新增 post function
func addTodoList(completionHandler: ((NSDictionary!, NSError!) -> Void)!, content: String) { var session = NSURLSession.sharedSession() var request = NSMutableURLRequest(URL: self.addTodoUrl!) request.HTTPMethod = "POST" var params = ["content": content] as Dictionary<String, String> var err: NSError? request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err) request.addValue("application/json", forHTTPHeaderField: "Content-Type") request.
Github 參考
log 處理 今天要來談談 log 的處理,
身為一台自走 (?) node.js API server
也應該要記錄一下 request 的 log 呀!
不然哪天出問題了都不知道是哪個 request 把 server 搞掛了!
因此我們就要加入 log 的 middleware
node.js 的 log 套件也蠻多的, 例如 winston
不過我們今天要用的是 log4js
會選擇他其實也只是因為之前寫 java 有用過 log4j
log4js 的設定感覺起來比較相似
所以就使用它了!
再來我們就安裝一下 log4js 吧
$ npm install log4js -save 並在 app.js 中 require 進去
var log4js = require('log4js'); 接著在 app.js 的前面區段加入以下程式碼:
log4js.configure({ appenders: [ { type: 'console' }, //控制台輸出 { type: 'file', //文件輸出 filename: 'logs/access.
Github link
(某一天把兩天份的 commit 在一起了忘了開 branch 了…)
接下來就要來寫 api utility 了
我們先開一個 swift 檔案 RestApi.swift
import Foundation class RestApi { var API_key = "55665566" var getListUrl = NSURL(string: "http://192.168.1.158:3000/user/kerkerj/todos") } 先做好前置設定,因為 API 有上簡單的小鎖,因此要先寫起來
還有 request 的網址
以下是 get list 的範例:
func getTodoList(completionHandler: ((NSArray!, NSError!) -> Void)!) { var session = NSURLSession.sharedSession() var request = NSMutableURLRequest(URL: self.getListUrl!) request.HTTPMethod = "GET" request.addValue("application/json", forHTTPHeaderField: "Content-Type") request.addValue(self.API_key, forHTTPHeaderField: "API-Key") let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in if (error !
Github 參考
假設今天我們的 API 上線了,可能就會面臨到一些問題,
例如說,任何人都可以存取我們的 API
當然我們不希望任何人都可以存取,
因此我們必須加一點驗證機制在裡面,
其中一種做法是使用 Oauth token
在拿 API 資料前,先向 Oauth server 要一個 token
Oauth Server 認可身份後即會核發一個 token 給 client 端
該 token 具有時效性,6 mins ~ 30 min 不等,看怎麼實作
接著 client 端就拿該組 token 以及 API url 對 resources server 丟 request
其實我們現在在做的 API server 就是一個 resources server
因為我們提供資源
而 resources server 就會先認 token,
確保該 token 的時效性以及正確性,以及該 token 可存取的資源範圍
確認無誤後再回送正確的資料
不過在這邊我們並沒有要實作 Oauth Server
單純以一個 resources server 而言,只要認 token 是否正確
接下來是要串 隔壁棚的 API XD
從前幾天的 APP 組成
我們所需要的資料大概會是以下幾種:
GET todo list GET http://192.168.1.158:3000/user/kerkerj/todos return: [ { "_id": "54441f64d84f1ea412db855c", "updated_at": "2014-10-19T20:30:28.797Z", "created_at": "2014-10-19T20:30:28.797Z", "content": "task11syy", "user_id": "kerkerj", "__v": 0 }, { "_id": "54441f6fd84f1ea412db855e", "updated_at": "2014-10-19T20:30:39.957Z", "created_at": "2014-10-19T20:30:39.957Z", "content": "task13", "user_id": "kerkerj", "__v": 0 } ] Get a todo task GET http://192.168.1.158:3000/user/kerkerj/todos/54441f64d84f1ea412db855c return: { "_id": "54441f64d84f1ea412db855c", "updated_at": "2014-10-19T20:30:28.797Z", "created_at": "2014-10-19T20:30:28.797Z", "content": "task11syy", "user_id": "kerkerj", "__v": 0 } Add a todo task POST http://192.
Github 參考
不知道大家在用 POSTMAN 對前幾天寫的 API 丟 request 有沒有遇過類似下面的情況:
Cannot GET /user/kerkerj/todoss 通常是丟錯網址時會出現的,或是 code 沒寫好會出現 500 error
這些情況是有辦法接到的,今天我們希望能夠接到後,將 message 轉成 json 格式吐回給 client
因此程式碼如下
app.js
// catch 404 and forward to error handler app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; res.status(404).jsonp({error: "Not Found"}); next(); }); // catch 500 app.use(function(err, req, res, next) { res.status(err.status || 500).json({error: err.message}); }); 基本上這兩段 code 的意思就是加入了兩個 middleware
Github link
(忘了是放在哪個 branch 了 Orz)
接下來就要進到最後一個 Update View 了!
什麼時候會進到 Update View 呢?
是在顯示單筆 TODO 的時候的右上方按鈕:
我們今天只會實作 view 的部分, fakeData 就不實作了
因為接下來就要直接接 API 啦
也不需要更新 fakeData 了 :P
要加入 Edit 這個按鈕
要到 ShowViewController, 加入 UIBarButtonItem
並且讓其吃到一個方法,可以讓 Navigation 往下一個 View 前進:
var id: String! override func viewDidLoad() { super.viewDidLoad() indexLabel.text = "\(index)" contentLabel.text = content self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Edit", style: UIBarButtonItemStyle.Bordered, target: self, action: Selector("editTodo")) } p.s. 先前忘記加了 id, 現在補回來 XD