Thursday, April 24, 2008

rails2.0.2 fastcgi sqlite3 setup

# add below line to /etc/hosts
127.0.0.1 www.test.com

# add below green lines at the end of lighttpd.conf file


$HTTP["host"] == "www.test.com" {
server.document-root = "/Users/test/Sites/RubyOnRails/public"
server.errorlog = "/Users/test/Sites/lighttpd/logs/rails.lighttpd.error.log"
server.indexfiles = ( "dispatch.fcgi", "index.html" )
accesslog.filename = "/Users/test/Sites/lighttpd/logs/rails.access.log"
server.error-handler-404 = "/dispatch.fcgi"
fastcgi.server = ( ".fcgi" =>
( "localhost" =>
(
"socket" => "/tmp/rails-fastcgi.socket",
"bin-path" => "/Users/test/Sites/RubyOnRails/public/dispatch.fcgi",
"bin-environment" => ("RAILS_ENV" => "development"),
"max-procs" => 3,
"min-procs" => 1
)
)
)
}

wget http://www.sqlite.org/sqlite-3.5.8.tar.gz
tar zxvf sqlite-3.5.8.tar.gz
cd sqlite-3.5.8
./configure --prefix=/usr/local/sqlite358
make
sudo make install

# create db files under rails app db folder
cd /Users/test/Sites/RubyOnRails/db
/usr/local/sqlite358/bin/sqlite3 development.sqlite3
/usr/local/sqlite358/bin/sqlite3 test.sqlite3
/usr/local/sqlite358/bin/sqlite3 production.sqlite3

sudo gem install sqlite3-ruby

# restart lighttpd, and request url: http://www.test.com

json 解析工具

当Ajax请求返回的数据为JSON格式的字符串,需要对此字符串进行解析,如果自己在JS中处理的话,按以下方式调用:
eval('(' + json + ')');
用js的library的话,在prototypejs里String有个方法evalJSON()可以使用,Extjs里有一个JSON相关的Util组件,也可以用json官方网站提供的一个js: http://www.json.org/json.js

Wednesday, April 23, 2008

lighttpd php fastcgi and 500 internal error

当访问php页面时,得到一个500服务器内部错误(500 internal error ),服务器端错误日志如下:


2008-04-23 23:20:50: (mod_fastcgi.c.1743) connect failed: Connection refused on unix:/tmp/php-fastcgi.socket-3
2008-04-23 23:20:50: (mod_fastcgi.c.2912) backend died; we'll disable it for 5 seconds and send the request to another backend instead: reconnects: 0 load: 1
2008-04-23 23:20:50: (mod_fastcgi.c.2471) unexpected end-of-file (perhaps the fastcgi process died): pid: 350 socket: unix:/tmp/php-fastcgi.socket-3
2008-04-23 23:20:50: (mod_fastcgi.c.3281) response not received, request sent: 872 on socket: unix:/tmp/php-fastcgi.socket-3 for /php/phpinfo.php , closing connection

用lighttpd fastcgi模式调用php时报以上错误,在lighttpd官方网站上查到,是因为php在编译时未指定--enable-fastcgi, 于是重新编译了最新版的php5.2.5:

./configure --prefix=/usr/local/php5 --with-zlib --enable-fastcgi --with-mysql=/usr/local/mysql --enable-mbstring --enable-sockets --enable-gd-native-ttf --with-snmp --enable-soap
make
sudo make install

重启lighttpd之后即可正确访问php文件。

firefox bug when using iframe and javascript alert() function


<iframe src="http://localhost/perl/cgi.pl" height=1 width=1></iframe>

<script type="text/javascript" charset="utf-8">
alert('test');
window.location = "http://localhost/javascript/index.html";
</script>

以上代码在ie7和safari里调用的都会去请求iframe的src指向的URL,但在Firefox里这个动作却并不会执行,在server端不会收到这个GET请求。
必须在iframe之外加一些html标签,如img/body等才能使此iframe的src指向的请求被执行。如下所示:

<html>

<body>

<iframe src="http://localhost/perl/cgi.pl" height=1 width=1></iframe>

