# minimal http
## b/s和c/s架構
* b/s= browser/server
* c/s= client/server
目前我們最常見的開發都是b/s架構的,也就是都是基于瀏覽器和服務器交互的、采用http協議的瘦應用
nodejs做為新興平臺,自然在這方面也提供了較好支持。nodejs的http部分相對比較完善,足矣滿足絕大多數應用使用,而且又有nodejs本身的事件異步機制,它天生并發就比較高,和其他語言比較
* js語法簡單
* 開發速度快
* 在不優化的情況下就會比java、php等其他語言高效
* 部署和運維也相對簡單
綜上,已經有非常多公司采用nodejs作為它們的后端技術棧。
## 科普:無狀態的http協議
HTTP協議(HyperText Transfer Protocol,超文本傳輸協議)是用于從WWW服務器傳輸超文本到本地瀏覽器的傳送協議。
它可以使瀏覽器更加高效,使網絡傳輸減少。
它不僅保證計算機正確快速地傳輸超文本文檔,還確定傳輸文檔中的哪一部分,以及哪部分內容首先顯示(如文本先于圖形)等。
HTTP是一個應用層協議,由請求和響應構成,是一個標準的客戶端服務器模型。
HTTP是一個無狀態的協議。
## 科普request和response
大家都明白,Web應用抽象起來就是客戶端發出請求,請求到達服務器后,服務器經過一番搗鼓,給客戶端發回一個應答。“請求”我們一般抽象成 request,“應答”是 response。服務器和客戶端(一般也就是瀏覽器啦,但是絕不局限于瀏覽器哦。)之間交流的語言就是 HTTP 協議了。至于服務器怎么折騰出一個應答來的,就八仙過海,各顯神通了。
總之,Web 應用中兩個重量級的東東就是: Request , Response 。
前面我們說到,每次有訪問進來,我們的代碼都會跑一遍。
現在的問題是,在我們的代碼里,怎么抓到客戶端發來的 request , 然后,到哪里去找這個 response ,好把我們搗鼓出來的東西放進去,發給客戶端呢?
答案是,只要我們把他們作為參數交給 tellme 函數(你可以給這個函數取任何名字甚至不給他名字),然后,當請求到達時,node.js 就會把客戶的請求封裝成 request ,預備發給客戶的應答封裝成 response 。
我們拿到 request ,看看他請求些什么,再折騰些東西(讀出個文件也好,去查數據庫也好,隨便你了。)丟進 response ,發給客戶端。

