sailsjs differentiate api and view controller

Sails 是一套我相當喜歡的 Node.js web framework,底層仍然是使用 Express.js,另外整合了很多常用的 web 套件:grunt, socket.io, RESTful API, ......等。

由於 sails 的架構與 codeigniter 相當類似,Controller 對應到 View,並且對應到 route,在 config 中有個 controller.js 還可以對所有的 controller 做設定,如自動產生 restful api 等,以及這次的重點「prefix」,prefix 設定後在 route 上就會自動改變如下

使用 prefix 前
http://localhost/CONTROLLER_NAME/ACTION_NAME

使用 prefix 後( prefix 設定為 '/api/')
http://localhost/api/CONTROLLER_NAME/ACTION_NAME

如果只是要做 api server 相信這會是個很棒的設計,還可以作為 api 的版本區分(例如「/api/v1/」),但要做「網站」在 view 與 api 之間就必須做些區分,以下的作法就是將 view 與 api 切開,view 統一由 ViewController 控制,其他的 api 交由一般的 controller 控制,從 route 看起來如下
// ViewController
// Get user or user's view
http://localhost/user

// UserController
// Get user '1' api
http://localhost/api/user/1

資料夾目錄如下
/api
    /adapters
        ...
    /controllers
        ViewController.js
        ...
    /models
        ...
    /services
        ...
/assets
    /bower_components
        ...
    /images
        ...
    /scripts
        ...
    /styles
        ...
    /fonts
        ...
    favicon.ico
    robots.txt
/config
    /locales
        ...
    404.js
    500.js
    adapters.js
    bootstrap.js
    controller.js
    cors.js
    csrf.js
    i18n.js
    local.js
    log.js
    policies.js
    routes.js
    session.js
    sockets.js
    views.js
/node_modules
    ...
/views
    /home
        index.ejs
        ...
.bowerrc
.gitignore
app.js
bower.json
Gruntfile.js
package.json
README.md
view raw structure.md hosted with ❤ by GitHub


接下來開始實作把 api 與 view 切開
首先是設定好 api 的 prefix,修改 「/config/controllers.js」
/**
* Controllers
*
* By default, Sails controllers automatically bind routes for each of their functions.
* Additionally, each controller will automatically bind routes for a CRUD API
* controlling the model which matches its name, if one exists.
*
* NOTE: These settings are for the global configuration of controllers.
* You may also override these settings on a per-controller basis
* by modifying the 'blueprints' object in your controllers
*
* For more information on controller configuration and blueprints, check out:
* http://sailsjs.org/#documentation
*/
module.exports.controllers = {
blueprints: {
// Optional mount path prefix for blueprints
// (the automatically bound routes in your controllers)
// e.g. '/api/v2'
prefix: '/api',
// Whether routes are automatically generated for every action in your controllers
// (also maps `index` to /:controller)
// '/:controller', '/:controller/index', and '/:controller/:action'
actions: true,
// ** NOTE **
// These CRUD shortcuts exist for your convenience during development,
// but you'll want to disable them in production.
// '/:controller/find/:id?'
// '/:controller/create'
// '/:controller/update/:id'
// '/:controller/destroy/:id'
shortcuts: true,
// Automatic REST blueprints enabled?
// e.g.
// 'get /:controller/:id?'
// 'post /:controller'
// 'put /:controller/:id'
// 'delete /:controller/:id'
rest: true,
// If a blueprint route catches a request,
// only match :id param if it's an integer
//
// e.g. only trigger route handler if requests look like:
// get /user/8
// instead of:
// get /user/a8j4g9jsd9ga4ghjasdha
expectIntegerId: false
}
};
view raw controllers.js hosted with ❤ by GitHub


再來是設定 route 把 view 改為 '/',修改「/config/routes.js」
routes.js
/**
* Routes
*
* Sails uses a number of different strategies to route requests.
* Here they are top-to-bottom, in order of precedence.
*
* For more information on routes, check out:
* http://sailsjs.org/#documentation
*/
module.exports.routes = {
'/': 'ViewController.index',
'/:page': {
controller: 'ViewController',
action: 'page'
}
};
view raw routes.js hosted with ❤ by GitHub


最後是產生 ViewController,在 terminal 輸入
sails generate controller view

並修改 「/api/controllers/ViewController.js」
/**
* ViewController
*
* @module :: Controller
* @description :: Contains logic for handling requests.
*/
module.exports = {
index: function(req, res) {
console.log('viewController index begin');
return res.view('home/index.ejs', {
// layout default in the same folder
// layout: 'layout',
});
},
/**
* redirect to right page
* i.e http://localhost:3000/user
* ^^^^^^
* page = user
* controller will redirect to ViewController/user
*
* @param {String} page redirect to page
*/
page: function(req, res) {
var page = req.param('page');
return sails.controllers.view[page](req, res);
},
user: function(req, res) {
return res.view('user/index.ejs');
}
};



ps. 或許也可以直接做 single page design,但某些狀況下透過 controller 可以從 server side 將其他訊息一併回給前端

完整的 code 可至 Gist 查看

相關連結
Sails
Node.js
grunt
socket.io
Express.js
codeigniter

沒有留言:

張貼留言