<script type="text/javascript" charset="utf-8">
alert('test');
window.location = "http://localhost/javascript/index.html";
</script>

</body>
</html>

lighttpd install and configure

# install libevent
curl -O http://www.monkey.org/~provos/libevent-1.4.3-stable.tar.gz
tar xzvf libevent-1.4.3-stable.tar.gz
cd libevent-1.4.3-stable
./configure --prefix=/usr/local/libevent143
make
sudo make install

# install memcached
curl -O http://www.danga.com/memcached/dist/memcached-1.2.5.tar.gz
tar xzvf memcached-1.2.5.tar.gz
cd memcached-1.2.5
./configure --prefix=/usr/local/memcached125 --with-libevent=/usr/local/libevent143
make
sudo make install

#install pcre in order to install lighttpd
curl -O ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-6.6.tar.gz
tar zxvf pcre-6.6.tar.gz
cd pcre-6.6
./configure --prefix=/usr/local/pcre66
make
sudo make install

#modify PATH include /usr/local/pcre66/bin, add below command to .bashrc or .profile or .bash_profile etc.
$> export PATH="/usr/local/pcre66/bin:$PATH"

# install lighttpd
curl -O http://www.lighttpd.net/download/lighttpd-1.4.19.tar.gz
tar zxvf lighttpd-1.4.19.tar.gz
cd lighttpd-1.4.19
./configure --prefix=/usr/local/lighttpd1419 --with-zlib --with-pcre --with-openssl
make
sudo make install

# lighttpd.conf example


server.modules = (
"mod_rewrite",
"mod_redirect",
"mod_fastcgi",
"mod_proxy",
"mod_userdir",
"mod_cgi",
"mod_usertrack",
"mod_accesslog"
)

server.name = "localhost"
server.document-root = "/Users/test/Sites/Public"
server.errorlog = "/Users/test/Sites/lighttpd/logs/lighttpd.error.log"
accesslog.filename = "/Users/test/Sites/lighttpd/logs/access.log"

server.port = 80

server.username = "test"
server.groupname = "admin"

mimetype.assign = (
".html" => "text/html",
".txt" => "text/plain",
".jpg" => "image/jpeg",
".png" => "image/png"
)

static-file.exclude-extensions = ( ".fcgi", ".php", ".rb", "~", ".inc" )
index-file.names = ( "index.html" )

$HTTP["host"] == "www.test.com" {
server.document-root = "/Users/test/Sites/CakePHP/"
}

### for PHP don't forget to set cgi.fix_pathinfo = 1 in the php.ini
fastcgi.server = ( ".php" =>
( "localhost" =>
(
"socket" => "/tmp/php-fastcgi.socket",
"bin-path" => "/usr/local/php5/bin/php-cgi"
)
)
)

### CGI module
cgi.assign = ( ".pl" => "/usr/bin/perl",
".cgi" => "/usr/bin/perl",
".py" => "/usr/bin/python",
".rb" => "/usr/local/ruby186/bin/ruby"
)

# lighttpd server start
$> /usr/local/lighttpd1419/sbin/lighttpd -f lighttpd.conf

Monday, April 21, 2008

install fastcgi and ruby-fastcgi

curl -O http://www.fastcgi.com/dist/fcgi-2.4.0.tar.gz
tar xzvf fcgi-2.4.0.tar.gz
cd fcgi-2.4.0
./configure --prefix=/usr/local/fcgi240
make
sudo make install
cd ..

# install Ruby-FastCGI gem

curl -O http://rubyforge.iasi.roedu.net/files/fcgi/ruby-fcgi-0.8.7.tar.gz
tar xzvf ruby-fcgi-0.8.7.tar.gz
cd ruby-fcgi-0.8.7
/usr/local/bin/ruby install.rb config -- --with-fcgi-dir=/usr/local/fcgi240
/usr/local/bin/ruby install.rb setup
sudo /usr/local/bin/ruby install.rb install
cd ..

# or install Ruby-FastCGI gem using:
$> sudo gem install fcgi -- --with-fcgi-dir=/usr/local/fcgi240

