2013年8月4日 星期日

GitLab one click installer

GitLab是一套提供類似Private Github服務的軟體,開放且因為使用上親近Github,所以是套非常建議每個開發Team都安裝的服務... 實際上看過GitLab的手動安裝方式,其實相當複雜,但是因為有Bitnami這個熱心的服務者打包GitLab的服務,讓Linux上安裝非常的方便...

目前我常試過CentOS的安裝方式,原則上是下載下來後,直接執行:
執行安裝:
# chmod u+x bitnami-gitlab-5.4.0-0-linux-x64-installer.run
# ./bitnami-gitlab-5.4.0-0-linux-x64-installer.run


----------------------------------------------------------------------------
Welcome to the BitNami GitLab Stack Setup Wizard.

----------------------------------------------------------------------------
Select the components you want to install; clear the components you do not want
to install. Click Next when you are ready to continue.

GitLab : Y (Cannot be edited)

GitLab CI [Y/n] :
Is the selection above correct? [Y/n]:
----------------------------------------------------------------------------
Installation folder

Please, choose a folder to install BitNami GitLab Stack

Select a folder [/opt/gitlab-5.4.0-0]:
----------------------------------------------------------------------------
Create Admin account

BitNami GitLab Stack admin user creation

Login [user]: root

Password :
Please confirm your password :

----------------------------------------------------------------------------
Hostname that will be used to create internal URLs. If this value is incorrect,
you may be unable to access your Gitlab installation from other computers. It is
advisable to use a Domain instead of an IP address for compatibility with
different browsers.

Domain [127.0.0.1]: xxx.xxx.xxx.xxx

Do you want to configure mail support? [y/N]: y

----------------------------------------------------------------------------
Configure SMTP Settings

This is required so your application can send notifications via email.

Default email provider:

[1] GMail
[2] Custom
Please choose an option [1] : 1

----------------------------------------------------------------------------
Configure SMTP Settings

Default mail server configuration.

GMail address []: simonsu@mitac.com.tw

GMail password :
Re-enter :
----------------------------------------------------------------------------
Setup is now ready to begin installing BitNami GitLab Stack on your computer.

Do you want to continue? [Y/n]: Y

----------------------------------------------------------------------------
Please wait while Setup installs BitNami GitLab Stack on your computer.

 Installing
 0% ______________ 50% ______________ 100%
 #########################################

----------------------------------------------------------------------------
Setup has finished installing BitNami GitLab Stack on your computer.

Info: To access the BitNami GitLab Stack, go to
http://xxx.xxx.xxx.xxx:80 from your browser.
Press [Enter] to continue :

完成安裝之後,就可以透過80 port連線進入該主機,畫面與操作上與Github真的頗為相像,後續有趣的地方就留給有興趣的網友去發現了 :D



2013年7月30日 星期二

Ejs page scope直接使用session物件的方式

在ExpressJS中,使用Ejs view engine時,發現session不能再ejs page中直接取用,所有參數都必須靠render時候傳遞過去...跟asp, jsp等scriptlet language操作上有明顯的不同...@@

為了達到可以在ejs中直接取用,這邊可以使用ejs page的locals變數,locals變數在route設定時候可以使用res.locals來取出,這時候只要將它與req.session做串連(res.locals.session = req.session)即可讓前端的ejs page直接透過<%=locals.session%>或是<%=session%>的方式來操作session...

而如果要在每一個route中設定res.locals.session,這樣也太麻煩... 我們可以透過app.use的方式來設定:

app.use(function(req, res, next){
  res.locals.session = req.session;
  next();
});

這樣所有的route在執行的時候都會先跑過一次這個動作,所以在使用時候可以這樣:

[app.js]
app.get('/', function(req, res) {
  req.session.user = {name: 'simon'}
  ...(skip)
});

[view/index.ejs]
...(skip)
<%=session.user? 'got user: '+session.user.name : 'no user...'%>
...(skip)

這時候從ejs取用session的物件就單純多了 :D

在ExpressJS中進階使用Ejs view engine

在操作ExpressJS的Ejs View Engine時候
發現針對頁面上的操作並不是那麼的順心
舉個例子:
app.js中做一個route希望能夠將值往前端(.ejs)帶,但是前端implement了express-partials的模組,希望把頁面用template的方式組織起來,並且在template page中會用到一部分的參數... 假設有時個route用到這個template,則每個route都必須把參數設定進去,否則後端會接收到"not defined"的錯誤訊息...

上面例子的片段程式碼如下:

[app.js]
app.get('/', function(req, res){
  res.render('index', { title: 'my express page' });
});

[index.ejs]
<% if(user) { %>
<%= user %>
<% } %>

執行時候會有Exception:
...(skip)
user is not defined
...(skip)

