前期准备
配置软件与库
需要安装- nodejs 0.8 或以上版本 (之后编译 Postgres 模块需要高版本)
- npm
- 下载编译 Stekinscript (非必需)
$ git clone git://github.com/neuront/stekinscript.git
# add-apt-repository ppa:chris-lea/node.js
npm install liteview
npm install validator
Stekinscript 快速入门 (非必需)
请参见 https://github.com/neuront/stekinscript/wiki/Language-Specification.对 Stekinscript 没有兴趣的同学可以无视这一步, 在每节之后生成的 Javascript 代码会奉上, 对于 Stekinscript 代码, 可以认为它是更易阅读的 JS.
开工
上手
创建如下内容的 main.stkn 文件, 先启动一个简单的服务器http: require('http')
port: 8888
http.createServer((request, response):
response.writeHead(200, { 'Content-Type':: 'text/html' })
response.end('<html><body>Hello, World!')
).listen(port, '127.0.0.1')
console.log('Server running at local host port=' + port)
$ stekin -i require < main.stkn > main.js
(function () {
const s_http = require("http");
s_http.createServer(function (s_request, s_response) {
s_response.writeHead(200, {
"Content-Type": "text/html"
});
s_response.end("<html><body>Hello, World!");
}).listen(8888, "127.0.0.1");
console.log("Server running at local host port=8888");
})();
$ node main.js
Server running at local host port=8888
Makefile
在目录下加入如下内容的 Makefile, 以便更便捷地生成 JS 文件 (其中的四点....
表示一个制表符, Makefile 必须用这货来缩进!)all:main.js
%.js:%.stkn
....stekin -i require -i exports < $< > $@
clean:
....rm -f *.js
all
后面丢就好了.请求路由
现在的程序对任何请求都返回这串 "Hello, World!". 下面构建一个简单的请求路由机制, 根据请求路径派发请求.http: require('http')
url: require('url')
port: 8888
index: (request, response):
response.writeHead(200, { 'Content-Type':: 'text/html' })
response.end('<html><body>Hello, World!')
app: {
'/':: index,
}
http.createServer((request, response):
path: url.parse(request.url).pathname
console.log('Request to ' + path)
if app[path]
app[path](request, response)
else
response.writeHead(404, { 'Content-Type':: 'text/html' })
response.end('<html><body>Not found')
).listen(port, '127.0.0.1')
console.log('Server running at local host port=' + port)
以上代码生成的 JS 如下
(function () {
const s_http = require("http");
const s_url = require("url");
const s_index = function (s_request, s_response) {
s_response.writeHead(200, {
"Content-Type": "text/html"
});
s_response.end("<html><body>Hello, World!");
};
const s_app = {
"/": s_index
};
s_http.createServer(function (s_request, s_response) {
const s_path = s_url.parse(s_request.url).pathname;
console.log("Request to " + s_path);
if (s_app[s_path]) {
s_app[s_path](s_request, s_response);
} else {
s_response.writeHead(404, {
"Content-Type": "text/html"
});
s_response.end("<html><body>Not found");
}
}).listen(8888, "127.0.0.1");
console.log("Server running at local host port=8888");
})();
使用模板
这里采用的是 liteview 这种轻便的模板框架.新建 index.html 文件, 内容为
<html>
<head>
<title>Server Sample</title>
</head>
<body>
Hello, #{who}!
http: require('http')
url: require('url')
view: require('liteview').create()
port: 8888
index: (request, response):
response.writeHead(200, { 'Content-Type':: 'text/html' })
response.end(view.render('index.html', {who: 'World'}))
(function () {
const s_http = require("http");
const s_url = require("url");
const s_view = require("liteview");
const s_index = function (s_request, s_response) {
s_response.writeHead(200, {
"Content-Type": "text/html"
});
s_response.end(s_view.render("index.html", {"who": "World"}));
};
const s_app = {
"/": s_index
};
s_http.createServer(function (s_request, s_response) {
const s_path = s_url.parse(s_request.url).pathname;
console.log("Request to " + s_path);
if (s_app[s_path]) {
s_app[s_path](s_request, s_response);
} else {
s_response.writeHead(404, {
"Content-Type": "text/html"
});
s_response.end("<html><body>Not found");
}
}).listen(8888, "127.0.0.1");
console.log("Server running at local host port=8888");
})();
区分 GET 与 POST
根据 GET / POST 方式区分对待请求是必要的. 下面的修改会让打开方式不对的请求获得 405 错误码.index: {
get: (request, response):
response.writeHead(200, { 'Content-Type':: 'text/html' })
response.end(view.render('index.html', {who: 'World'}))
}
app: {
'/':: index,
}
http.createServer((request, response):
path: url.parse(request.url).pathname
method: request.method.toLowerCase()
console.log('Request to ' + path + ' method=' + method)
if app[path]
if app[path][method]
app[path][method](request, response)
else
response.writeHead(405, { 'Content-Type':: 'text/html' })
response.end('<html><body>Method not allowed')
else
response.writeHead(404, { 'Content-Type':: 'text/html' })
response.end('<html><body>Not found')
).listen(port, '127.0.0.1')
$ curl -d '' localhost:8888
<html><body>Method not allowed
如果继续这么一个文件写下去会变得过于复杂, 下面就把这些功能拆分为两个不同的文件.
下面是 main.stkn, 其中通过
require('./index')
导入同一路径下的 index.js 文件.http: require('http')
url: require('url')
port: 8888
app: {
'/':: require('./index'),
}
http.createServer((request, response):
path: url.parse(request.url).pathname
method: request.method.toLowerCase()
console.log('Request to ' + path + ' method=' + method)
if app[path]
if app[path][method]
app[path][method](request, response)
else
response.writeHead(405, { 'Content-Type':: 'text/html' })
response.end('<html><body>Method not allowed')
else
response.writeHead(404, { 'Content-Type':: 'text/html' })
response.end('<html><body>Not found')
).listen(port, '127.0.0.1')
console.log('Server running at local host port=' + port)
exports
导出 get
函数, 以响应 GET 方式请求.view: require('liteview').create()
exports.get: (request, response):
response.writeHead(200, { 'Content-Type':: 'text/html' })
response.end(view.render('index.html', {who: 'World'}))
all:main.js index.js
附生成的 Javascript 等价代码: main.js
(function () {
const s_http = require("http");
const s_url = require("url");
const s_app = {
"/": require("./index")
};
s_http.createServer(function (s_request, s_response) {
const s_path = s_url.parse(s_request.url).pathname;
const s_method = s_request.method.toLowerCase();
console.log("Request to " + s_path + " method=" + s_method);
if (s_app[s_path]) {
if (s_app[s_path][s_method]) {
s_app[s_path][s_method](s_request, s_response);
} else {
s_response.writeHead(405, {
"Content-Type": "text/html"
});
s_response.end("<html><body>Method not allowed");
}
} else {
s_response.writeHead(404, {
"Content-Type": "text/html"
});
s_response.end("<html><body>Not found");
}
}).listen(8888, "127.0.0.1");
console.log("Server running at local host port=8888");
}
})();
(function () {
const s_view = require("liteview");
exports.get = function (s_request, s_response) {
s_response.writeHead(200, {
"Content-Type": "text/html"
});
s_response.end(s_view.render("index.html", {
"who": "World"
}));
};
})();