# Building native extensions. This could take a while...
# Successfully installed fcgi-0.8.7
# 1 gem installed

Thursday, April 17, 2008

img的onload事件说明


<script type="text/javascript">
function test() {alert('test');}
</script>
<img src="a.png" onload="test()" />

当img的src指向的a.png不是一个实际的png文件,比如是个空文本文件名为a.png(文件大小为0字节),此时就不会触发onload事件,实际发生的此img.onerror事件。
如果往此文件中写入一个字符,使文件大小大于0字节,此时在Firefox中能触发onload事件,在IE中则因为图片加载不正常,会在页面上显示一个加载图片失败的X图形,并触发的是onerror事件。

还原apache访问日志中的URL查询字符串

当IE在访问URL:
http://localhost/a.html?q=中文
在apache日志里能看到以下内容:
GET /a.html?q=\xd6\xd0\xce\xc4 HTTP/1.1

而在Firefox中访问相同URL:
日志中看到的内容是对字符串进行urlencode过后的格式:
GET /a.html?q=%D6%D0%CE%C4 HTTP/1.1

现在IE下,\xXX这种看上像2位16进制值XX指定的1个字符(可能是Latin-1字符集的字符),如果想直接还原出“中文”2个字比较困难。
不过在与Firefox中的日志对比之下,能看出只要直接将\x替换成%,然后用PHP的urldecode反解析就能得到对应的字符串。

另外说明一点:
这个例子中看到的值%D6%D0%CE%C4,是按gbk字符集进行urlencode计算得到的对应值,如果urldecode反解析得到是乱码,则日志记录的应该是utf-8格式的urlencode值,用PHP的iconv函数处理一下。

Wednesday, April 16, 2008

IE中innerHTML的局限性

IE的相关文档表明,在IE中,innerHTML在以下封闭标签中为只读属性:
1. col
2. colgroup
3. frameset
4. html
5. style
6. table
7. tbody
8. thead
9. tfoot
10. title
11. tr
在这些标签中只能读取到innerHTML内容却无法设置,在其他浏览器却都是可以的。
另外在select标签对中用innerHTML写入option,在IE中是可以写入,但无法正常显示,写入的内容与innerHTML的内容已经不一样,不过将其innerHTML=''赋空值却是可以正确将select原来的options移除。
换一种写法,如:
document.getElementById('select_elem_id').appendChild(new Option(text, value));
这个在IE中也是不可行,在其他浏览器中一切正常。

在IE中,往select中写入options可以用select对象的options属性写入:
document.getElementById('select_elem_id').options[0] = new Option(text, value);
这种方法在其他浏览器里也是一样正确执行。

Tuesday, April 08, 2008

HTTP request and response headers examples using telnet

yu$ telnet www.google.com 80
Trying 64.233.189.99...
Connected to www.l.google.com.
Escape character is '^]'.
GET /intl/en_ALL/images/logo.gif HTTP/1.1
Host: www.google.com
User-Agent: Mozilla/5.0(Robots) Gecko/20061206 Firefox/1.5.0.9
Accept-Encoding: gzip,deflate

HTTP/1.1 200 OK
Content-Type: image/gif
Last-Modified: Wed, 07 Jun 2006 19:38:24 GMT
Expires: Sun, 17 Jan 2038 19:14:07 GMT
Server: gws
Content-Length: 8558
Age: 13
Date: Sun, 06 Apr 2008 06:51:56 GMT

GIF89an.....

yu$ telnet www.google.com 80
Trying 64.233.189.104...
Connected to www.l.google.com.
Escape character is '^]'.
GET /intl/en_ALL/images/logo.gif HTTP/1.1
Host: www.google.com
User-Agent: Mozilla/5.0(Robots) Gecko/20061206 Firefox/1.5.0.9
Accept-Encoding: gzip,deflate
If-Modified-Since: Wed, 07 Jun 2006 19:38:24 GMT

HTTP/1.1 304 Not Modified
Date: Sun, 06 Apr 2008 06:53:10 GMT
Server: GFE/1.3