這部份的錯誤應該是Ejs在render page時候造成的,它直接throw Exception而會造成page終止render,在遍尋不著比較好的方法時,從某篇文章找到一些蛛絲馬跡...

原來Ejs使用"locals"這個物件來包裝頁面上會用到的所有參數,而經過ejs的scriptlet tag包裝起來的部分,可以直接使用locals裡面的參數,也就是說上面的app.js做page render時候:

res.render('index', { title: 'my express page' })

相當於把title這個參數與ejs頁面的locals變數做整合
亦即ejs頁面操作:

<%=title%>


<%=locals.title%>

是相等的,但是直接操作title屬性時候,會被ejs compile成runtime exception,這導致如果在ejs中執行下面判斷會出錯;

<% if(user) { .... %>

因為實際上locals.user不存在,且ejs compiler會將不存在的狀況throw exception...

解決方式,直接使用locals來判斷裡面是否有user這個變數...,因此改寫上面的判斷後:

<% if(locales['user']) { .... %>

應該就可以正常運作...

2013年6月22日 星期六

About HTTP delete method error response

記錄一個比較不常用到的操作方式...
以client使用request module為例...
http delete method中,某些client遇到error時,解讀回覆部分不是直接取用body
而是去解析error物件來做回覆
此時如何從server端製作一個錯誤來讓client操作呢...

下面是client端的模擬code,主要client端想要取出callback function中的error物件...

Client side:
var opts = {url:'http://localhost:1337/test/123', method:'DELETE'};
request(
  opts, 
  function(error,res,body) {
    console.log(e);
  }
);

此時server side的實作,以express為例,只需要在res.send()中依序帶入:
  • 第一個欄位設定錯誤代碼
  • 第二個欄位為錯誤物件描述,建議以JSON為格式(預設格式為{code: xxx, message:xxx},若符合此格式,回覆時候匯自動取message內文做為error的message欄位,並會在error物件中多一個code的欄位}
下面模擬del協定,於呼叫時候丟錯:

Server side:
app.del('/test/:id', function(req, res) {
  res.send(400, {code:"test error", message:"the tested error"});
});

此時client的console pring匯出現下面訊息:

Client result: 
{ message: 'the tested error',
  body: { code: 'test error', message: 'the tested error' },
  httpCode: 400,
  statusCode: 400,
  restCode: 'test error',
  code: 'test error' }

如上描述,如果server改寫response回傳物件(不使用預設格式)...

Server side:
app.del('/test/:id', function(req, res) {
  res.send(400, {coder:"test error", msg:"the tested error"});
});

則,error物件會長這樣子:

{ message: '{\n  "coder": "test error",\n  "msg": "the tested error"\n}',
  body: { coder: 'test error', msg: 'the tested error' },
  httpCode: 400,
  statusCode: 400 }

Log4js support print object inline

log4js套件是我常使用的log管理工具
最近看別人的程式才發現,原來它有支援物件的列印
透過 log.info('......%o....', jsonObject) 的方式
可以直接把物件解析成String...
真是方便的功能∼

範例:

執行結果:


更正,不是%o造成的
應該是log4js將最後一個參數使用像console.log(object)的方式
解些json物件成為string...

2013年6月11日 星期二

Access-Control-Allow-Origin範例

在JS的世界裡,Ajax的頭號天敵就是為了避免不安全,Browser所設限的coss site not allow的限制,為了避免cross site javascript的問題,傳統作法是透過script tag來嵌入非同個網站的資源,或是使用jsonp來做site to site的呼叫,但是...

  • script tag內文必須要是script,否則無法順利讀取,甚至會弄壞網頁中的js...
  • jsonp已經被chrome排擠... firefox可以正常使用
有了Node.js的request套件後,我們大可以一行解決... 讓遠方資源變成我發資源:
request.get('http://mysite.com/doodle.png').pipe(resp)
上面可以讓原本需要透過http://mysite.com/doodle.png 來呼叫的資源,透過你制定的鏈結呼叫該資源...
而,根本的解決方式可以使用Header中加入Access-Control-Allow-Origin參數來設定你的js,允許讓其他網站來呼叫...
Server端實作:

See:/examples/basic/http/cross-site-server.js

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200,{"Access-Control-Allow-Origin": "http://10-20-0-31.my.micloud.tw"});
  res.end(JSON.stringify({result:'yes'}));
}).listen(8080);
console.log('Server running at port 8080');
上面設定資源可以讓site:http://10-20-0-31.my.micloud.tw 下面的網頁來呼叫,如果想要讓所有網站都可以呼叫,可以使用"*"來讓所有網站可以呼叫...
Client端實作:

See:/examples/basic/http/cross-site.html

<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
$(document).ready(function(){
  $.getJSON('http://211.78.254.38:8080/', function(data){
    $('#r').html(data.result);
  });
});
</script>
<h1>Server response: <span id="r"></span></h1>