更多見[http://i5ting.github.io/node-http/](http://i5ting.github.io/node-http/)
## Write a http server use Nodejs
~~~
var http = require('http');
http.createServer(function(request,response){
console.log(request);
response.end('Hello world!');
}).listen(8888);
~~~
這就是最簡單的實現
如果要是根據不同url去處理呢?
~~~
var http = require('http');
http.createServer(function(req, res){
console.log(req);
if(req.url =='/'){
res.end('Hello world!');
}else if(req.url =='/2'){
res.end('Hello world!2');
}else{
res.end('Hello world! other');
}
}).listen(8888);
~~~
如果成百上千、甚至更多http服務呢?這樣寫起來是不是太low了,肯定要封裝一下,讓它更簡單。
connect就是這樣的一個框架,下面我們看一下
## 如何調試
node-inspector
* 本地可以
* Coding WebIDE不可以
第一步
~~~
npm i -g node-inspector
~~~
第二步
~~~
node-debug hello.js
~~~
第三步
打開[http://127.0.0.1:8080/?ws=127.0.0.1:8080&port=5858](http://127.0.0.1:8080/?ws=127.0.0.1:8080&port=5858)
## Write a http server use Node connect
Connect is an extensible HTTP server framework for node using "plugins" known as middleware.
* extensible是可擴展的
* HTTP server framework是http服務端框架
* using "plugins" known as middleware即使用插件機制,就是大家常說的中間件
### 先看一下helloworld
~~~
var connect = require('connect')
var http = require('http')
var app = connect()
// respond to all requests
app.use(function(req, res){
res.end('Hello from Connect!\n');
})
//create node.js http server and listen on port
http.createServer(app).listen(3011)
~~~
[http://127.0.0.1:3011/](http://127.0.0.1:3011/)
回想一下上一節中的http的例子
~~~
http.createServer(function(request,response){
...
}).listen(8888);
~~~
與
~~~
var app = connect()
// respond to all requests
app.use(function(req, res, next){
...
})
//create node.js http server and listen on port
http.createServer(app).listen(3011)
~~~
說明
* 都是http.createServer
* 差異是createServer的參數獨立出去了,并且在connect里通過app.use方法可以掛在多個插件式的中間件
編程上有區分可變和不可變狀態,可變的抽取出去,不可變的就固化好即可。connect做的就是提供了可變部分的插件化。
### 多url處理
好,我們再看一下它如何出個多個url情況
* /
* /2
connect2.js
~~~
var connect = require('connect')
var http = require('http')
var app = connect()
app.use('/2', function fooMiddleware(req, res, next) {
// req.url starts with "/foo"
res.end('Hello from Connect2!\n');
});
// respond to all requests
app.use(function(req, res){
res.end('Hello from Connect!\n');
})
//create node.js http server and listen on port
http.createServer(app).listen(3011)
~~~
訪問[http://127.0.0.1:3011/2](http://127.0.0.1:3011/2)?看看能否訪問?
上面講了,connect實際上是將開發中得可變部分抽象出來,通過app.use方法都掛載到app對象上,這樣處理起來就非常簡單、清晰了。
### 中間件順序
下面我們看一下中間件順序
connect2.js
~~~
var connect = require('connect')
var http = require('http')
var app = connect()
// respond to all requests
app.use(function(req, res){
res.end('Hello from Connect!\n');
})
app.use('/2', function fooMiddleware(req, res, next) {
// req.url starts with "/foo"
res.end('Hello from Connect2!\n');
});
//create node.js http server and listen on port
http.createServer(app).listen(3011)
~~~
訪問[http://127.0.0.1:3011/2](http://127.0.0.1:3011/2)?看看能否訪問?
答案是不能的,原因是第一個use里沒有指定path,這時候它就響應了所有請求,根本不給第二use的機會,所以正確的寫法是
~~~
app.use('/', function fooMiddleware(req, res, next) {
// req.url starts with "/foo"
res.end('Hello from Connect2!\n');
});
app.use('/2', function fooMiddleware(req, res, next) {
// req.url starts with "/foo"
res.end('Hello from Connect2!\n');
});
// respond to other requests
app.use(function(req, res){
res.end('Hello from Connect!\n');
})
~~~
這其實和我們第一個http里寫的if判斷一樣
~~~
if(req.url =='/'){
res.end('Hello world!');
}else if(req.url =='/2'){
res.end('Hello world!2');
}else{
res.end('Hello world! other');
}
~~~
這樣的寫法是不是很討厭?順序都要思考,弄死人了,這其實就是很多人埋怨nodejs坑多的原因之一,是真的有問題,還是自己沒有弄明白呢?
總結一下,我們能得出什么結論呢?
* use的中間件有順序
* 中間件分類:全局和路由里的
* 中間件定義
## Express
### helloworld
~~~
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World')
})
// 隨機端口3000 - 10000 之間
app.listen(4001)
~~~
### 多url處理
~~~
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World')
})
app.get('/2', function (req, res) {
res.send('Hello World2')
})
// 隨機端口3000 - 10000 之間
app.listen(4001)
~~~
## 總結一下
* connect的helloworld
* connect多url處理方式
* connect中間件順序
* 最后講了一下中間件
- 前言
- 1 skill
- 1.1 Coding WebIDE
- 1.2 git
- 1.3 extra practice
- 1.4 預習
- 2 nodejs入門
- 2.1 入門
- 2.2 安裝
- 2.3 helloworld
- 2.4 commonJS規范
- 2.5 模塊導出
- 2.6 Nodejs代碼調試
- 2.7 編寫Nodejs模塊
- 2.8 最小化問題
- 2.9 隨堂練習
- 3 異步流程控制
- 3.1 什么時候會用到異步流程控制
- 3.2 簡單做法async模塊
- 3.3 Promise/a+規范
- 3.4 Node.js Promise/a+實現
- 3.5 生成器Generators/yield
- 3.6 Async函數/Await
- 3.7 神奇的co
- 3.8 5種 yieldable
- 3.9 學習重點
- 3.10 隨堂練習
- 4 express和微信開發入門
- 4.1 入門
- 4.2 connect
- 4.3 靜態Http服務器
- 4.4 那些預處理器
- 4.5 路由
- 4.6 視圖與模塊引擎
- 4.7 中間件
- 4.8 更多實踐
- 4.9 微信入門
- 4.10 隨堂練習:完成登錄、注冊功能
- 5 微信實例與H5實踐
- 5.1 微信基礎和sandbox
- 5.2 公眾號菜單和自動回復
- 5.3 微信OAuth用戶授權
- 5.4 微信分享
- 5.5 wechat-api
- 5.6 H5-上篇
- 5.7 H5-下篇
- 5.8 隨堂練習
- 6 weui實戰
- 6.1 使用bower
- 6.2 移動端抽象
- 6.3 優化滑動列表
- 6.4 weui
- 6.5 讓weui和iscroll結婚
- 6.6 優化事件
- 6.7 how-to-write-h5
- 6.8 優化無止境
- 6.9 隨堂練習
- 7 微信支付
- 7.1 吹個牛
- 7.2 支付概述
- 7.3 科普幾個概念
- 7.4 準備
- 7.5 調試
- 7.6 公眾號支付(JSAPI)
- 7.7 對賬單
- 7.8 數據處理
- 7.9 隨堂練習
- 8 項目實戰《付費課程系統MVP》
- 8.1 需求分析
- 8.2 ui/ue
- 8.3 技術棧
- 8.4 模型
- 8.5 靜態api
- 8.6 開發
- 8.7 部署
- 8.8 監控
- 8.9 數據統計
- 8.10 demo
- 9 高級篇
- 9.1 前后端分離實踐?
- 9.2 如何展望未來的大前端
- 9.3 容器和微服務
- 10 答疑問題收集