yu$ telnet l.yimg.com 80
Trying 203.209.246.249...
Connected to geoycs-l.yahoo8.akadns.net.
Escape character is '^]'.
GET /a/i/ww/news/2008/04/04/crocodile-sm.jpg HTTP/1.1
Host: l.yimg.com
User-Agent: Mozilla/5.0(Robots) Gecko/20061206 Firefox/1.5.0.9
Accept-Encoding: gzip,deflate
Connection: keep-alive

HTTP/1.1 200 OK
Date: Sat, 05 Apr 2008 00:14:27 GMT
Cache-Control: max-age=315360000
Expires: Tue, 03 Apr 2018 00:14:27 GMT
Last-Modified: Fri, 04 Apr 2008 17:49:26 GMT
Accept-Ranges: bytes
Content-Length: 860
Content-Type: image/jpeg
Age: 133250
Connection: keep-alive
Server: YTS/1.16.0



Connection closed by foreign host.

In HTTP/1.1 the ETag and If-None-Match headers are another way to make conditional GET requests.

<IMG ALT="Red Star"
SRC="data:image/gif;base64,R0lGODlhDAAMALMLAPN8ffBiYvWW
lvrKy/FvcPewsO9VVfajo+w6O/zl5estLv/8/AAAAAAAAAAAAAAAACH5BAEA
AAsALAAAAAAMAAwAAAQzcElZyryTEHyTUgknHd9xGV+qKsYirKkwDYiKDBia
tt2H1KBLQRFIJAIKywRgmhwAIlEEADs=">

Apache2 mod_headers using to modify http response headers

将mod_headers.so复制到modules目录下,修改httpd.conf文件:

LoadModule headers_module modules/mod_headers.so
Header add P3P "CP=\"CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR\""
Header set TEST "%D %t"

其中Header可添加在Context: server config, virtual host, directory, .htaccess
Reference: http://httpd.apache.org/docs/1.3/mod/mod_headers.html
http://httpd.apache.org/docs/2.2/mod/mod_headers.html

恢复HTML文件默认icon图标

也不知道系统安装了什么软件之后,所有的HTML/HTM文件图标全变成未关联的应用程序图标,相当难看
Google后得到如下解决方法:
在CMD命令行里依次输入以下4个命令:
C:>ASSOC .HTM=""
C:>ASSOC .HTM="htmlfile"
C:>ASSOC .HTML=""
C:>ASSOC .HTML="htmlfile"

ReplaceHTML instead innerHTML


/* This is much faster than using (el.innerHTML = value) when there are many
existing descendants, because in some browsers, innerHTML spends much longer
removing existing elements than it does creating new ones. */
function replaceHtml(el, html) {
var oldEl = (typeof el === "string" ? document.getElementById(el) : el);
/*@cc_on // Pure innerHTML is slightly faster in IE
oldEl.innerHTML = html;
return oldEl;
@*/
var newEl = oldEl.cloneNode(false);
newEl.innerHTML = html;
oldEl.parentNode.replaceChild(newEl, oldEl);
/* Since we just removed the old element from the DOM, return a reference
to the new element, which can be used to restore variable references. */
return newEl;
};


Reference: When innerHTML isn’t Fast Enough

Monday, April 07, 2008

Ruby http-access2

require 'pp'
require 'http-access2'
client = HTTPAccess2::Client.new()
# head = client.head('http://www.google.com')
# p head.header['Server'][0]

# content = client.get_content('http://www.google.com')
# puts content

# response = client.get('http://www.google.com/')
# pp response.header.get
# puts response.header.request_uri
# puts response.header.response_status_code
# pp response.header
# puts response.dump
# puts response.contenttype
# puts response.version
# puts response.status
# puts response.reason
# puts response.body.content
# puts response.content
# pp response.methods.sort
# puts response.content

=begin

== WebAgent::CookieManager Class

Load, save, parse and send cookies.

=== Usage

## initialize
## load from IE7 cookie file
cm = WebAgent::CookieManager.new("C:\Documents and Settings\user\Local Settings\Temporary Internet Files")

## load cookie data
cm.load_cookies()

## parse cookie from string (maybe "Set-Cookie:" header)
cm.parse(str)

## send cookie data to url
f.write(cm.find(url))

## save cookie to cookiefile
cm.save_cookies()


=== Class Methods

-- CookieManager::new(file=nil)

create new CookieManager. If a file is provided,
use it as cookies' file.

=== Methods

-- CookieManager#save_cookies(force = nil)

save cookies' data into file. if argument is true,
save data although data is not modified.

-- CookieManager#parse(str, url)

parse string and store cookie (to parse HTTP response header).

-- CookieManager#find(url)

get cookies and make into string (to send as HTTP request header).

-- CookieManager#add(cookie)

add new cookie.

-- CookieManager#load_cookies()

load cookies' data from file.


== WebAgent::CookieUtils Module

-- CookieUtils::head_match?(str1, str2)
-- CookieUtils::tail_match?(str1, str2)
-- CookieUtils::domain_match(host, domain)
-- CookieUtils::total_dot_num(str)


== WebAgent::Cookie Class

=== Class Methods

-- Cookie::new()

create new cookie.

=== Methods

-- Cookie#match?(url)

match cookie by url. if match, return true. otherwise,
return false.

-- Cookie#name
-- Cookie#name=(name)
-- Cookie#value
-- Cookie#value=(value)
-- Cookie#domain
-- Cookie#domain=(domain)
-- Cookie#path
-- Cookie#path=(path)
-- Cookie#expires
-- Cookie#expires=(expires)
-- Cookie#url
-- Cookie#url=(url)

accessor methods for cookie's items.

-- Cookie#discard?
-- Cookie#discard=(discard)
-- Cookie#use?
-- Cookie#use=(use)
-- Cookie#secure?
-- Cookie#secure=(secure)
-- Cookie#domain_orig?
-- Cookie#domain_orig=(domain_orig)
-- Cookie#path_orig?
-- Cookie#path_orig=(path_orig)
-- Cookie#override?
-- Cookie#override=(override)
-- Cookie#flag
-- Cookie#set_flag(flag_num)

accessor methods for flags.

=end

ActiveRecord::Base transaction explain


#---
# Excerpted from "Agile Web Development with Rails, 2nd Ed.",
# published by The Pragmatic Bookshelf.
# Copyrights apply to this code. It may not be used to create training material,
# courses, books, articles, and the like. Contact us if you are in doubt.
# We make no guarantees that this code is fit for any purpose.
# Visit http://www.pragmaticprogrammer.com/titles/rails2 for more book information.
#---
# $: << File.dirname(__FILE__)

require "logger"
require "rubygems"
require "active_record"

ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Base.establish_connection(
:adapter => "mysql",
:host => "localhost",
:user => "root",
:password => "",
:database => "test"
)

# InnoDB table: users, accounts
ActiveRecord::Schema.define do

create_table :accounts, :force => true do |t|
t.column :number, :string
t.column :balance, :decimal, :precision => 10, :scale => 2, :default => 0
end

create_table :users, :force => true do |t|
t.column :name, :string
t.column :password, :string
end

end

class User < ActiveRecord::Base
end

class Account < ActiveRecord::Base
end

Account.transaction do
Account.create(:balance => 100, :number => "12345")
User.create(:name => 'test', :password => "123456")
raise 'error!!!'
# 如果transaction内部所有SQL都正确执行并且通过ActiveRecord::Base validates,在block中没有raise的话则正确写入数据库
# 如果有SQL错误或者validates没有通过,或者是transaction中有raise错误,则事务会ROLLBACK
# ROLLBACK 是基于事务表(如InnoDB表)的,非事务表(如MyISAM表)则需要在程序中手工回滚
end

Saturday, April 05, 2008

unix awk simple usages example


yu$ cat *.txt
php line 1
lin 2
line 3
php line 4

yu$ grep 'php' *.txt
php line 1
php line 4

yu$ cat *.txt|grep 'php'
php line 1
php line 4

yu$ awk -F " " '/php/' *.txt
php line 1
php line 4

yu$ awk -F " " '/php/{print NR": "$0}' *.txt
1: php line 1
4: php line 4

yu$ awk -F " " 'length($0)>7 {print NR": "$0}' *.txt
1: php line 1
4: php line 4

yu$ awk -F " " '/php|line 2/{print NR": "$0}' *.txt
1: php line 1
2: line 2
4: php line 4

在awk中,缺省的情况下总是将文本文件中的一行视为一个记录,而将一行中的某一部分作为记录中的一个字段。为了操作这些不同的字段,awk借用shell的方法,用$1,$2,$3...这样的方式来顺序地表示行(记录)中的不同字段。特殊地,awk用$0表示整个行(记录)。不同的字段之间是用称作分隔符的字符分隔开的。系统默认的分隔符是空格。awk允许在命令行中用-F re的形式来改变这个分隔符。

附录: awk的常规表达式元字符

\ 换码序列
^ 在字符串的开头开始匹配
$ 在字符串的结尾开始匹配
. 与任何单个字符串匹配
[ABC] 与[]内的任一字符匹配
[A-Ca-c] 与A-C及a-c范围内的字符匹配(按字母表顺序)
[^ABC] 与除[]内的所有字符以外的任一字符匹配
Desk|Chair 与Desk和Chair中的任一个匹配
[ABC][DEF] 关联。与A、B、C中的任一字符匹配,且其后要跟D、E、F中的任一个字符。
* 与A、B或C中任一个出现0次或多次的字符相匹配
+ 与A、B或C中任何一个出现1次或多次的字符相匹配
? 与一个空串或A、B或C在任何一个字符相匹配
(Blue|Black)berry 合并常规表达式,与Blueberry或Blackberry相匹配

awk的内置函数

V 函数 用途或返回值
------------------------------------------------
N gsub(reg,string,target) 每次常规表达式reg匹配时替换target中的string
N index(search,string) 返回string中search串的位置
A length(string) 求串string中的字符个数
N match(string,reg) 返回常规表达式reg匹配的string中的位置
N printf(format,variable) 格式化输出,按format提供的格式输出变量variable。
N split(string,store,delim) 根据分界符delim,分解string为store的数组元素
N sprintf(format,variable) 返回一个包含基于format的格式化数据,variables是要放到串中的数据
G strftime(format,timestamp) 返回一个基于format的日期或者时间串,timestmp是systime()函数返回的时间
N sub(reg,string,target) 第一次当常规表达式reg匹配,替换target串中的字符串
A substr(string,position,len) 返回一个以position开始len个字符的子串
P totower(string) 返回string中对应的小写字符
P toupper(string) 返回string中对应的大写字符
A atan(x,y) x的余切(弧度)
N cos(x) x的余弦(弧度)
A exp(x) e的x幂
A int(x) x的整数部分
A log(x) x的自然对数值
N rand() 0-1之间的随机数
N sin(x) x的正弦(弧度)
A sqrt(x) x的平方根
A srand(x) 初始化随机数发生器。如果忽略x,则使用system()
G system() 返回自1970年1月1日以来经过的时间(按秒计算)

Reference:
http://www.chinaunix.net/jh/7/16985.html

PHP 301 permanently redirect [php5.1 manual]


<?php

/**
* PHP下的301重定向
* HTTP Protocol defined status codes
* @param int $num
*/

function HTTPStatus($num) {

static $http = array (
100 => "HTTP/1.1 100 Continue",
101 => "HTTP/1.1 101 Switching Protocols",
200 => "HTTP/1.1 200 OK",
201 => "HTTP/1.1 201 Created",
202 => "HTTP/1.1 202 Accepted",
203 => "HTTP/1.1 203 Non-Authoritative Information",
204 => "HTTP/1.1 204 No Content",
205 => "HTTP/1.1 205 Reset Content",
206 => "HTTP/1.1 206 Partial Content",
300 => "HTTP/1.1 300 Multiple Choices",
301 => "HTTP/1.1 301 Moved Permanently",
302 => "HTTP/1.1 302 Found",
303 => "HTTP/1.1 303 See Other",
304 => "HTTP/1.1 304 Not Modified",
305 => "HTTP/1.1 305 Use Proxy",
307 => "HTTP/1.1 307 Temporary Redirect",
400 => "HTTP/1.1 400 Bad Request",
401 => "HTTP/1.1 401 Unauthorized",
402 => "HTTP/1.1 402 Payment Required",
403 => "HTTP/1.1 403 Forbidden",
404 => "HTTP/1.1 404 Not Found",
405 => "HTTP/1.1 405 Method Not Allowed",
406 => "HTTP/1.1 406 Not Acceptable",
407 => "HTTP/1.1 407 Proxy Authentication Required",
408 => "HTTP/1.1 408 Request Time-out",
409 => "HTTP/1.1 409 Conflict",
410 => "HTTP/1.1 410 Gone",
411 => "HTTP/1.1 411 Length Required",
412 => "HTTP/1.1 412 Precondition Failed",
413 => "HTTP/1.1 413 Request Entity Too Large",
414 => "HTTP/1.1 414 Request-URI Too Large",
415 => "HTTP/1.1 415 Unsupported Media Type",
416 => "HTTP/1.1 416 Requested range not satisfiable",
417 => "HTTP/1.1 417 Expectation Failed",
500 => "HTTP/1.1 500 Internal Server Error",
501 => "HTTP/1.1 501 Not Implemented",
502 => "HTTP/1.1 502 Bad Gateway",
503 => "HTTP/1.1 503 Service Unavailable",
504 => "HTTP/1.1 504 Gateway Time-out"
);

header($http[$num]);
}

HTTPStatus(301);
header( "Location: http://www.test.com" );

// apache2 access_log
// 127.0.0.1 - - [05/Apr/2008:21:45:56 +0800] "GET /redirect301.php HTTP/1.1" 301 -
// 127.0.0.1 - - [05/Apr/2008:21:45:58 +0800] "GET / HTTP/1.1" 200 859
?>

Thursday, April 03, 2008

Javascript unicode string using fromCharCode and charCodeAt

// &#20013; => 中
document.write("&#20013;");
document.write("中国".charCodeAt(0)); // utf-8: 20013, GBK: 28051
document.write("&#" + "中国".charCodeAt(0) + ";");
document.write(String.fromCharCode("&#20013;".replace(/[&#;]/g,"")));

Difference of \b and [\b] in javascript

\b Match a word boundary. That is, match the position between a \w character and a \W character or between a \w character and the beginning or end of a string. (Note, however, that [\b] matches backspace.)
\B Match a position that is not a word boundary.
[\b] A literal backspace (special case).
Note that the special character-class escapes can be used within square brackets. \s matches any whitespace character, and \d matches any digit, so /[\s\d]/ matches any one whitespace character or digit. Note that there is one special case. As you'll see later, the \b escape has a special meaning. When used within a character class, however, it represents the backspace character. Thus, to represent a backspace character literally in a regular expression, use the character class with one element: /[\b]/.

Reference: Javascript the Definitive Guide 5th.

Wednesday, April 02, 2008

load a track link when window.onunload

When close this window or leave this page will get request below, this trick may be cause bad user experience, and Opera will ignore it:
***.***.***.*** - - [02/Apr/2008:23:10:18 +0800] "GET /track.html?1207149018624 HTTP/1.1" 301 253


<script type="text/javascript">
window.onunload = function(){
var img = new Image(1,1), i = 0;
img.src = "http://www.test.com/track.html?" + (new Date()).getTime();
while(i < 1000000) i++ ; // for img src load
};
</script>


window.onbeforeunload will pop out a confirm dialog, so can't using onbeforeunload.

Tuesday, April 01, 2008

Rails Content type header setting

Added utf-8 as the default charset for all renders. You can change this default using:
ActionController::Base.default_charset=(encoding) [DHH]
...now:
config.action_controller.default_charset="utf-8"

Added proper getters and setters for content type and charset [DHH]. Example of what we used to do:
response.headers["Content-Type"] = "application/atom+xml; charset=utf-8"

...now:
response.content_type = Mime::ATOM
response.charset = "utf-8"