Ã¥ÂÂè¨Â
å¾Âå¤Âä¸Â西ï¼Âè¿Âä¹ äºÂå°±ä¼Âå¿Âè®°ï¼ÂæÂÂ们åªæÂÂä¸ÂæÂÂçÂÂå»å¤Âä¹ ãÂÂå·©åºï¼ÂæÂÂè½åÂʾᱏª己çÂÂè®°å¿ÂÃ¥ÂÂçÂÂ解ï¼ÂÃ¥ÂÂæÂÂä¸ÂÃ¥ÂȋÂÂðªð»ðªð»ðªð»
æÂÂå 容å¦Âä¸Â
- URI & URL
- HTTP0.9 / HTTP 1.1 / HTTP2 è¿Âä¸Âè æÂÂä»Âä¹Âåºå«ï¼Âå ±åÂÂç¹åÂÂæ¯ä»Âä¹Âï¼Â
- ä¸Â次æ¡æÂÂ
- Ã¥ÂÂè¿ÂæÂ¥éÂÂÃ¥ÂÂ
- Ã¥ÂÂ次æÂ¥æÂÂ
- 请æ±ÂæÂ¥æÂÂ
- Ã¥ÂÂåºÂæÂ¥æÂÂ
- è·¨åÂÂ
- é¢Â请æ±Âï¼Âoptionsï¼Â
- Cache-control
- Disk cache & Memory cache
- ç¼ÂÃ¥ÂÂéªÂè¯Âï¼Â强ç¼ÂÃ¥ÂÂ/Ã¥ÂÂÃ¥ÂÂç¼ÂÃ¥ÂÂï¼Â
- Etag & Last-Modified
- Cookie
- Seesion
- HTTP é¿è¿ÂæÂÂ¥
- Chrome æµÂè§Âå¨å Â许并åÂÂå¤Âå°Â个 TCP è¿ÂæÂ¥ï¼Â
- æ°æ®åÂÂÃ¥ÂÂ
- éÂÂå®ÂÃ¥ÂÂ
- HTTP CSP
URI & URL
URIï¼ÂUniform Resource Identifierï¼ÂÃ¥ÂÂURLï¼ÂUniform Resource Locatorï¼Âæ¯äºÂèÂÂç½Âä¸Âæ Âè¯ÂÃ¥ÂÂå®Âä½ÂèµÂæºÂçÂÂ两个æ¦Â念ï¼Âå®Â们å¨æÂÂäºÂæ¹é¢æÂÂåºå«ï¼Âä½ÂéÂÂ常人们使ç¨å®Â们æ¥表示ç¸åÂÂçÂÂå 容ãÂÂ
URIæ¯ä¸Â个æ´éÂÂç¨çÂÂæ¦Â念ï¼Âç¨äºÂæ Âè¯Âä»»ä½ÂèµÂæºÂçÂÂå¯ä¸Âæ Âè¯Â符ãÂÂå®Âå¯以ç¨æÂ¥æ Âè¯Âä¸Âä» ä» æ¯ç½Âç»ÂèµÂæºÂï¼Âè¿Âå æ¾Œ°æÂÂ件ãÂÂæ°æ®åºÂæ¡ç®çÂÂãÂÂURIç±两é¨åÂÂç»ÂæÂÂï¼Âæ Âè¯Â符åÂÂå®Âä½Âå¨ãÂÂ
URLæ¯URIçÂÂä¸Âç§Â常è§Âå½¢å¼Âï¼Âå®ÂæÂÂä¾ÂäºÂå®Âä½ÂÃ¥ÂÂ访é®ç½Âç»ÂèµÂæºÂçÂÂæ¹å¼ÂãÂÂURLæÂÂè¿°äºÂä¸Â个èµÂæºÂå¨ç½Âç»Âä¸ÂçÂÂå ·ä½Âä½Âç½®åÂÂ访é®æ¹å¼ÂãÂÂå®Âå å«äºÂÃ¥ÂÂè®®ï¼Âå¦ÂHTTPãÂÂHTTPSãÂÂFTPçÂÂï¼ÂãÂÂ主æºåÂÂãÂÂè·¯å¾ÂãÂÂæ¥询åÂÂæ°çÂÂä¿¡æ¯ï¼Âç¨äºÂå®Âä½ÂÃ¥ÂÂ访é®ç¹å®ÂçÂÂç½Âç»ÂèµÂæºÂãÂÂ
ä¸Âé¢æ¯ä¸Â个示ä¾Âï¼Â
URI:ÃÂ urn:isbn:9780345534491
àè¿Âæ¯ä¸Â个URIï¼Âç¨äºÂæ Âè¯Âä¸Âæ¬书çÂÂISBNå·ãÂÂå®Â以”urn”ä½Â为æ Âè¯Â符ï¼ÂÃ¥ÂÂé¢æ¯åÂ
·ä½ÂçÂÂæ Âè¯Âä¿¡æ¯ãÂÂ
URL:ÃÂ https://www.example.com/images/pic.jpg
àè¿Âæ¯ä¸Â个URLï¼Âç¨äºÂ访é®ä½ÂäºÂwww.example.com
æÂÂå¡å¨ä¸ÂçÂÂpic.jpg
å¾çÂÂæÂÂ件ãÂÂå®ÂÃ¥ÂÂ
å«äºÂÃ¥ÂÂè®®ï¼Âhttpsï¼ÂãÂÂ主æºåÂÂï¼Âwww.example.comï¼ÂÃ¥ÂÂè·¯å¾Âï¼Â/images/pic.â¦
æ»ç»Âæ¥说ï¼ÂURIæ¯ä¸Âç§ÂéÂÂç¨çÂÂèµÂæºÂæ Âè¯Â符ï¼ÂèÂÂURLæ¯ä¸Âç§Âå ·ä½ÂçÂÂç½Âç»ÂèµÂæºÂå®Âä½Âå¨ãÂÂURLæ¯URIçÂÂä¸Âç§Âç¹æ®Âå½¢å¼Âï¼Âç¨äºÂå®Âä½ÂÃ¥ÂÂ访é®ç½Âç»ÂèµÂæºÂãÂÂ
HTTP0.9 / HTTP 1.1 / HTTP2 è¿Âä¸Âè æÂÂä»Âä¹Âåºå«ï¼Âå ±åÂÂç¹åÂÂæ¯ä»Âä¹Âï¼Â
HTTP 0.9ãÂÂHTTP 1.1Ã¥ÂÂHTTP/2ï¼Âä¹Â称为HTTP2ï¼Âæ¯HTTPÃ¥ÂÂè®®çÂÂä¸ÂÃ¥ÂÂçÂÂæ¬ï¼Âå®Â们å¨åÂÂè½åÂÂæ§è½æ¹é¢æÂÂä¸ÂäºÂåºå«ï¼ÂÃ¥ÂÂæ¶ä¹ÂæÂÂä¸ÂäºÂå ±åÂÂç¹ãÂÂ
HTTP 0.9æ¯æÂÂæ©çÂÂHTTPçÂÂæ¬ï¼ÂäºÂ1991å¹´åÂÂå¸ÂãÂÂå®Âæ¯ä¸Âç§ÂéÂÂ常ç®ÂÃ¥ÂÂçÂÂÃ¥ÂÂè®®ï¼Âåªæ¯æÂÂGETæ¹æ³Âï¼Â没æÂÂ请æ±Â头åÂÂÃ¥ÂÂåºÂ头ï¼Âä¹Âä¸Âæ¯æÂÂæÂÂä¹Â
è¿ÂæÂ¥çÂÂé«Â级åÂÂè½
ãÂÂå®Â主è¦Âç¨äºÂéÂÂè¿ÂURLè·åÂÂHTMLæÂÂæ¡£ãÂÂ
HTTP 1.1æ¯1997å¹´åÂÂå¸ÂçÂÂHTTPÃ¥ÂÂè®®çÂÂ主è¦ÂçÂÂæ¬ï¼Âå®Âå¼ÂÃ¥Â
¥äºÂ许å¤Âæ°ç¹æ§åÂÂæ¹è¿ÂãÂÂHTTP 1.1æ¯æÂÂå¤Âç§Â请æ±Âæ¹æ³Âï¼ÂGETãÂÂPOSTãÂÂPUTãÂÂDELETEçÂÂï¼Âï¼Âå¼ÂÃ¥Â
¥äºÂ请æ±Â头åÂÂÃ¥ÂÂåºÂ头ï¼Âæ¯æÂÂæÂÂä¹Â
è¿ÂæÂÂ¥
ãÂÂ管线åÂÂ
ãÂÂç¼ÂÃ¥ÂÂæ§å¶ãÂÂèÂÂæÂÂ主æºçÂÂÃ¥ÂÂè½ãÂÂHTTP 1.1éÂÂè¿Âå¤Âç¨è¿ÂæÂ¥ãÂÂ请æ±Â头åÂÂ缩çÂÂä¼ÂÃ¥ÂÂï¼ÂæÂÂé«ÂäºÂæ§è½åÂÂæÂÂçÂÂãÂÂ
HTTP/2æ¯HTTPÃ¥ÂÂè®®çÂÂæÂÂæ°çÂÂæ¬ï¼ÂäºÂ2015å¹´åÂÂå¸ÂãÂÂå®Âæ¯å¨HTTP 1.1çÂÂåºç¡Âä¸Âè¿Âè¡ÂçÂÂéÂÂ大æ¹è¿ÂãÂÂHTTP/2æÂÂæÂÂæ°æ®éÂÂç¨äºÂè¿Âå¶åÂÂè®®
èÂÂéÂÂæÂÂæÂŒÂÂè®®ï¼ÂéÂÂè¿ÂäºÂè¿Âå¶帧
è¿Âè¡Âæ°æ®传è¾Âï¼Âå¼ÂÃ¥Â
¥äºÂå¤Âè·¯å¤Âç¨ï¼ÂMultiplexingï¼Âæºå¶ï¼ÂÃ¥Â
Â许å¨åÂÂ个è¿ÂæÂ¥ä¸Â**Ã¥ÂÂæ¶**Ã¥ÂÂéÂÂå¤Â个请æ±ÂÃ¥ÂÂÃ¥ÂÂåºÂï¼ÂÃ¥ÂÂå°ÂäºÂè¿Âæ¥建ç«ÂÃ¥ÂÂÃ¥Â
³éÂÂçÂÂå¼ÂéÂÂ
ãÂÂæ¤å¤Âï¼ÂHTTP/2è¿Âæ¯æÂÂ头é¨åÂÂ缩ãÂÂæÂÂå¡å¨æ¨éÂÂãÂÂä¼ÂÃ¥Â
Â级çÂÂÃ¥ÂÂè½ï¼Âè¿Âä¸ÂæÂ¥æÂÂé«ÂäºÂæ§è½åÂÂæÂÂçÂÂãÂÂ
åºå«ï¼Â
- Ã¥ÂÂè½æ¯æÂÂï¼ÂHTTP 0.9ä» æ¯æÂÂGETæ¹æ³Âï¼ÂèÂÂHTTP 1.1Ã¥ÂÂHTTP/2æ¯æÂÂæ´å¤ÂçÂÂ请æ±Âæ¹æ³ÂÃ¥ÂÂÃ¥ÂÂè½ãÂÂ
- Ã¥ÂÂ议形å¼Âï¼ÂHTTP 0.9ãÂÂHTTP 1.1æ¯纯æÂÂæÂŒÂÂè®®ï¼ÂHTTP/2éÂÂç¨äºÂäºÂè¿Âå¶åÂÂè®®ãÂÂ
- è¿ÂæÂ¥å¤Âç¨ï¼ÂHTTP 0.9æ¯Â次请æ±Âé½éÂÂè¦Â建ç«Âæ°çÂÂè¿ÂæÂ¥ï¼ÂHTTP 1.1å¼Âå ¥äºÂæÂÂä¹ è¿ÂæÂ¥ï¼Âå Â许å¤Âç¨è¿ÂæÂ¥ï¼ÂèÂÂHTTP/2éÂÂè¿Âå¤Âè·¯å¤Âç¨å¨åÂÂ个è¿ÂæÂ¥ä¸ÂÃ¥ÂÂæ¶å¤ÂçÂÂå¤Â个请æ±ÂÃ¥ÂÂÃ¥ÂÂåºÂãÂÂ
- æ§è½ä¼ÂÃ¥ÂÂï¼ÂHTTP 1.1éÂÂè¿Â管线åÂÂÃ¥ÂÂ请æ±Â头åÂÂ缩çÂÂæ¹å¼ÂæÂÂé«Âæ§è½ï¼ÂèÂÂHTTP/2å¨æ¤åºç¡Âä¸Âå¼Âå ¥äºÂæ´é«Â级çÂÂä¼ÂÃ¥ÂÂæºå¶ï¼Âå¦ÂäºÂè¿Âå¶åÂÂ帧ãÂÂ头é¨åÂÂ缩çÂÂãÂÂ
å ±åÂÂç¹ï¼Â
- Ã¥ÂÂ为åºÂç¨å±ÂÃ¥ÂÂè®®ï¼Âç¨äºÂå¨客æ·端åÂÂæÂÂå¡å¨ä¹Âé´传è¾Âæ°æ®ãÂÂ
- Ã¥ÂÂåºäºÂ请æ±Â-Ã¥ÂÂåºÂ模åÂÂï¼Â客æ·端åÂÂéÂÂ请æ±Âï¼ÂæÂÂå¡å¨è¿ÂÃ¥ÂÂÃ¥ÂÂåºÂãÂÂ
- Ã¥ÂÂ使ç¨URLä½Â为èµÂæºÂå®Âä½Âæ Âè¯Â符ãÂÂ
- Ã¥ÂÂ使ç¨HTTPç¶æÂÂç Âæ¥表示请æ±ÂÃ¥ÂÂÃ¥ÂÂåºÂçÂÂç»ÂæÂÂãÂÂ
æ»ä½ÂèÂÂè¨Âï¼ÂHTTP 1.1Ã¥ÂÂHTTP/2æ¯HTTPÃ¥ÂÂè®®çÂÂéÂÂè¦Âæ¼ÂÃ¥ÂÂçÂÂæ¬ï¼ÂæÂÂä¾ÂäºÂæ´å¤ÂçÂÂÃ¥ÂÂè½åÂÂæ§è½ä¼ÂÃ¥ÂÂï¼Â以éÂÂåºÂäºÂèÂÂç½ÂÃ¥ÂÂå±ÂçÂÂéÂÂæ±ÂãÂÂ
ä¸Â次æ¡æÂÂ
ä¸Â次æ¡æÂÂæ¯建章TCP è¿ÂæÂ¥æ¶使ç¨çÂÂä¸Âç§ÂÃ¥ÂÂè®®ï¼Âç¨äºÂç¡®ä¿ÂÃ¥ÂÂæ¹çÂÂéÂÂä¿¡è½å¤Âæ£常è¿Âè¡ÂãÂÂä¸Âé¢æ¯ä¸Â次æ¡æÂÂçÂÂ详ç»Âæ¥骤ï¼Â
Ã¥ÂÂå¼Âå§Âæ¶ï¼Â客æ·端çÂÂç¶æÂÂæ¯åÂ
³éÂÂçÂÂï¼ÂCLOSEDï¼Â
ï¼ÂæÂÂå¡å¨ç¶æÂÂå¤ÂäºÂçÂÂå¬ä¸Âï¼ÂLISTENï¼Â
-
第ä¸Â次æ¡æÂÂï¼ÂSYNï¼Âï¼Â
- 客æ·端ï¼ÂæµÂè§Âå¨ï¼ÂÃ¥ÂÂæÂÂå¡å¨åÂÂéÂÂä¸Â个ÃÂ
SYNï¼ÂÃ¥ÂÂæÂ¥ï¼Âæ Âå¿Â
ç TCP æ°æ®å ï¼Â该æ°æ®å çÂÂåºÂÃ¥ÂÂå·表示客æ·端è¦ÂÃ¥ÂÂéÂÂæ°æ®çÂÂÃ¥ÂÂå§ÂåºÂÃ¥ÂÂå·ï¼ÂSeq=xï¼Â
ã - 客æ·端è¿ÂÃ¥Â
Â¥ÃÂ
SYN_SENT
àç¶æÂÂï¼ÂçÂÂå¾ æÂÂå¡å¨çÂÂÃ¥ÂÂåºÂãÂÂ
- 客æ·端ï¼ÂæµÂè§Âå¨ï¼ÂÃ¥ÂÂæÂÂå¡å¨åÂÂéÂÂä¸Â个ÃÂ
-
第äºÂ次æ¡æÂÂï¼ÂSYN-ACKï¼Âï¼Â
- æÂÂå¡å¨æ¶å°客æ·端åÂÂéÂÂç SYN æ°æ®å åÂÂï¼Âä¼Â确认æ¶å°ï¼Â并åÂÂéÂÂä¸Â个带æ SYN å ACKï¼Â确认åºÂÃ¥ÂÂå·ï¼Âæ Âå¿Âç TCP æ°æ®å ä½Â为åÂÂåºÂãÂÂï¼ÂACKï¼Â
- 该æ°æ®åÂÂ
ä¸ÂÃ¥ÂÂ
å«æÂÂå¡å¨èª己åÂÂéÂ
ÂçÂÂ
Ã¥ÂÂå§ÂåºÂÃ¥ÂÂå·ï¼ÂSeq=yï¼Â
Ã¥ÂÂ确认å·ï¼ÂACK= x + 1ï¼Â
ï¼Â确认å·为客æ·端çÂÂÃ¥ÂÂå§ÂåºÂÃ¥ÂÂå·(Seq=x)
å 1ã - æÂÂå¡å¨è¿ÂÃ¥Â
Â¥ÃÂ
SYN_RCIVED
àç¶æÂÂãÂÂ
-
第ä¸Â次æ¡æÂÂï¼ÂACKï¼Âï¼Â
- 客æ·端æ¶å°æÂÂå¡å¨åÂÂéÂÂçÂÂÃÂ
SYN / ACK
àæ°æ®å åÂÂï¼Âä¼Â确认æ¶å°ï¼Â并åÂÂéÂÂä¸Â个带æÂÂÃÂACK= y + 1
àæ Âå¿Âç TCP æ°æ®å ç»ÂæÂÂå¡å¨ã - 该æ°æ®åÂÂ
ä¸ÂçÂÂ确认å·为
æÂÂå¡å¨çÂÂÃ¥ÂÂå§ÂåºÂÃ¥ÂÂå·(Seq=y)
å 1ã - æÂÂå¡å¨æ¶å°客æ·端åÂÂéÂÂç ACK æ°æ®å åÂÂï¼Â确认å·ä¹Âå 1ãÂÂ
- 客æ·端åÂÂæÂÂå¡å¨é½è¿ÂÃ¥Â
Â¥ÃÂ
ESTABLISHED
àç¶æÂÂï¼ÂTCP è¿Âæ¥建ç«ÂæÂÂÃ¥ÂÂãÂÂ
- 客æ·端æ¶å°æÂÂå¡å¨åÂÂéÂÂçÂÂÃÂ
éÂÂè¿Âä¸Â次æ¡æÂÂï¼Â客æ·端åÂÂæÂÂå¡å¨é½è½å¤Â确认彼æ¤çÂÂæ¶åÂÂè½åÂÂæ£常ï¼Âå¯以å¼Âå§Âè¿Âè¡Âæ°æ®çÂÂä¼ è¾ÂãÂÂå¨æ¡æÂÂè¿Âç¨Âä¸Âï¼ÂÃ¥ÂÂå§ÂåºÂÃ¥ÂÂå·ï¼ÂISNï¼Âæ¯为äºÂä¿Âè¯Âæ¯Â个è¿ÂæÂ¥é½æÂÂå¯ä¸ÂçÂÂåºÂÃ¥ÂÂÃ¥ÂᏵጤÂå¼ï¼Â以å¢Â强è¿ÂæÂ¥çÂÂå®Âå ¨æ§ãÂÂ
éÂÂè¦Â注æÂÂçÂÂæ¯ï¼Âä¸Â次æ¡æÂÂåªæ¯建章TCP è¿ÂæÂ¥çÂÂè¿Âç¨Âï¼Â并ä¸Â代表æ°æ®çÂÂä¼ è¾ÂãÂÂæ°æ®çÂÂä¼ è¾Âæ¯å¨è¿Âæ¥建ç«Âå®ÂæÂÂÃ¥ÂÂè¿Âè¡ÂçÂÂï¼ÂÃ¥ÂÂæ¹å¯以éÂÂè¿Â已建ç«ÂçÂÂè¿ÂæÂ¥è¿Âè¡Âæ°æ®çÂÂÃ¥ÂÂéÂÂÃ¥ÂÂæÂ¥æ¶ãÂÂ
å¨堳é TCP è¿ÂæÂ¥æ¶ï¼Âä¹ÂéÂÂè¦Âè¿Âè¡Â类似çÂÂÃ¥ÂÂ次æÂ¥æÂÂï¼ÂÃ¥ÂÂ次æ¡æÂÂï¼Âè¿Âç¨Âï¼Â以ä¿Âè¯ÂÃ¥ÂÂæ¹é½å®ÂæÂÂäºÂæ°æ®传è¾Â并æ¿æÂÂå ³éÂÂè¿ÂæÂ¥ãÂÂ
Ã¥ÂÂè¿ÂæÂ¥éÂÂÃ¥ÂÂ
æÂÂå¡å¨第ä¸Â次æ¶å°客æ·端ç SYN ä¹ÂÃ¥ÂÂï¼Âå°±ä¼Âå¤Â亠SYN_RCVD ç¶æÂÂï¼Âæ¤æ¶åÂÂæ¹è¿Âà没æÂÂå®ÂÃ¥Â
¨å»ºç«ÂÃ¥Â
¶è¿ÂæÂÂ¥
ï¼ÂæÂÂå¡å¨ä¼ÂæÂÂæ¤ç§Âç¶æÂÂä¸Â请æ±Âè¿ÂæÂ¥æ¾å¨ä¸Â个éÂÂÃ¥ÂÂéÂÂï¼ÂæÂÂ们æÂÂè¿Âç§ÂéÂÂÃ¥ÂÂ称ä¹Â为åÂÂè¿ÂæÂ¥éÂÂÃ¥ÂÂ
ãÂÂ
è¿ÂæÂÂä¸Â个堨è¿ÂæÂ¥éÂÂÃ¥ÂÂï¼Âå°±æ¯已ç»Âå®ÂæÂÂä¸Â次æ¡æÂÂï¼Â建ç«Âèµ·è¿ÂæÂ¥çÂÂå°±ä¼Âæ¾å¨堨è¿ÂæÂ¥éÂÂÃ¥ÂÂä¸ÂãÂÂå¦ÂæÂÂéÂÂÃ¥ÂÂ满äºÂå°±æÂÂå¯è½ä¼Âåºç°丢å ç°象ãÂÂ
Ã¥ÂÂ次æÂ¥æÂÂ
é¦Âå Âè¦ÂæÂÂç½ï¼Â客æ·端åÂÂæÂÂå¡端é½å¯以åÂÂèµ·å ³éÂÂè¿ÂæÂ¥çÂÂ请æ±ÂãÂÂ
è¿ÂéÂÂ以客æ·端åÂÂèµ·å ³éÂÂ请æ±Â为ä¾ÂãÂÂ
Ã¥ÂÂå¼Âå§Âï¼Â客æ·端åÂÂæÂÂå¡å¨é½å¤ÂäºÂàestablished
àçÂÂç¶æÂÂï¼Â客æ·端主å¨åÂÂ起àåÂ
³éÂÂè¿ÂæÂÂ¥
àçÂÂ请æ±ÂãÂÂ
- 第ä¸Â次æÂ¥æÂÂ
客æ·端åÂÂéÂÂä¸Â个 FIN (finish) æÂ¥æÂÂï¼ÂæÂ¥æÂÂä¸Âä¼ÂæÂÂå®Âä¸Â个åºÂÃ¥ÂÂå·ãÂÂæ¤æ¶客æ·端å¤ÂäºÂàFIN_WAIT1 ç¶æÂÂ
ãÂÂ
- 第äºÂ次æÂ¥æÂÂ
æÂÂå¡端æ¶å° FIN ä¹ÂÃ¥ÂÂï¼Âä¼ÂÃ¥ÂÂé ACK æÂ¥æÂÂï¼Âä¸ÂæÂÂ客æ·端çÂÂåºÂÃ¥ÂÂå·å¼ +1 ä½Â为 ACK æÂ¥æÂÂçÂÂåºÂÃ¥ÂÂå·å¼ï¼Â表æÂÂå·²ç»Âæ¶å°客æ·端çÂÂæÂ¥æÂÂäºÂï¼Âæ¤æ¶æÂÂå¡端å¤ÂäºÂàCLOSE_WAIT ç¶æÂÂ
ãÂÂ
客æ·端æ¶å°æÂÂå¡端çÂÂ确认åÂÂï¼Âè¿ÂÃ¥Â
Â¥FIN_WAIT2ï¼Âç»Âæ¢çÂÂå¾Â
2ï¼Âç¶æÂÂ
ï¼ÂçÂÂå¾Â
æÂÂå¡端åÂÂåºçÂÂè¿ÂæÂ¥éÂÂæ¾æÂ¥æÂÂ段
ãÂÂ
æ¤æ¶ï¼ÂæÂÂå¡端è¿Âå¯以åÂÂéÂÂæªåÂÂéÂÂå®ÂçÂÂæ°æ®ï¼Â客æ·端ä¹Âå¯以æÂ¥æ¶æ°æ®ãÂÂ
- 第ä¸Â次æÂ¥æÂÂ
å¦ÂæÂÂæÂÂå¡端ä¹Âæ³æÂÂå¼Âè¿ÂæÂ¥äºÂï¼ÂÃ¥ÂÂ客æ·端çÂÂ第ä¸Â次æÂ¥æÂÂä¸Âæ ·ï¼ÂÃ¥ÂÂç» FIN æÂ¥æÂÂï¼Âä¸ÂæÂÂå®Âä¸Â个åºÂÃ¥ÂÂå·ãÂÂæ¤æ¶æÂÂå¡端è¿ÂÃ¥Â
¥æÂÂÃ¥ÂÂ确认ç¶æÂÂï¼ÂLAST_ACK çÂÂç¶æÂÂ
ï¼Â
- 第åÂÂ次æÂ¥æÂÂ
客æ·端æ¶å° FIN ä¹ÂÃ¥ÂÂï¼Âä¸Âæ ·åÂÂéÂÂä¸Â个 ACK æÂ¥æÂÂä½Â为åºÂçÂÂï¼Âä¸ÂæÂÂæÂÂå¡端çÂÂåºÂÃ¥ÂÂå·å¼ +1 ä½Â为èª己 ACK æÂ¥æÂÂçÂÂåºÂÃ¥ÂÂå·å¼ï¼Âæ¤æ¶客æ·端å¤ÂäºÂè¶Â
æ¶çÂÂå¾Â
TIME_WAIT ç¶æÂÂ
ï¼Âç»Âè¿Âè¶Â
æ¶æ¶é´åÂÂÃ¥Â
³éÂÂè¿ÂæÂ¥ãÂÂæÂÂå¡端æ¶å° ACK æÂ¥æÂÂä¹Âå ç«Âå³ Ã¥Â
³éÂÂè¿ÂæÂ¥äºÂï¼Âå¤Â亠CLOSED ç¶æÂÂãÂÂ
为ä»Âä¹Â客æ·端éÂÂè¦Âè¿Â堥趠æ¶çÂÂå¾ ç¶æÂÂ
ç¡®ä¿ÂæÂÂå¡端è½æ¶å°èª己ç ACK æÂ¥æÂÂãÂÂ
Ã¥ÂÂ设客æ·端åÂÂéÂÂå® ack Ã¥ÂÂ
ï¼Âå°±ç«ÂÃ¥ÂȌÂ
³éÂÂäºÂè¿ÂæÂ¥ï¼Âä¸Âæ¦ ack Ã¥ÂÂ
å¨ç½Âç»Âä¼ è¾Âä¸Â丢失ï¼ÂæÂÂå¡å¨å°Âä¸Âç´å¤ÂäºÂàæÂÂÃ¥ÂÂ确认ç¶æÂÂï¼ÂLAST_ACKï¼Â
ãÂÂæÂÂå¡端å 为没æÂÂæ¶å° ACK Ã¥ÂÂ
ä¼ÂéÂÂå FIN Ã¥ÂÂ
ï¼Âæ¤æ¶客æ·端åÂ
³éÂÂäºÂé¾æÂ¥ï¼Âé£ä¹Âå°±æ æ³ÂÃ¥Â
³éÂÂè¿ÂæÂ¥ãÂÂ
æÂÂå¡端å 为没æÂÂæ¶å° ACK Ã¥ÂÂ
ä¼ÂéÂÂå FIN Ã¥ÂÂ
ï¼Â客æ·端æ¶å° FIN Ã¥ÂÂ
Ã¥ÂÂï¼Âå°±ä¼ÂéÂÂå ACK Ã¥ÂÂ
并å·æ°è¶Â
æ¶æ¶é´
ãÂÂ
æÂÂÃ¥ÂÂï¼Â客æ·端åÂÂä¹Â没æÂÂæ¶å°æÂÂå¡å¨åÂÂéÂÂè¿ÂæÂ¥ç FINï¼ÂçÂÂå¾ ä¸Â段æ¶é´åÂÂï¼Â客æ·端ä¹Âè¿Âå ¥äºÂå ³éÂÂç¶æÂÂ(Closed)ãÂÂ
请æ±ÂæÂ¥æÂÂ
HTTP请æ±ÂæÂ¥æÂÂç±请æ±Âè¡Âï¼ÂRequest Lineï¼ÂãÂÂ请æ±Â头é¨ï¼ÂHeadersï¼ÂÃ¥ÂÂ请æ±Â主ä½Âï¼ÂBodyï¼Âä¸Âé¨åÂÂç»ÂæÂÂãÂÂ以ä¸Âæ¯ä¸Â个示ä¾ÂHTTP请æ±ÂæÂ¥æÂÂçÂÂç»ÂæÂÂï¼Â
GET /path/to/resource HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: https://www.example.com/referer-page
Connection: keep-alive
请æ±Â主ä½Âï¼Âå¦ÂæÂÂÃ¥ÂÂå¨ï¼Â//æ¯Âå¦Âï¼ÂHelloï¼ÂWorld!!
解éÂÂæ¯Â个é¨åÂÂçÂÂå«ä¹Âï¼Â
-
请æ±Âè¡Âï¼ÂRequest Lineï¼Âï¼Âå å«äºÂHTTPæ¹æ³ÂãÂÂ请æ±ÂçÂÂè·¯å¾ÂÃ¥ÂÂÃ¥ÂÂè®®çÂÂæ‹ÂÂ
- HTTPæ¹æ³Âï¼Âä¾Âå¦ÂGETãÂÂPOSTãÂÂPUTçÂÂï¼ÂæÂÂå®ÂäºÂ客æ·端对èµÂæºÂçÂÂæÂÂä½Âç±»åÂÂãÂÂ
- 请æ±ÂçÂÂè·¯å¾ÂæÂÂå®ÂäºÂæÂÂå¡å¨ä¸Âè¦Â访é®çÂÂèµÂæºÂçÂÂè·¯å¾ÂãÂÂ
- Ã¥ÂÂè®®çÂÂæ¬ï¼Âä¾Âå¦ÂHTTP/1.1ï¼ÂæÂÂå®ÂäºÂ客æ·端æÂÂ使ç¨çÂÂHTTPÃ¥ÂÂè®®çÂÂæ‹ÂÂ
-
请æ±Â头é¨ï¼ÂHeadersï¼Âï¼Âå å«äºÂä¸Â请æ±Âç¸堳çÂÂÃ¥ÂÂç§Âå Âæ°æ®信æ¯ï¼Â以é®å¼对çÂÂå½¢å¼Â表示ãÂÂæ¯Â个é®å¼对å æ®ä¸Âè¡ÂãÂÂ
- Hostï¼ÂæÂÂå®ÂäºÂæÂÂå¡å¨çÂÂ主æºåÂÂæÂÂIPå°åÂÂãÂÂ
- User-Agentï¼ÂÃ¥ÂÂéÂÂ请æ±ÂçÂÂ客æ·端çÂÂç¨æ·代çÂÂæ Âè¯ÂãÂÂ
- Acceptï¼ÂæÂÂå®ÂäºÂ客æ·端è½å¤ÂæÂ¥åÂÂçÂÂÃ¥ÂÂåºÂå 容类åÂÂãÂÂ
- Refererï¼ÂæÂÂå®ÂäºÂ请æ±ÂçÂÂæÂ¥æºÂ页é¢çÂÂURLãÂÂ
- Connectionï¼ÂæÂÂå®ÂäºÂ客æ·端ä¸ÂæÂÂå¡å¨ä¹Âé´çÂÂè¿ÂæÂ¥æ¯å¦ä¿ÂæÂÂæÂÂä¹ è¿ÂæÂ¥ãÂÂ
-
请æ±Â主ä½Âï¼ÂBodyï¼Âï¼Âå¯éÂÂé¨åÂÂï¼Âç¨äºÂÃ¥ÂÂéÂÂéÂÂå çÂÂ请æ±Âæ°æ®ï¼Âä¾Âå¦Â表åÂÂæ°æ®ãÂÂJSONæ°æ®çÂÂãÂÂå¨GET请æ±Âä¸ÂéÂÂ常为空ï¼ÂèÂÂå¨POST请æ±Âä¸Âä¼Âå å«è¦ÂÃ¥ÂÂéÂÂçÂÂæ°æ®ãÂÂ
Ã¥ÂÂåºÂæÂ¥æÂÂ
HTTPÃ¥ÂÂåºÂæÂ¥æÂÂç±ç¶æÂÂè¡Âï¼ÂStatus Lineï¼ÂãÂÂÃ¥ÂÂåºÂ头é¨ï¼ÂHeadersï¼ÂÃ¥ÂÂÃ¥ÂÂåºÂ主ä½Âï¼ÂBodyï¼Âä¸Âé¨åÂÂç»ÂæÂÂãÂÂ以ä¸Âæ¯ä¸Â个示ä¾ÂHTTPÃ¥ÂÂåºÂæÂ¥æÂÂçÂÂç»ÂæÂÂï¼Â
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 1234
Server: Apache/2.4.29 (Unix)
Ã¥ÂÂåºÂ主ä½Âï¼Âå¦ÂæÂÂÃ¥ÂÂå¨ï¼Â(注æÂÂï¼ÂÃ¥ÂÂåºÂ主ä½Âä¸Âä»Â
ä»Â
æ¯æ¢è¡Âï¼ÂèÂÂæ¯çÂÂæ£空äºÂä¸Âæ ·ï¼ÂæÂÂå¼Âå§Âæ¾示主ä½Âé¨åÂÂ)
解éÂÂæ¯Â个é¨åÂÂçÂÂå«ä¹Âï¼Â
-
ç¶æÂÂè¡Âï¼ÂStatus Lineï¼Âï¼Âå å«äºÂÃ¥ÂÂè®®çÂÂæ‹ÂÂç¶æÂÂç ÂÃ¥ÂÂç¶æÂÂæ¶Âæ¯ãÂÂ
- Ã¥ÂÂè®®çÂÂæ¬ï¼Âä¾Âå¦ÂHTTP/1.1ï¼ÂæÂÂå®ÂäºÂæÂÂå¡å¨使ç¨çÂÂHTTPÃ¥ÂÂè®®çÂÂæ‹ÂÂ
- ç¶æÂÂç Âæ¯ä¸Â个ä¸Âä½Âæ°ï¼Âç¨äºÂ表示æÂÂå¡å¨对请æ±ÂçÂÂå¤ÂçÂÂç»ÂæÂÂãÂÂä¾Âå¦Âï¼Âç¶æÂÂç Â200表示æÂÂÃ¥ÂÂï¼Â404表示èµÂæºÂæªæ¾å°ãÂÂ
- ç¶æÂÂæ¶Âæ¯æ¯对ç¶æÂÂç ÂçÂÂç®Âè¦ÂæÂÂè¿°ï¼ÂæÂÂä¾ÂäºÂæ´详ç»ÂçÂÂ说æÂÂãÂÂ
-
Ã¥ÂÂåºÂ头é¨ï¼ÂHeadersï¼Âï¼Âå å«äºÂä¸ÂÃ¥ÂÂåºÂç¸堳çÂÂÃ¥ÂÂç§Âå Âæ°æ®信æ¯ï¼Â以é®å¼对çÂÂå½¢å¼Â表示ãÂÂæ¯Â个é®å¼对å æ®ä¸Âè¡ÂãÂÂ
- Content-Typeï¼ÂæÂÂå®ÂäºÂÃ¥ÂÂåºÂ主ä½ÂçÂÂåªÂä½Âç±»åÂÂÃ¥ÂÂÃ¥ÂÂ符éÂÂãÂÂ
- Content-Lengthï¼ÂæÂÂå®ÂäºÂÃ¥ÂÂåºÂ主ä½ÂçÂÂé¿度ï¼Â以åÂÂèÂÂ为åÂÂä½Âï¼ÂãÂÂ
- Serverï¼ÂæÂÂå®ÂäºÂÃ¥ÂÂåºÂçÂÂæÂÂå¡å¨软件åÂÂ称åÂÂçÂÂæ‹ÂÂ
-
Ã¥ÂÂåºÂ主ä½Âï¼ÂBodyï¼Âï¼Âå¯éÂÂé¨åÂÂï¼Âå å«äºÂæÂÂå¡å¨è¿ÂÃ¥ÂÂçÂÂå®Âé åÂÂåºÂå 容ãÂÂä¾Âå¦Âï¼Â对äºÂHTML页é¢ï¼ÂÃ¥ÂÂåºÂ主ä½Âå¯è½å å«HTMLæ Âè®°åÂÂæÂÂ挠容ãÂÂ
è·¨åÂÂ
ä»Âä¹Âæ¯跨åÂÂï¼Â
CORS 堨称æ¯ Cross-Origin Resource Sharingï¼ÂæÂÂ为跨åÂÂèµÂæºÂ報享ãÂÂå½Âä¸Â个èµÂæºÂå»访é®å¦ä¸Â个ä¸ÂÃ¥ÂÂÃ¥ÂÂÃ¥ÂÂæÂÂè ä¸ÂÃ¥ÂÂ端å£çÂÂèµÂæºÂæ¶ï¼Âå°±ä¼ÂÃ¥ÂÂåº跨åÂÂ请æ±ÂãÂÂå¦ÂæÂÂå¦ä¸Â个èµÂæºÂä¸Âå Â许堶è¿Âè¡Âè·¨åÂÂèµÂæºÂ访é®ï¼Âå°±ä¼Âé æÂÂè·¨åÂÂãÂÂ
è·¨åÂÂä¸Âæ¯é®é¢Âï¼Âæ¯æµÂè§Âå¨çÂÂå®Âå ¨æºå¶
è·¨åÂÂä¸Âä¼ÂéÂȾ¢请æ±ÂçÂÂÃ¥ÂÂåºï¼Âä¹Âä¸Âä¼ÂéÂȾ¢请æ±ÂçÂÂæÂ¥æ¶
ï¼Âè·¨åÂÂæ¯æµÂè§Âå¨为äºÂä¿Âæ¤å½ÂÃ¥ÂÂ页é¢ï¼Âä½ çÂÂ请æ±Âå¾Âå°äºÂÃ¥ÂÂåºÂï¼Âä½Âæ¯æµÂè§Âå¨ä¸Âä¼Âå°Â请æ±Âå°çÂÂæ°æ®æÂÂ交ç»Âå½ÂÃ¥ÂÂ页é¢ä¸ÂçÂÂÃ¥ÂÂè°Âï¼ÂÃ¥ÂÂèÂÂ代ä¹ÂçÂÂæ¯åÂȾÂÂ示你è¿Âæ¯ä¸Â个跨åÂÂæ°æ®ãÂÂ
Ã¥ÂÂæºÂçÂÂç¥导è´ãÂÂ
æÂÂè°ÂÃ¥ÂÂæºÂçÂÂçÂ¥ï¼Âå°±æ¯åÂÂè®®ãÂÂÃ¥ÂÂÃ¥ÂÂãÂÂ端å£å·
é½è¦Âç¸åÂÂï¼ÂæÂÂä¸Â个ä¸Âç¸åÂÂï¼Âé£ä¹Âå°±æ¯éÂÂÃ¥ÂÂæºÂï¼Âå°±ä¼Âåºç°跨åÂÂãÂÂ
// è·¨åÂÂ(端å£ä¸ÂÃ¥ÂÂ)
http://localhost:8080
http://localhost:3000
// è·¨åÂÂ(Ã¥ÂÂè®®ä¸ÂÃ¥ÂÂ)
https://localhost:8080
http://localhost:8080
// è·¨åÂÂ(Ã¥ÂÂÃ¥ÂÂ)
https://localhost:8080
https://192.168.1.2:8080
// è·¨åÂÂ(Ã¥ÂÂè®®ä¸ÂÃ¥ÂÂï¼Â端å£ä¹Âä¸ÂÃ¥ÂÂ)
// http é»Â认端å£æ¯ 80ï¼Âhttps é»Â认端å£æ¯ 443
http://localhost/bbb
https://localhost/aaa
解å³跨åÂÂ
- 纯åÂÂ端æ¹å¼Â
Ã¥ÂÂ设æÂÂ们æÂÂ个åÂÂ端æÂÂå¡ 3000ï¼ÂæÂÂä¾ÂäºÂà/user
àæÂ¥å£ï¼ÂæÂÂ们å¯以ç´æÂ¥å¨à.html
àæÂÂ件ä¸Â访é®ï¼Âå¦ÂæÂÂÃ¥ÂÂ端ä¸Â设置跨åÂÂï¼Âé£ä¹Âè¯å®Âä¼Âåºç°跨åÂÂæÂÂ示çÂÂãÂÂ
// server
const express = require('express')
const app = express()
app.get('/user', (req, res) => {
res.json({
code: 0,
msg: '请æ±ÂuseræÂÂÃ¥ÂÂ'
})
})
app.listen('3000', () => {
console.log('server running at port 3000...')
})
// client
<script>
const xhr = new XMLHttpRequest()
xhr.open('get', 'http://localhost:3000/user')
xhr.onload = function() {
consolelog(xhr.response)
}
xhr.send()
// fetch
fetch('http://localhost:3000/user')
.then(res => res.text())
.then(res => {
console.log(res)
})
</script>
Ã¥ÂÂ端设置跨åÂÂ访é®
// CORS
app.all('*', function(req, res, next) {
// Ã¥Â
Â许æÂÂæÂÂ请æ±ÂæºÂ
res.header("Access-Control-Allow-Origin", "*") // Ã¥ÂÂÃ¥ÂÂå°åÂÂ
res.header("Access-Control-Allow-Headers", "*") // Ã¥Â
Â许èªå®Âä¹ headers
res.header("Access-Control-Allow-Methods", "*") // é»Â认åÂ
Â许çÂÂæ¹æ³Âï¼ÂGET,HEAD,POST
next()
})
- Ã¥ÂÂ端å¤Âç 主è¦Âæ¯éÂÂè¿ÂÃÂ
webpack devServer
àçÂÂÃÂproxy
àæÂ¥å¤ÂçÂÂãÂÂ
...
devServer: {
proxy: {
'/api': {
target: 'http://localhost:3000/' // http://localhost:8080/api/user => http://localhost:3000/api/user
}
},
proxy: {
'/no-api': {
target: 'http://localhost:3000/', // http://localhost:8080/no-api/user => http://localhost:3000/user
pathRewrite: {
'/no-api': '', // Ã¥ÂÂ端æÂ¥å£ä¸Âä¸Âè¬ä¸Âä¼Âå«æ api æ Âè¯Â符ï¼ÂæÂÂ们å¯以åÂȾÂÂ
}
}
},
}
...
- Nginx
è¦Â注æÂÂçÂÂæ¯ï¼ÂdevServer éÂ
Âç½® proxy åªæ¯åÂÂå¨äºÂæÂÂ们å¼ÂÃ¥ÂÂ项ç®æ¶æÂÂç¨ï¼Âå¦ÂæÂÂ项ç®è¦Âä¸Â线ï¼ÂdevServer 就没æÂÂäºÂï¼Âè¿Âæ¶å¯以èÂÂèÂÂéÂÂç¨àNginx
àæ¥代çÂÂãÂÂ
- Ã¥ÂÂÃ¥ÂÂ端åÂÂ并æ¹å¼Â
æÂÂ们å¯以ä¸ÂéÂÂç¨àdevServer proxy
àæ¹å¼Âï¼ÂèÂÂæ¯å¨åÂÂ端éÂ
Â置àwebpack-dev-middleware
ï¼Âå°ÂÃ¥ÂÂÃ¥ÂÂ端è¿Âè¡ÂÃ¥ÂÂ并ãÂÂ
const express = require('express')
const webpack = require('webpack')
const middle = require('webpack-dev-middleware')
const compile = require('./webpack.config.js')
const app = express()
app.use(middle(compile))
app.get('/user', (req, res) => {
res.json({
code: 0,
msg: '请æ±ÂuseræÂÂÃ¥ÂÂ'
})
})
app.listen('3000', () => {
console.log('server running at port 3000...')
})
- jsonp
æ¯Âè¾ÂèÂÂãÂÂ堼容æ§好çÂÂæ¹å¼ÂãÂÂ
å©ç¨æ Âç¾没æÂÂè·¨åÂÂéÂÂå¶çÂÂæ¼Âæ´Âï¼Âå¨ script æ Âç¾ä¸ÂæÂÂ们å¯以å¼Âç¨堶ä»ÂæÂÂå¡ä¸ÂçÂÂèÂÂæ‹ÂÂ
æÂÂ常è§ÂçÂÂåºæ¯就æ¯ CDN.
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
使ç¨æ¹å¼Âï¼Â
function callback(res) {
console.log(JSON.stringify(res, null, 2))
}
// å¨æÂÂÃ¥ÂÂ建 script æ Âç¾ï¼Â设置好 scr å±Âæ§ï¼Â主è¦ÂÃ¥ÂÂæ°æ¯ cb=callback
const script = document.createElement('script')
script.src = 'http://127.0.0.1:3000/info/jsonp?cb=callback'
document.getElementByTagsName('head')[0].appendChild(script)
é¢Â请æ±Â(OPTIONS)
OPTIONS 请æ±Âå GET 请æ±ÂçÂÂåºå«å¨äºÂå®Â们çÂÂç®çÂÂÃ¥ÂÂä½Âç¨ä¸ÂÃ¥ÂÂãÂÂ
- OPTIONS 请æ±Âç¨äºÂæ¢æµÂæÂÂå¡å¨çÂÂæ¯æÂÂè½åÂÂÃ¥ÂÂå®Âæ½å®ÂÃ¥Â
¨æºå¶ï¼Â以便å¨è¿Âè¡Âå®ÂéÂÂ
请æ±Âä¹ÂÃ¥ÂÂè¿Âè¡ÂÃÂ
é¢Âæ£Â
- å ¶å®Â请æ±Âæ¹æ³Âï¼Âæ¯Â妠GET 请æ±ÂÃ¥ÂÂæ¯ç¨äºÂè·åÂÂå®Âé çÂÂèµÂæºÂæ°æ®ãÂÂ
éÂÂè¦Â注æÂÂçÂÂæ¯ï¼Âåºç°两个ç¸åÂÂURLä½Â请æ±Âæ¹æ³Âä¸ÂÃ¥ÂÂçÂÂ请æ±Âå¯è½æ¯å 为æµÂè§Âå¨è¿Âè¡ÂäºÂ请æ±Âä¼ÂÃ¥ÂÂæÂÂÃ¥Â
¶ä»ÂÃ¥ÂÂå ãÂÂä¾Âå¦Âï¼ÂæÂÂäºÂæµÂè§Âå¨å¯è½ä¼Âå¨åÂÂéÂÂå®ÂéÂÂ
ç GET 请æ±Âä¹ÂÃ¥ÂÂï¼ÂÃ¥Â
ÂÃ¥ÂÂéÂÂä¸Â个 OPTIONS 请æ±Â以éªÂè¯Âæ¯å¦åÂ
Â许跨åÂÂ请æ±Â
ãÂÂè¿Âæ¯æµÂè§Âå¨çÂÂè¡Â为ï¼Â并éÂÂæÂÂæÂÂ请æ±Âé½ä¼Âåºç°è¿Âç§ÂæÂÂ
Ã¥Â括ÂÃ¥Â
·ä½ÂÃ¥ÂÂå³äºÂæµÂè§Âå¨çÂÂå®Âç°åÂÂéÂ
Âç½®ãÂÂ
å¦ÂæÂÂæÂÂ们ä¸Âæ³è¦Âàé¢Âæ£Â
ï¼Âé£ä¹Âå¨æÂÂå¡端设置àAccess-Control-Max-Age
ï¼Â表示å¨à1000ç§Â
àåÂÂ
ï¼Âé½ä¸ÂéÂÂè¦Âé¢Â请æ±ÂéªÂè¯Â
ãÂÂ
res.writeHead(200, {
'Access-Control-Max-Age': '1000', // ç§Â
})
æÂÂå¡端设置好ä¹ÂÃ¥ÂÂï¼Â客æ·端åÂÂèµ·çÂÂ第ä¸Â次请æ±Âï¼Âè¿Âæ¯ä¼ÂæÂÂé¢Âæ£Âï¼ÂOPTIONSï¼ÂÃ¥ÂÂå®Âé 请æ±Âï¼ÂÃ¥ÂÂ次å·æ°页é¢就åªä¼ÂÃ¥ÂÂèµ·å®Âé çÂÂ请æ±ÂäºÂãÂÂ
Cache-Control
HTTP头é¨åÂÂ段Cache-Control
ç¨äºÂæ§å¶ç¼ÂÃ¥ÂÂçÂÂè¡Â为ï¼Âå®Âå¯以æÂÂ示æµÂè§Âå¨æÂÂ代çÂÂæÂÂå¡å¨æ¯å¦ç¼ÂÃ¥ÂÂÃ¥ÂÂåºÂ以åÂÂå¦Âä½Âç¼ÂÃ¥ÂÂãÂÂ
Cache-Control
头é¨åÂÂ段æÂÂå¤Â个å¯éÂÂçÂÂæÂÂ令ï¼Âå¯以åÂÂç¬使ç¨æÂÂç»ÂÃ¥ÂÂ使ç¨ãÂÂä¸Âé¢æ¯ä¸ÂäºÂ常è§ÂçÂÂæÂÂ令åÂÂÃ¥Â
¶ä½Âç¨ï¼Â
no-cache
ï¼ÂæÂÂ示æµÂè§Âå¨åÂÂ代çÂÂæÂÂå¡å¨ä¸ÂåºÂç´æ¥使ç¨
ç¼ÂÃ¥ÂÂçÂÂÃ¥ÂÂåºÂï¼ÂèÂÂåºÂÃ¥ÂÂéÂÂ请æ±Âå°æÂÂå¡å¨è¿Âè¡ÂéªÂè¯Â
ãÂÂæÂÂå¡å¨å¯以éÂÂè¿Âæ ¡éªÂ请æ±Â头ï¼ÂEtag/Last-Modifiedï¼Âæ¥确å®Âæ¯å¦éÂÂè¦Âè¿ÂÃ¥ÂÂæ°çÂÂÃ¥ÂÂåºÂæÂÂ使ç¨ç¼ÂÃ¥ÂÂçÂÂÃ¥ÂÂåºÂãÂÂno-store
ï¼ÂæÂÂ示æµÂè§Âå¨åÂÂ代çÂÂæÂÂå¡å¨ä¸ÂåºÂÃ¥ÂÂå¨任ä½Âå ³äºÂ请æ±ÂÃ¥ÂÂÃ¥ÂÂåºÂçÂÂå 容
ãÂÂæ¯Â次é½忠须ä»ÂÃ¥ÂÂå§ÂæÂÂå¡å¨è·åÂÂå®Âæ´çÂÂÃ¥ÂÂåºÂãÂÂpublic
ï¼ÂæÂÂ示åÂÂåºÂå¯以被任ä½ÂèÂÂç¹ç¼ÂÃ¥ÂÂï¼Âå æ¬客æ·端åÂÂ代çÂÂæÂÂå¡å¨ï¼Âç¼ÂÃ¥ÂÂãÂÂprivate
ï¼ÂæÂÂ示åÂÂåºÂåªè½被客æ·端ç¼ÂÃ¥ÂÂï¼Âä¸Âå Â许代çÂÂæÂÂå¡å¨ç¼ÂÃ¥ÂÂãÂÂmax-age=<seconds>
ï¼ÂæÂÂ示åÂÂåºÂå¨æÂÂå®ÂçÂÂç§Âæ°å å¯以被ç¼ÂÃ¥ÂÂãÂÂä¾Âå¦Âï¼ÂCache-Control: max-age=3600
表示åÂÂåºÂå¯以å¨ä¸Â个å°Âæ¶å 被ç¼ÂÃ¥ÂÂãÂÂs-maxage=<seconds>
ï¼Â类似äºÂmax-age
ï¼Âä½Âä» éÂÂç¨äºÂ報享ç¼ÂÃ¥ÂÂï¼Âä¾Âå¦Â代çÂÂæÂÂå¡å¨ï¼ÂãÂÂå®Âè¦ÂçÂÂmax-age
æÂÂ令ãÂÂ
è¿ÂäºÂæÂÂ令å¯以éÂÂè¿ÂéÂÂå·åÂÂéÂÂçÂÂæ¹å¼Âç»ÂÃ¥ÂÂ使ç¨ï¼Â以满足ç¹å®ÂçÂÂç¼ÂÃ¥ÂÂéÂÂæ±ÂãÂÂ
éÂÂè¿Â使ç¨Cache-Control
头é¨åÂÂ段ï¼ÂæÂÂå¡å¨å¯以æ§å¶ç¼ÂÃ¥ÂÂçÂÂè¡Â为ï¼ÂÃ¥ÂÂ
æ¬ç¼ÂÃ¥ÂÂæÂÂæÂÂæÂÂãÂÂæ¯å¦éÂÂè¦ÂéªÂè¯ÂçÂÂãÂÂèÂÂæµÂè§Âå¨åÂÂ代çÂÂæÂÂå¡å¨ä¼Âæ ¹æ®è¿ÂäºÂæÂÂ令æÂ¥å³å®Âæ¯å¦ç¼ÂÃ¥ÂÂÃ¥ÂÂåºÂ以åÂÂå¦Âä½Â使ç¨ç¼ÂÃ¥ÂÂãÂÂè¿ÂæÂÂå©äºÂæÂÂé«Âæ§è½åÂÂÃ¥ÂÂå°Âç½Âç»ÂæµÂéÂÂï¼ÂÃ¥ÂÂæ¶ä¿Âè¯ÂÃ¥ÂÂæ¶è·åÂÂæÂÂæ°çÂÂèµÂæºÂãÂÂ
æ¯Âå¦Â:
res.setHeader('Cache-Control', 'max-age=3600, public');
à表示æÂÂæÂÂèÂÂç¹é½è½ç¼ÂÃ¥ÂÂï¼Â客æ·端ãÂÂ代çÂÂæÂÂå¡å¨çÂÂï¼Â3600ç§Âä¹ÂÃ¥ÂÂï¼Âå°±éÂÂæ°ä»ÂæÂÂå¡å¨æÂÂÃ¥ÂÂèµÂæºÂï¼ÂæÂ¥çÂÂç¼ÂÃ¥ÂÂèµ·æÂ¥ï¼Â客æ·端åÂÂå¯以使ç¨ç¼ÂÃ¥ÂÂèµÂæºÂäºÂãÂÂ以æ¤循篅
çÂÂå¦Âä¸Âä¾ÂÃ¥ÂÂï¼Â
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Hello Http!你好åÂÂ</h1>
<script>
// 请æ±Âå¦ä¸Â个æÂÂå¡å¨èµÂæºÂ
fetch('http://localhost:9999/', {
method: 'get'
})
.then(res => console.log('??? ', res))
</script>
<!-- å 载 js èÂÂæ¬ -->
<script src="/script.js"></script>
</body>
</html>
// server.js
const http = require('http');
const fs = require('fs')
const html = fs.readFileSync('./index.html', 'utf8')
// Ã¥ÂÂ建HTTPæÂÂå¡å¨
const server = http.createServer((req, res) => {
if (req.url === '/') {
// 设置åÂÂåºÂ头é¨åÂÂ段
res.setHeader('Cache-Control', 'max-age=10, public');
// Ã¥Â
¶ä»ÂÃ¥ÂÂåºÂ设置ï¼ÂÃ¥ÂÂåºÂ头åÂÂ段ä¹Âå¯以å¨è¿Â设置
res.writeHead(200, {
'Content-Type': 'text/html'
});
res.end(html);
}
if (req.url === '/script.js') {
res.writeHead(200, {
'Content-Type': 'text/javascript',
'Cache-Control': 'max-age=10, private' // åªè½客æ·端ç¼ÂÃ¥ÂÂï¼Â并丠10 ç§ÂÃ¥ÂÂç¼ÂÃ¥ÂÂ失æÂÂ
})
res.end('console.log("Javascript loaded!!!")') // æ§å¶å°æÂÂå° ..
}
});
// çÂÂå¬端å£
const port = 8888;
server.listen(port, () => {
console.log(`Server running at http://localhost:${port}/`);
});
å 亠cache-control ä¹ÂÃ¥ÂÂï¼Â第ä¸Â次访é®å°äºÂèµÂæºÂï¼ÂÃ¥ÂÂ次访é®æ¶ï¼Âå°±ä¼Â读åÂÂæµÂè§Âå¨ç¼ÂÃ¥ÂÂçÂÂèµÂæºÂäºÂï¼ÂçÂÂ请æ±Âæ¶é´æ¯éÂÂ常çÂÂçÂÂãÂÂ
Disk cache å Memory cache
Disk cache
Ã¥ÂÂMemory cache
æ¯æµÂè§Âå¨ä¸Â常è§ÂçÂÂ两ç§Âç¼ÂÃ¥ÂÂæºå¶ï¼Âå®Â们å¨ç¼ÂÃ¥ÂÂèµÂæºÂæ¶æÂÂä¸ÂäºÂåºå«ãÂÂ
- Disk Cacheï¼Âç£ÂçÂÂç¼ÂÃ¥ÂÂï¼ ï¼ÂDisk cacheæ¯æÂÂå°Â请æ±ÂçÂÂèµÂæºÂÃ¥ÂÂå¨å¨硬çÂÂä¸ÂçÂÂç¼ÂÃ¥ÂÂæºå¶ãÂÂå½ÂæµÂè§Âå¨æ¶å°æÂÂå¡å¨çÂÂÃ¥ÂÂåºÂÃ¥ÂÂï¼Âä¼Âå°ÂÃ¥ÂÂåºÂçÂÂèµÂæºÂä¿ÂÃ¥ÂÂå¨硬çÂÂçÂÂç¹å®Âä½Âç½®ãÂÂå½Âä¸Â次请æ±Âç¸åÂÂçÂÂèµÂæºÂæ¶ï¼ÂæµÂè§Âå¨ä¼Âé¦ÂÃ¥Â
Âæ£Âæ¥硬çÂÂä¸ÂçÂÂç¼ÂÃ¥ÂÂï¼Âå¦ÂæÂÂç¼ÂÃ¥ÂÂÃ¥ÂÂå¨ä¸ÂæÂÂæÂÂï¼ÂÃ¥ÂÂç´æÂ¥ä»Â硬çÂÂä¸Â读åÂÂèµÂæºÂï¼Âé¿åÂ
ÂäºÂÃ¥ÂÂ次åÂÂéÂÂç½Âç»Â请æ±ÂãÂÂ
Disk cache
ç¸对äºÂMemory cacheæ¥说ï¼ÂÃ¥ÂÂå¨容éÂÂè¾Â大ï¼Âå¯以ç¼ÂÃ¥ÂÂæ´å¤ÂçÂÂèµÂæºÂï¼Âä½Â访é®éÂÂ度ç¸对è¾Âæ ¢ãÂÂ
- Memory Cacheï¼ÂÃ¥ÂÂ
Ã¥ÂÂç¼ÂÃ¥ÂÂï¼ ï¼ÂMemory cacheæ¯æÂÂå°Â请æ±ÂçÂÂèµÂæºÂÃ¥ÂÂå¨å¨åÂÂ
Ã¥ÂÂä¸ÂçÂÂç¼ÂÃ¥ÂÂæºå¶ãÂÂå½ÂæµÂè§Âå¨æ¶å°æÂÂå¡å¨çÂÂÃ¥ÂÂåºÂÃ¥ÂÂï¼Âä¼Âå°ÂÃ¥ÂÂåºÂçÂÂèµÂæºÂä¿ÂÃ¥ÂÂå¨åÂÂ
Ã¥ÂÂä¸ÂãÂÂÃ¥ÂÂ
Ã¥ÂÂç¼ÂÃ¥ÂÂçÂÂ访é®éÂÂ度éÂÂ常快ï¼Âå 为åÂÂ
Ã¥ÂÂçÂÂ读åÂÂéÂÂ度æ¯Â硬çÂÂå¿«å¾Âå¤ÂãÂÂå½Âä¸Â次请æ±Âç¸åÂÂçÂÂèµÂæºÂæ¶ï¼ÂæµÂè§Âå¨ä¼Âé¦ÂÃ¥Â
Âæ£ÂæÂ¥åÂÂ
Ã¥ÂÂä¸ÂçÂÂç¼ÂÃ¥ÂÂï¼Âå¦ÂæÂÂç¼ÂÃ¥ÂÂÃ¥ÂÂå¨ä¸ÂæÂÂæÂÂï¼ÂÃ¥ÂÂç´æÂ¥ä»ÂÃ¥ÂÂ
Ã¥ÂÂä¸Â读åÂÂèµÂæºÂï¼Âæ éÂÂè¿Âè¡Âç½Âç»Â请æ±ÂãÂÂ
Memory cache
ç¸对äºÂDisk cacheæ¥说ï¼ÂÃ¥ÂÂå¨容éÂÂè¾Âå°Âï¼Âåªè½ç¼ÂÃ¥ÂÂè¾Âå°ÂçÂÂèµÂæºÂï¼Âä½Â访é®éÂÂ度éÂÂ常快ãÂÂ
éÂÂ常æ åµä¸Âï¼ÂæµÂè§Âå¨å¨æÂ¥æ¶å°èµÂæºÂÃ¥ÂÂä¼Âé¦Âå Âå°ÂèµÂæºÂÃ¥ÂÂå¨å¨å åÂÂç¼ÂÃ¥ÂÂä¸Âï¼Âè¿Âæ ·å¯以æÂÂä¾Âæ´快çÂÂ访é®éÂÂ度ãÂÂå¦ÂæÂÂå åÂÂç¼ÂÃ¥ÂÂ已满æÂÂèµÂæºÂéÂÂè¦Âé¿æÂÂä¿ÂÃ¥ÂÂï¼ÂæµÂè§Âå¨ä¼Âå°ÂèµÂæºÂÃ¥ÂÂå¨å¨ç£ÂçÂÂç¼ÂÃ¥ÂÂä¸Âï¼Â以便é¿æÂÂ使ç¨ãÂÂå½ÂæµÂè§Âå¨åÂÂ次请æ±Âç¸åÂÂçÂÂèµÂæºÂæ¶ï¼Âä¼Âæ ¹æ®ç¼ÂÃ¥ÂÂçÂÂçÂ¥é¦Âå Âæ£ÂæÂ¥å åÂÂç¼ÂÃ¥ÂÂï¼Âç¶åÂÂÃ¥ÂÂæ£ÂæÂ¥ç£ÂçÂÂç¼ÂÃ¥ÂÂï¼Â以æÂÂä¾Âæ´快çÂÂ访é®éÂÂ度åÂÂèÂÂçÂÂç½Âç»Â带宽ãÂÂ
ä»Âä¹Âæ¶åÂÂæµÂè§Âå¨ä¼Â使ç¨ disk cacheï¼Âä»Âä¹Âæ åµä¸Â使ç¨ memory cache å¢ï¼Â
æµÂè§Âå¨å¨ç¼ÂÃ¥ÂÂèµÂæºÂæ¶ï¼Âä¼Âæ ¹æ®ä¸ÂäºÂå 素æÂ¥å³å®Âæ¯使ç¨Disk cache
è¿Âæ¯Memory cache
ãÂÂ
-
Memory Cacheï¼Âå åÂÂç¼ÂÃ¥ÂÂï¼ÂçÂÂ使ç¨åºæ¯ï¼Â
- éÂÂæÂÂèµÂæºÂï¼ÂéÂÂ常æ åµä¸Âï¼ÂæµÂè§Âå¨ä¼Âä¼Âå Âå°ÂéÂÂæÂÂèµÂæºÂï¼Âå¦ÂCSSãÂÂJavaScriptãÂÂå¾çÂÂçÂÂï¼ÂÃ¥ÂÂå¨å¨å åÂÂç¼ÂÃ¥ÂÂä¸Âï¼Â以æÂÂä¾Âæ´快çÂÂ访é®éÂÂ度ãÂÂè¿Âæ¯å 为å åÂÂçÂÂ读åÂÂéÂÂ度æ¯Â硬çÂÂå¿«å¾Âå¤Âï¼Âå¯以快éÂÂÃ¥ÂÂåºÂèµÂæºÂ请æ±ÂãÂÂ
- 常ç¨èµÂæºÂï¼Âç»Â常被访é®çÂÂèµÂæºÂä¼Â被åÂÂå¨å¨å åÂÂç¼ÂÃ¥ÂÂä¸Âï¼Â以åÂÂå°Â对ç½Âç»ÂçÂÂä¾ÂèµÂï¼ÂæÂÂé«Âç¨æ·ä½ÂéªÂãÂÂ
- çÂÂæÂÂç¼ÂÃ¥ÂÂï¼Âä¸ÂäºÂå ·æÂÂçÂÂæÂÂæÂÂæÂÂæ§çÂÂèµÂæºÂï¼Âæ¯Âå¦ÂéÂÂè¿ÂAjaxå¨æÂÂè·åÂÂçÂÂæ°æ®ï¼ÂéÂÂ常ä¼Â被åÂÂå¨å¨å åÂÂç¼ÂÃ¥ÂÂä¸Âï¼Â以便快éÂÂè·åÂÂæÂÂæ°çÂÂæ°æ®ãÂÂ
-
Disk Cacheï¼Âç£ÂçÂÂç¼ÂÃ¥ÂÂï¼ÂçÂÂ使ç¨åºæ¯ï¼Â
- 大åÂÂèµÂæºÂï¼Âè¾Â大çÂÂèµÂæºÂæÂÂ件ï¼Âå¦Âè§Âé¢ÂãÂÂé³é¢ÂçÂÂï¼ÂéÂÂ常ä¼Â被åÂÂå¨å¨ç£ÂçÂÂç¼ÂÃ¥ÂÂä¸ÂãÂÂç±äºÂå åÂÂ容éÂÂæÂÂéÂÂï¼Âå åÂÂç¼ÂÃ¥ÂÂä¸ÂéÂÂÃ¥ÂÂÃ¥ÂÂå¨大åÂÂèµÂæºÂï¼Âå æ¤æµÂè§Âå¨ä¼Âå°Âè¿ÂäºÂèµÂæºÂä¿ÂÃ¥ÂÂå¨ç£ÂçÂÂä¸Âï¼Â以便é¿æÂÂ使ç¨ãÂÂ
- æÂÂä¹ ç¼ÂÃ¥ÂÂï¼Âä¸ÂäºÂå ·æÂÂé¿æÂÂæÂÂæÂÂæ§çÂÂèµÂæºÂï¼Âå¦Â页é¢çÂÂéÂÂæÂÂèµÂæºÂæÂÂ件ï¼Âå¦ÂCSSãÂÂJavaScriptãÂÂå¾çÂÂçÂÂï¼Âï¼ÂéÂÂ常ä¼Â被åÂÂå¨å¨ç£ÂçÂÂç¼ÂÃ¥ÂÂä¸ÂãÂÂè¿Âæ ·å¯以é¿å Âæ¯Â次é½éÂÂæ°ä¸Âè½½èµÂæºÂï¼ÂÃ¥ÂÂå°Âç½Âç»Â请æ±ÂÃ¥ÂÂå 快页é¢å 载éÂÂ度ãÂÂ
æµÂè§Âå¨ä¹Âå¯以根æ®ç¨æ·çÂÂé Âç½®åÂÂç¼ÂÃ¥ÂÂçÂÂçÂ¥æÂ¥å³å®Âæ¯å¦使ç¨ç¼ÂÃ¥ÂÂ以åÂÂç¼ÂÃ¥ÂÂçÂÂÃ¥ÂÂå¨ä½Âç½®ï¼Âå åÂÂç¼ÂÃ¥ÂÂæÂÂç£ÂçÂÂç¼ÂÃ¥ÂÂï¼ÂãÂÂ
ç¼ÂÃ¥ÂÂæ¯å¦失æÂÂï¼Âå¦Âä½ÂéªÂè¯Âï¼Â
ç¼ÂÃ¥ÂÂæ¯å¦已ç»Â失æÂÂæ¯ç±æµÂè§Âå¨根æ®ä¸ÂäºÂè§ÂÃ¥ÂÂÃ¥ÂÂçÂÂçÂ¥è¿Âè¡Âå¤æÂÂçÂÂãÂÂ以ä¸Âæ¯ä¸ÂäºÂ常è§ÂçÂÂå¤æÂÂä¾Âæ®ï¼Â
- ç¼ÂÃ¥ÂÂæ Âè¯Â符ï¼ÂæµÂè§Âå¨éÂÂè¿Âæ£Âæ¥请æ±Âä¸ÂçÂÂç¼ÂÃ¥ÂÂæ Âè¯Â符æÂ¥å¤æÂÂç¼ÂÃ¥ÂÂæ¯å¦æÂÂæÂÂãÂÂ常è§ÂçÂÂç¼ÂÃ¥ÂÂæ Âè¯Â符æÂÂ
ETag
Ã¥ÂÂLast-Modified
ãÂÂå½ÂæÂÂå¡å¨è¿ÂÃ¥ÂÂÃ¥ÂÂåºÂæ¶ï¼Âä¼Âå å«ä¸Â个æÂÂå¤Â个ç¼ÂÃ¥ÂÂæ Âè¯Â符ï¼ÂæµÂè§Âå¨ä¼Âå°Âè¿ÂäºÂæ Âè¯Â符åÂÂå¨起æÂ¥ãÂÂä¸Â次请æ±Âç¸åÂÂèµÂæºÂæ¶ï¼ÂæµÂè§Âå¨ä¼Âå°Âç¼ÂÃ¥ÂÂæ Âè¯Â符带ä¸Âï¼ÂæÂÂå¡å¨根æ®è¿ÂäºÂæ Âè¯Â符å¤æÂÂèµÂæºÂæ¯å¦åÂÂçÂÂäºÂÃ¥ÂÂÃ¥ÂÂãÂÂå¦ÂæÂÂèµÂæºÂ没æÂÂÃ¥ÂÂÃ¥ÂÂï¼ÂæÂÂå¡å¨å¯以è¿ÂÃ¥ÂÂä¸Â个304 Not Modified
çÂÂÃ¥ÂÂåºÂï¼ÂÃ¥ÂÂçÂ¥æµÂè§Âå¨使ç¨ç¼ÂÃ¥ÂÂå¯æ‹ - ç¼ÂÃ¥ÂÂæ§å¶æÂÂ令ï¼ÂÃ¥ÂÂåºÂ头é¨ä¸ÂçÂÂç¼ÂÃ¥ÂÂæ§å¶æÂÂ令ï¼Âå¦Â
Cache-Control
Ã¥ÂÂExpires
ï¼ÂæÂÂä¾ÂäºÂå ³äºÂç¼ÂÃ¥ÂÂçÂÂçÂÂçÂ¥åÂÂè¿ÂæÂÂæ¶é´ãÂÂæµÂè§Âå¨ä¼Âæ ¹æ®è¿ÂäºÂæÂÂ令æÂ¥å¤æÂÂç¼ÂÃ¥ÂÂæ¯å¦è¿ÂæÂÂãÂÂå¦ÂæÂÂç¼ÂÃ¥ÂÂçÂÂè¿ÂæÂÂæ¶é´å°Âæªå°达ï¼Âä¸Âç¼ÂÃ¥ÂÂæ§å¶æÂÂ令å Â许使ç¨ç¼ÂÃ¥ÂÂï¼ÂæµÂè§Âå¨å°Â使ç¨ç¼ÂÃ¥ÂÂçÂÂå¯æ‹ - éÂÂæ°éªÂè¯Âæºå¶ï¼ÂæµÂè§Âå¨å¯以éÂÂè¿ÂÃ¥ÂÂéÂÂä¸Â个æ¡件请æ±ÂæÂ¥éªÂè¯Âç¼ÂÃ¥ÂÂæ¯å¦ä»Âç¶æÂÂæÂÂãÂÂè¿Âç§ÂéªÂè¯ÂéÂÂ常使ç¨
If-None-Match
Ã¥ÂÂIf-Modified-Since
çÂÂæ¡件头é¨åÂÂ段ãÂÂæÂÂå¡å¨å¯以根æ®è¿ÂäºÂæ¡件åÂÂ段å¤æÂÂèµÂæºÂæ¯å¦åÂÂçÂÂäºÂÃ¥ÂÂÃ¥ÂÂï¼Âå¦ÂæÂÂ没æÂÂÃ¥ÂÂÃ¥ÂÂï¼Âå¯以è¿ÂÃ¥ÂÂä¸Â个304 Not Modified
çÂÂÃ¥ÂÂåºÂï¼ÂæµÂè§Âå¨继ç»Â使ç¨ç¼ÂÃ¥ÂÂå¯æ‹ÂÂ
请注æÂÂï¼ÂæµÂè§Âå¨对ç¼ÂÃ¥ÂÂçÂÂå¤ÂçÂÂæ¯åºäºÂä¸Âç³»åÂÂè§ÂèÂÂÃ¥ÂÂçÂÂçÂ¥çÂÂï¼Âå ·ä½ÂçÂÂå¤æÂÂä¾Âæ®å¯è½ä¼Âå æµÂè§Âå¨çÂÂå®Âç°åÂÂé Âç½®èÂÂæÂÂæÂÂä¸ÂÃ¥ÂÂãÂÂå¦ÂæÂÂæ¨æ³è¦Â详ç»ÂäºÂ解ç¹å®ÂæµÂè§Âå¨çÂÂç¼ÂÃ¥ÂÂæºå¶åÂÂè¡Â为ï¼Âå¯以åÂÂèÂÂç¸堳æµÂè§Âå¨çÂÂæÂÂæ¡£åÂÂè§ÂèÂÂãÂÂ
ETag & Last-Modified éªÂè¯Â头
è½ç¶æÂÂ们设置亠cache-control ç max-age å¼ï¼Âä½Âæ¯æÂÂæ³è¦Âæ¯Â次åÂÂéÂÂ请æ±Âé½æ³è¦ÂÃ¥ÂȾÂÂå¡å¨éªÂè¯Âï¼ÂåºÂ该æÂÂä¹ÂÃ¥ÂÂï¼Â
é£就åÂÂ设置àno-cache
ãÂÂ
res.writeHead(200, {
'Content-Type': 'text/javascript',
'Cache-Control': 'max-age=360000, no-cache',
})
为äºÂéªÂè¯Âæ¯å¦继ç»Â使ç¨ç¼ÂÃ¥ÂÂï¼ÂæÂÂ们å¨åÂÂåºÂ头ä¸Âå 丠Etag å Last-Modified è¿Â两个å±Âæ§
res.writeHead(200, {
'Content-Type': 'text/javascript',
'Cache-Control': 'max-age=10, no-cache',
'ETag': '123456789', // ä¸Âä¸Â次请æ±Âæ¶ï¼Â客æ·端ä¼Âå¨请æ±Â头å 丠If-None-Match: 123456789
'Last-Modified': '2023-05-27 21:30' // ä¸Âä¸Â次请æ±Âæ¶ï¼Â客æ·端ä¼Âå¨请æ±Â头å 丠If-Modified-Since: 2023-05-27 21:30
})
è¿Âæ¯以ä¸Âé¢çÂÂä¾ÂÃ¥ÂÂÃ¥ÂÂ示èÂÂï¼Âè½ç¶å 亠Etag å Last-Modified è¿Â两个å±Âæ§ï¼Âè¿Â没å®Âï¼Âè¿ÂéÂÂè¦Âå¨àæÂÂå¡端åÂÂæ ¡éªÂå¤æÂÂ
ï¼Â
// server.js
if (req.url === '/script.js') {
if (req.headers['if-none-match'] === '123456789' && req.headers['if-modified-since'] === '2023-05-27 21:30') {
res.writeHead(304)
// è¿Â段代ç Âä¸Âä¼ÂçÂÂæÂÂäºÂï¼Âå 为æµÂè§Âå¨ä¼Âä»Âç¼ÂÃ¥ÂÂè·åÂÂèµÂæºÂï¼Âæ§å¶å°è¿Âæ¯ä¼ÂæÂÂå° Javascript loaded!!!
res.end('console.log("æÂÂå¡å¨éªÂè¯Âå®Âæ¯Âï¼ÂÃ¥ÂÂæÂÂ客æ·端è·åÂÂç¼ÂÃ¥ÂÂèµÂæºÂ!!")')
} else {
res.writeHead(200, {
'Content-Type': 'text/javascript',
'Cache-Control': 'max-age=10, no-cache',
'ETag': '123456789',
'Last-Modified': '2023-05-27 21:30'
})
res.end('console.log("Javascript loaded!!!")')
}
}
æÂÂæÂÂå¦Âä¸Âï¼Â第ä¸Â次åÂÂèµ· 请æ±Âæ¶ï¼Âä¼Âä»ÂæÂÂå¡å¨è·åÂÂèµÂæºÂï¼ÂæÂ¥ä¸ÂæÂ¥å¦ÂæÂÂÃ¥ÂÂÃ¥ÂÂ起请æ±Âï¼Âå 为设置亠no-cache å ETag å Last-Modifiedï¼ÂæÂÂ以ä¼Âå¨æÂÂå¡å¨è¿Âè¡ÂèµÂæºÂæ¯å¦失æÂÂçÂÂæ ¡éªÂãÂÂ
å¦ÂæÂÂèµÂæºÂæª失æÂÂï¼ÂÃ¥ÂÂæÂÂå¡å¨è¿ÂÃ¥ÂÂç¶æÂÂç  304ï¼Â表示èµÂæºÂæª被修æ¹ï¼Âå¯以使ç¨ç¼ÂÃ¥ÂÂèµÂæºÂãÂÂ
注æÂÂï¼Âå¦ÂæÂÂå Chrome æµÂè§Âå¨éÂÂï¼Âå¾éÂÂäºÂàDisable cache
ï¼Â表示ä¸Â使ç¨ç¼ÂÃ¥ÂÂï¼Âé£习HTTP 请æ±Â头æ¯ä¸Âä¼Âæº带 if-none-match æ if-modified-since è¿ÂäºÂÃ¥Â
·æÂÂç¼ÂÃ¥ÂÂæÂÂä¹ÂçÂÂä¿¡æ¯äºÂ
Cookie
Cookieæ¯ä¸Âç§Âå¨WebæµÂè§Âå¨åÂÂWebæÂÂå¡å¨ä¹Âé´传éÂÂçÂÂå°ÂÃ¥ÂÂæÂÂæ¾ÂÂ件ï¼Âç¨äºÂÃ¥ÂÂå¨åÂÂä¼ éÂÂç¨æ·çÂÂç¸åÂ
³ä¿¡æ¯ãÂÂå®Âç±æÂÂå¡å¨
å¨HTTPÃ¥ÂÂåºÂ
çÂÂSet-Cookie
é¦Âé¨åÂÂ段ä¸ÂÃ¥ÂÂéÂÂç»ÂæµÂè§Âå¨ï¼Â并ç±æµÂè§Âå¨å¨åÂÂç»ÂçÂÂ请æ±Âä¸ÂéÂÂè¿ÂCookieé¦Âé¨åÂÂ段å°Â该信æ¯åÂÂéÂÂÃ¥ÂÂæÂÂå¡å¨ãÂÂ
Cookie主è¦Âç¨äºÂå®Âç°ä¼Âè¯Â管çÂÂÃ¥ÂÂç¨æ·è·Â踪ï¼Â以æÂÂä¾Â个æ§åÂÂçÂÂWebä½ÂéªÂãÂÂ
CookieçÂÂå·¥ä½ÂæµÂç¨Âå¦Âä¸Âï¼Â
- å½ÂæµÂè§Âå¨åÂÂæÂÂå¡å¨åÂÂéÂÂ请æ±Âæ¶ï¼ÂæÂÂå¡å¨å¯以å¨HTTPÃ¥ÂÂåºÂä¸ÂéÂÂè¿ÂSet-Cookieé¦Âé¨åÂÂ段å°Âä¸Â个æÂÂå¤Â个CookieÃ¥ÂÂéÂÂç»ÂæµÂè§Âå¨ãÂÂ
- æµÂè§Âå¨æ¶å°CookieÃ¥ÂÂï¼Âå°Âå ¶åÂÂå¨å¨æΡçÂÂCookieÃ¥ÂÂå¨ä¸ÂãÂÂ
- å½ÂæµÂè§Âå¨åÂÂÃ¥ÂÂä¸ÂæÂÂå¡å¨åÂÂéÂÂÃ¥ÂÂç»Â请æ±Âæ¶ï¼Âä¼Âå¨HTTP请æ±ÂçÂÂCookieé¦Âé¨åÂÂ段ä¸Âæº带ç¸åºÂçÂÂCookieæ°æ®ãÂÂ
- æÂÂå¡å¨æ¶å°请æ±ÂÃ¥ÂÂï¼Âå¯以解æÂÂCookieæ°æ®并根æ®堶ä¸ÂçÂÂä¿¡æ¯æÂ¥æ§è¡Âç¸åºÂçÂÂæÂÂä½Âï¼Âå¦Âè¯Âå«ç¨æ·ãÂÂä¿ÂæÂÂä¼Âè¯Âç¶æÂÂçÂÂãÂÂ
å½ÂæÂÂå¡å¨éÂÂè¿ÂHTTPÃ¥ÂÂåºÂçÂÂSet-Cookieé¦Âé¨åÂÂ段åÂÂéÂÂCookieæ¶ï¼Âå¯以设置å¤Â个Cookie项ï¼Âæ¯Â个项使ç¨é®å¼对çÂÂå½¢å¼Â表示ãÂÂä¸Âé¢æ¯ä¸Â个示ä¾Âï¼Â
HTTP/1.1 200 OK
Set-Cookie: username=johndoe; Expires=Wed, 21 Oct 2023 07:28:00 GMT; Path=/; Secure; HttpOnly
Set-Cookie: language=en-US; Path=/
Set-Cookie: theme=dark; Expires=Wed, 21 Oct 2023 07:28:00 GMT; Path=/
å¨ä¸Âé¢çÂÂ示ä¾Âä¸Âï¼ÂæÂÂå¡å¨åÂÂéÂÂäºÂä¸Â个Cookie项ï¼Â
username=johndoe
ï¼Â设置äºÂä¸Â个åÂÂ为username
çÂÂCookieï¼Âå ¶å¼为johndoe
ãÂÂlanguage=en-US
ï¼Â设置äºÂä¸Â个åÂÂ为language
çÂÂCookieï¼Âå ¶å¼为en-US
ãÂÂtheme=dark
ï¼Â设置äºÂä¸Â个åÂÂ为theme
çÂÂCookieï¼Âå ¶å¼为dark
ãÂÂ
æ¯Â个Cookie项å¯以éÂÂ带ä¸ÂäºÂå¯éÂÂçÂÂå±Âæ§ï¼Âå¦ÂExpires
ãÂÂPath
ãÂÂSecure
Ã¥ÂÂHttpOnly
çÂÂãÂÂ
Expires
å±Âæ§æÂÂå®ÂäºÂCookieçÂÂè¿ÂæÂÂæ¶é´ï¼ÂæµÂè§Âå¨å°Âå¨è¿ÂæÂÂæ¶é´ä¹ÂÃ¥ÂÂå é¤该CookieãÂÂå¨ä¸Âé¢çÂÂ示ä¾Âä¸Âï¼Âusername
Ã¥ÂÂtheme
çÂÂCookieé½设置äºÂè¿ÂæÂÂæ¶é´为Wed, 21 Oct 2023 07:28:00 GMT
ãÂÂMax-Age
àå±Âæ§æÂÂå®ÂäºÂCookieçÂÂæÂÂ大åÂÂæ´»æ¶é´ï¼Â以ç§Â为åÂÂä½ÂãÂÂå®Â表示ä»Âå½ÂÃ¥ÂÂæ¶é´å¼Âå§Âï¼ÂCookieå°Âå¨å¤Âå°Âç§ÂÃ¥ÂÂè¿ÂæÂÂãÂÂPath
å±Âæ§æÂÂå®ÂäºÂCookieçÂÂæÂÂæÂÂè·¯å¾Âï¼Âå³åªæÂÂå¨æÂÂå®Âè·¯å¾Âä¸ÂçÂÂ请æ±ÂæÂÂä¼Âæº带该CookieãÂÂå¨ä¸Âé¢çÂÂ示ä¾Âä¸Âï¼Âusername
Ã¥ÂÂlanguage
çÂÂCookieçÂÂè·¯å¾ÂÃ¥ÂÂå«为根路å¾Â/
Ã¥ÂÂé»Â认路å¾Â/
ãÂÂSecure
å±Âæ§æÂÂ示æµÂè§Âå¨仠å¨éÂÂè¿Âå®Âå ¨è¿ÂæÂ¥ï¼Âå¦ÂHTTPSï¼ÂÃ¥ÂÂéÂÂ请æ±Âæ¶æÂÂä¼Âæº带该CookieãÂÂHttpOnly
å±Âæ§æÂÂå®ÂäºÂ该Cookieæ¯å¦åªè½éÂÂè¿ÂHTTPÃ¥ÂÂ议访é®ï¼ÂèÂÂä¸Âè½éÂÂè¿ÂJavaScript代ç Â访é®(document.cookie)
ãÂÂè¿Âå¯以æÂÂé«Âå®Âå ¨æ§ï¼Âé²æ¢跨ç«ÂèÂÂæ¾ÂȌ»ï¼ÂXSSï¼ÂãÂÂ
注æÂÂï¼ÂæµÂè§Âå¨å¨åÂÂç»ÂçÂÂ请æ±Âä¸Âä¼Âèªå¨å¨Cookieé¦Âé¨åÂÂ段ä¸Âæº带ç¸åºÂçÂÂCookieæ°æ®ï¼Âæ éÂÂæÂÂå¨添å ãÂÂæÂÂå¡å¨å¯以éÂÂè¿Â解æÂÂCookieé¦Âé¨åÂÂ段æÂ¥è·åÂÂ客æ·端åÂÂéÂÂçÂÂCookieä¿¡æ¯ãÂÂ
res.writeHead(200, {
'Content-Type': 'text/javascript',
'Set-Cookie': 'age=18'
})
æÂ¥ç network:
// 第ä¸Â次åÂÂåºÂ头
Set-Cookie: age=18
// 第äºÂ次请æ±Â头
Cookie: age=18
设置å¤Â个 Cookie'Set-Cookie': ['age=18', 'name=alex.cheng']
æÂ¥ç network:
// 第ä¸Â次åÂÂåºÂ头
Set-Cookie: age=18
Set-Cookie: name=alex.cheng
// 第äºÂ次请æ±Â头
Cookie: name=alex.cheng; age=18
æÂÂ们å¯以å¨æ§å¶å°çÂÂàApplicatioin
àä¸ÂæÂ¥ç cookieï¼ÂæÂÂå¡端éÂÂè¿Âàreq.headers.cookie
àè·åÂÂ请æ±Â头ä¸Âç cookieãÂÂ
cookie è¿ÂæÂÂæ¶é´
Expires å max-age é½å¯以设置è¿ÂæÂÂæ¶é´ï¼Âåªæ¯ max-age 设置起æÂ¥æ´ç®ÂÃ¥ÂÂæ¹便ãÂÂ
å¦ÂæÂÂ没æÂÂ设置è¿ÂæÂÂæ¶é´ï¼Â表示 cookie Ã¥ÂÂå¨äºÂàåÂÂè¯Â
àä¸Â(å¨ application ä¸Âæ¾示 session
)ï¼Â表示åÂ
³éÂÂå½ÂÃ¥ÂÂçªÂå£ï¼ÂÃ¥ÂÂÃ¥ÂÂéÂÂ请æ±Âï¼Âæ¯ä¸Âä¼Â带丠cookie çÂÂãÂÂ
以丠cookieä¸Âï¼Âage ä¼Âå¨ 5s Ã¥ÂÂè¿ÂæÂÂï¼Âä¹Âå°±æ¯说è¿Â亠5s Ã¥ÂÂÃ¥ÂÂ请æ±Âï¼Â请æ±Â头ä¸Âä¸Âä¼Âæº带 age ä¿¡æ¯äºÂãÂÂ
res.writeHead(200, {
'Content-Type': 'text/javascript',
'Set-Cookie': ['age=18; max-age=5', 'name=alex.cheng']
})
res.end('console.log("Javascript loaded!!!")')
Session
Sessionï¼Âä¼Âè¯Âï¼Âæ¯æÂÂå¨客æ·端ä¸ÂæÂÂå¡å¨ä¹Âé´建ç«ÂçÂÂä¸Âç§Âç¶æÂÂ管çÂÂæºå¶ãÂÂ
å®Âç¨äºÂè·Â踪åÂÂÃ¥ÂÂå¨ç¹å®Âç¨æ·å¨ä¸Â段æ¶é´å çÂÂç¸堳信æ¯ãÂÂå¨WebåºÂç¨ç¨ÂåºÂä¸Âï¼Âä¼Âè¯ÂéÂÂ常ç¨äºÂå¨ç¨æ·访é®ä¸ÂÃ¥ÂÂ页é¢æÂÂÃ¥ÂÂéÂÂ请æ±Âæ¶ä¿ÂæÂÂç¨æ·çÂÂ身份éªÂè¯Âç¶æÂÂÃ¥ÂÂå ¶ä»Âä¼Âè¯Âæ°æ®ãÂÂ
ä¹Âå°±æ¯说ï¼ÂæÂÂ们åªè¦Âè½å¨æÂÂå¡å¨å®Âä½Âå°ç¹å®ÂçÂÂç¨æ·ï¼Âç¶åÂÂæ¿å°对åºÂç cookie ä¿¡æ¯ï¼Âé£就æ¯ session çÂÂå®Âç°æ¹æ¡ÂãÂÂ
SessionçÂÂä¼Âç¹å æ¬ï¼Â
- å¯以åÂÂå¨åÂÂ管çÂÂç¨æ·çÂÂç¶æÂÂÃ¥ÂÂç¸堳æ°æ®ãÂÂ
- æÂÂä¾ÂäºÂ身份éªÂè¯ÂÃ¥ÂÂç¨æ·è·Â踪çÂÂæºå¶ãÂÂ
- å¯以ç¨äºÂ報享æ°æ®åÂÂä¸Âä¸ÂæÂÂä¿¡æ¯ï¼Â使å¾Âå¤Â个请æ±Âä¹Âé´å¯以報享æ°æ®ãÂÂ
éÂÂè¦Â注æÂÂçÂÂæ¯ï¼ÂSessionæºå¶ä¾ÂèµÂäºÂä¼Âè¯ÂIDçÂÂä¼ éÂÂÃ¥ÂÂÃ¥ÂÂå¨ãÂÂ常è§ÂçÂÂæ¹å¼Âæ¯使ç¨CookieæÂ¥åÂÂå¨ä¼Âè¯ÂIDï¼Âä½Âä¹Âå¯以éÂÂè¿Âå ¶ä»Âæ¹å¼Âï¼Âä¾Âå¦ÂURLÃ¥ÂÂæ°æÂÂéÂÂèÂÂ表åÂÂÃ¥ÂÂ段ï¼Âä¼ éÂÂä¼Âè¯ÂIDãÂÂæ¤å¤Âï¼Â为äºÂç¡®ä¿Âä¼Âè¯ÂçÂÂå®Âå ¨æ§ï¼ÂéÂÂè¦ÂéÂÂÃ¥ÂÂä¸ÂäºÂå®Âå ¨æªæ½ï¼Âä¾Âå¦Â使ç¨å å¯Âç®Âæ³Â对ä¼Âè¯ÂIDè¿Âè¡Âå å¯Âï¼ÂéÂÂå¶ä¼Âè¯ÂIDçÂÂæÂÂæÂÂæÂÂéÂÂçÂÂãÂÂ
const express = require('express');
const session = require('express-session');
const app = express();
// éÂ
Âç½®ä¼Âè¯Âä¸Âé´件
app.use(session({
secret: 'my-secret-key', // ç¨äºÂå å¯Âä¼Âè¯Âæ°æ®çÂÂå¯ÂéÂÂ¥
resave: false,
saveUninitialized: true
}));
app.get('/login', (req, res) => {
// å¨ä¼Âè¯Âä¸ÂÃ¥ÂÂå¨ç¨æ·信æ¯
req.session.username = 'john_doe';
req.session.isLoggedIn = true;
res.send('Login successful!');
});
app.get('/dashboard', (req, res) => {
// æ£ÂæÂ¥ä¼Âè¯Âä¸ÂçÂÂç¨æ·信æ¯
if (req.session.isLoggedIn) {
const username = req.session.username;
const sessionId = req.sessionID; // è·åÂÂä¼Âè¯ÂID
res.send(`Welcome to the dashboard, ${username}! Session ID: ${sessionId}`);
} else {
res.send('You need to login first!');
}
});
app.get('/logout', (req, res) => {
// éÂÂæ¯Âä¼Âè¯Â
req.session.destroy();
res.send('Logout successful!');
});
app.listen(3000, () => {
console.log('Server started on port 3000');
});
å¨ä¸Â述示ä¾Âä¸Âï¼Âæ¯Âå½Âç¨æ·ç»å½Âæ¶ï¼Âä¼Âå°Âç¨æ·信æ¯åÂÂå¨å¨ä¼Âè¯Âä¸ÂãÂÂå¨访é®/dashboardè·¯ç±æ¶ï¼Âå¯以éÂÂè¿Âreq.sessionIDè·åÂÂå½ÂÃ¥ÂÂä¼Âè¯ÂçÂÂå¯ä¸ÂIDï¼Â并ä¸Âç¨æ·信æ¯ä¸Âèµ·è¿ÂÃ¥ÂÂç»Âç¨æ·ãÂÂè¿Âæ ·ï¼Âä¸ÂÃ¥ÂÂç¨æ·å°Âå ·æÂÂä¸ÂÃ¥ÂÂçÂÂä¼Âè¯ÂIDï¼Âä»ÂèÂÂåºåÂÂä¸ÂÃ¥ÂÂçÂÂç¨æ·ãÂÂ
请注æÂÂï¼Âä¼Âè¯ÂIDçÂÂçÂÂæÂÂÃ¥ÂÂ管çÂÂéÂÂ常æ¯ç±ä¼Âè¯Âä¸Âé´件èªå¨å¤ÂçÂÂçÂÂï¼Âæ éÂÂæÂÂå¨æÂÂä½ÂãÂÂ
HTTP é¿è¿ÂæÂÂ¥
HTTPé¿è¿ÂæÂ¥ï¼ÂHTTP connectionàkeep-alive
ï¼Âæ¯ä¸Âç§Âæºå¶ï¼Âç¨äºÂå¨åÂÂ个TCPè¿ÂæÂ¥ä¸ÂÃ¥ÂÂéÂÂå¤Â个HTTP请æ±ÂÃ¥ÂÂÃ¥ÂÂåºÂ(æÂÂÃ¥Â
ÂÃ¥ÂÂ顺åºÂ
)ï¼ÂèÂÂä¸Âæ¯为æ¯Â个请æ±ÂÃ¥ÂÂÃ¥ÂÂåºÂé½建ç«Âä¸Â个æ°çÂÂTCPè¿ÂæÂ¥ãÂÂå¨传ç»ÂçÂÂHTTP请æ±Â-Ã¥ÂÂåºÂ模åÂÂä¸Âï¼Âæ¯Â个请æ±Âé½éÂÂè¦Â建ç«Âä¸Â个æ°çÂÂTCPè¿ÂæÂ¥ï¼Âå®ÂæÂÂ请æ±ÂÃ¥ÂÂç«Âå³åÂ
³éÂÂè¿ÂæÂ¥ãÂÂèÂÂ使ç¨é¿è¿ÂæÂ¥ï¼Âå¯以å¨åÂÂä¸Â个TCPè¿ÂæÂ¥ä¸ÂÃ¥ÂÂéÂÂå¤Â个请æ±Âï¼Â并å¨ä¸Â段æ¶é´åÂÂ
ä¿ÂæÂÂè¿ÂæÂ¥å¤ÂäºÂæÂÂå¼Âç¶æÂÂï¼Â以便å¨éÂÂè¦Âæ¶åÂÂéÂÂæ´å¤ÂçÂÂ请æ±ÂãÂÂ
使ç¨HTTPé¿è¿ÂæÂ¥å¯以带æ¥以ä¸Â好å¤Âï¼Â
- Ã¥ÂÂå°Âè¿Âæ¥建ç«ÂÃ¥ÂÂæÂÂå¼ÂçÂÂå¼ÂéÂÂï¼ÂTCPè¿ÂæÂ¥çÂÂ建ç«ÂÃ¥ÂÂæÂÂå¼ÂéÂÂè¦Âæ¶ÂèÂÂä¸Âå®ÂçÂÂæ¶é´åÂÂèµÂæºÂãÂÂ使ç¨é¿è¿ÂæÂ¥å¯以åÂÂå°Âè¿ÂäºÂå¼ÂéÂÂï¼ÂæÂÂé«Âæ§è½ãÂÂ
- Ã¥ÂÂå°Âç½Âç»ÂæÂ¥å¡Âï¼Âé¿è¿ÂæÂ¥å¯以åÂÂå°Âç½Âç»Âä¸ÂçÂÂè¿ÂæÂ¥æ°ï¼ÂÃ¥ÂÂè½»ç½Âç»ÂæÂ¥å¡ÂçÂÂç¨Â度ãÂÂ
- æÂÂé«ÂÃ¥ÂÂåºÂéÂÂ度ï¼Âç±äºÂä¸ÂéÂÂè¦Â为æ¯Â个请æ±Â建ç«Âæ°çÂÂè¿ÂæÂ¥ï¼Âå¯以æ´快å°åÂÂéÂÂ请æ±Â并æÂ¥æ¶åÂÂåºÂãÂÂ
- èÂÂçÂÂ带宽ï¼Âå¨é¿è¿ÂæÂ¥ä¸ÂÃ¥ÂÂéÂÂå¤Â个请æ±Âæ¶ï¼Âå¯以åÂÂå°Âé¢Âå¤ÂçÂÂTCPæ¡æÂÂÃ¥ÂÂé¦Âé¨信æ¯çÂÂä¼ è¾Âï¼ÂèÂÂçÂÂ带宽ãÂÂ
请注æÂÂï¼ÂHTTPé¿è¿Âæ¥并ä¸Âæ¯永ä¹Â
çÂÂè¿ÂæÂ¥ï¼ÂèÂÂæ¯å¨ä¸Âå®ÂçÂÂæ¶é´åÂÂ
ä¿ÂæÂÂæÂÂå¼Âç¶æÂÂãÂÂÃ¥Â
·ä½ÂçÂÂè¿ÂæÂ¥æ¶é´å¯以ç±æÂÂå¡å¨æÂÂ客æ·端è¿Âè¡ÂéÂ
Âç½®
ãÂÂå¦ÂæÂÂé¿æ¶é´没æÂÂæ´»å¨ï¼Âè¿ÂæÂ¥å¯è½ä¼Â被æÂÂå¡å¨æÂÂ客æ·端åÂ
³éÂÂãÂÂ
Chrome æµÂè§Âå¨å Â许并åÂÂå¤Âå°Â个 TCP è¿ÂæÂ¥ï¼Â
å¨ç°代ç Chrome æµÂè§Âå¨ä¸Âï¼Âé»Â认æÂÂ
åµä¸Âï¼Âæ¯Â个åÂÂÃ¥ÂÂÃ¥Â
Â许åÂÂæ¶建ç«ÂçÂÂæÂÂä¹Â
TCP è¿ÂæÂ¥æ°æ¯æÂÂéÂÂçÂÂï¼ÂÃ¥Â
·ä½ÂÃ¥ÂÂå³äºÂæµÂè§Âå¨çÂÂæÂŒÂÂæÂÂä½Âç³»ç»ÂãÂÂå¨è¿ÂÃ¥ÂȍÂÂçÂÂæ¬ä¸Âï¼Â该éÂÂå¶éÂÂ常为à6
à个 TCP è¿ÂæÂ¥ãÂÂç¶èÂÂï¼ÂéÂÂçÂÂæ¶é´çÂÂæ¨移åÂÂæµÂè§Âå¨çÂÂæ´æ°ï¼Âè¿Â个éÂÂå¶已ç»ÂæÂÂæÂÂæ¹åÂÂãÂÂ
æÂÂ们æÂ¥åÂÂ个ç®ÂÃ¥ÂÂçÂÂæ¼Â示:
æÂÂ们åÂÂå¤Âä¸Âå¼ å¾çÂÂï¼Âè¿ÂæÂÂ个 html æÂÂ件ï¼Âhtml ä¸Â请æ±Â亠7 å¼ å¾çÂÂ
// index.html
<body>
<h1>HTTP é¿è¿ÂæÂÂ¥ connection keep-alive</h1>
<img src="test.jpg1" />
<img src="test.jpg2" />
<img src="test.jpg3" />
<img src="test.jpg4" />
<img src="test.jpg5" />
<img src="test.jpg6" />
<img src="test.jpg7" />
</body>
Ã¥ÂÂÃ¥ÂÂ建ä¸Â个 http æÂÂå¡ï¼Âç¨æÂ¥å 载àindex.html
àæÂÂ件ï¼Â并å¤ÂçÂÂå¾çÂÂç¸åÂ
³çÂÂ请æ±Â
:
const http = require('http')
const fs = require('fs')
const server = http.createServer((req, res) => {
if (req.url === '/') {
const html = fs.readFileSync('index.html')
res.writeHead(200, {
'Content-Type': 'text/html'
})
res.end(html)
} else {
// 读åÂÂå¾çÂÂï¼Â并è¿ÂÃ¥ÂÂç»Â页é¢
const img = fs.readFileSync('tcp-connect.jpg')
res.writeHead(200, {
'Content-Type': 'iamge/jpg'
})
res.end(img)
}
})
server.listen(8888, () => {
console.log('server running at port 8888...')
})
ç¶åÂÂæÂÂ们å°Âç½ÂéÂÂè°ÂæÂ
¢ä¸Âç¹ï¼Âå·æ°æµÂè§Âå¨æÂ¥çÂÂç»ÂæÂÂï¼ÂæÂÂ们ä¼ÂÃ¥ÂÂç°ï¼Ânetwork ä¸Âæ 7 个åÂ
³äºÂå¾çÂÂç http 请æ±Âï¼ÂÃ¥Â
¶ä¸ÂæÂÂä¸Â个å±ÂäºÂàpendding
àç¶æÂÂï¼Âå½Âæ TCP è¿ÂæÂ¥æÂÂ空åºæÂ¥çÂÂäºÂï¼Âè¿ÂæÂ¥æ°é < 6
ï¼Âï¼ÂæÂÂä¼Âå 载å¤Â亠pendding ç¶æÂÂçÂÂ请æ±ÂãÂÂ
Connection ID
à表示å½Âå TCP è¿ÂæÂ¥ç IDï¼Âæ¯Â个 ID ä¸Âä¸Âæ ·ï¼Â表示åÂÂ建亠ä¸Âä¸Âæ ·ç TCP è¿ÂæÂ¥ãÂÂç±äºÂ使ç¨çÂÂæ¯é»Â认ç HTTP/1.1 Ã¥ÂÂè®®ï¼ÂæÂÂå¡å¨ä¼Âàèªå¨å¯ç¨é¿è¿ÂæÂÂ¥
ï¼Âå¯以å¨åÂÂä¸Â个è¿ÂæÂ¥ä¸Âå¤ÂçÂÂå¤Â个请æ±Âï¼ÂTCPè¿ÂæÂ¥å¤Âç¨
ï¼ÂãÂÂ
å½ÂæÂÂ们å°Âç½ÂéÂÂè°ÂÃ¥ÂÂæÂ¥ï¼ÂÃ¥ÂÂ次å·æ°页é¢ï¼Âä½ ä¼ÂÃ¥ÂÂç°æÂÂå¤Â个ç¸åÂÂçÂÂàConnection ID
ï¼Â表示 tcp è¿Âæ¥被å¤Âç¨äºÂãÂÂ
å¦ÂæÂÂæ³è¦ÂÃ¥Â
³éÂÂé¿è¿ÂæÂ¥ï¼Â设置àConnection: close
àå³å¯ï¼Â
res.writeHead(200, {
'Content-Type': 'iamge/jpg',
'Connection': 'close'
})
HTTP2 Ã¥ÂÂ个 TCP è¿ÂæÂÂ¥
HTTP/2
àä¸ÂÃ¥ÂÂ使ç¨å¤Â个 TCP è¿ÂæÂ¥æ¥并åÂÂä¼ è¾Âæ°æ®ï¼ÂèÂÂæ¯éÂÂè¿ÂÃ¥ÂÂ个 TCP è¿ÂæÂ¥è¿Âè¡Âå¤Âè·¯å¤Âç¨ãÂÂè¿ÂæÂÂå³çÂÂå¨ HTTP/2 ä¸Âï¼Âå¯以àå¨åÂÂ个è¿ÂæÂ¥ä¸ÂÃ¥ÂÂæ¶è¿Âè¡Âå¤Â个请æ±ÂÃ¥ÂÂÃ¥ÂÂåºÂ
ãÂÂ
HTTP/2 使ç¨äºÂäºÂè¿Âå¶åÂÂè®®ï¼Âå°Â请æ±ÂÃ¥ÂÂÃ¥ÂÂåºÂÃ¥ÂÂ解为æ´å°ÂçÂÂ帧ï¼Âframesï¼Âï¼Â并å¨ä¸Â个è¿ÂæÂ¥ä¸Â交éÂÂå°åÂÂéÂÂè¿ÂäºÂ帧ãÂÂæ¯Â个帧é½æÂÂä¸Â个å¯ä¸ÂçÂÂæ Âè¯Â符ï¼Âç¨äºÂå°ÂÃ¥Â
¶ä¸Âç¸åºÂçÂÂ请æ±ÂæÂÂÃ¥ÂÂåºÂÃ¥Â
³èÂÂèµ·æÂ¥ãÂÂè¿Âç§Âå¤Âè·¯å¤Âç¨çÂÂæºå¶åÂ
Â许åÂÂæ¶åÂÂéÂÂå¤Â个帧ï¼Âä»ÂèÂÂå®Âç°äºÂ并åÂÂä¼ è¾ÂãÂÂæÂÂé«ÂäºÂæ§è½åÂÂæÂÂçÂÂï¼Â并åÂÂå°ÂäºÂ延è¿ÂãÂÂ
æ°æ®åÂÂÃ¥ÂÂ
HTTP æ°æ®åÂÂÃ¥ÂÂï¼ÂHTTP Content Negotiationï¼Âæ¯æÂÂ客æ·端åÂÂæÂÂå¡å¨ä¹Âé´就请æ±ÂæÂÂÃ¥ÂÂåºÂä¸ÂçÂÂÃ¥ÂÂ
容è¿Âè¡ÂÃ¥ÂÂÃ¥ÂÂï¼Â以确å®ÂæÂÂÃ¥ÂÂéÂÂçÂÂÃ¥ÂÂ
容格å¼ÂãÂÂè¯Âè¨ÂãÂÂç¼Âç ÂçÂÂ
ãÂÂ
å¨ HTTP æ°æ®åÂÂÃ¥ÂÂä¸Âï¼Â客æ·端åÂÂéÂÂ请æ±Âæ¶ï¼Âå¯以éÂÂè¿Â请æ±Â头åÂÂ段æÂ¥æÂÂä¾Âä¸ÂäºÂå ³äºÂæÂÂæÂÂçÂÂå 容ç¹æ§çÂÂä¿¡æ¯ï¼Âä¾Â妠AcceptãÂÂAccept-LanguageãÂÂAccept-Encoding çÂÂãÂÂæÂÂå¡å¨æÂ¥æ¶å°请æ±ÂÃ¥ÂÂï¼Âå¯以根æ®è¿ÂäºÂ请æ±Â头åÂÂ段çÂÂå¼ï¼ÂéÂÂæ©æÂÂéÂÂÃ¥ÂÂ客æ·端çÂÂå 容è¿Âè¡ÂÃ¥ÂÂåºÂãÂÂ
HTTP æ°æ®åÂÂÃ¥ÂÂå¯以åÂÂ为两ç§Âç±»åÂÂï¼Â
æÂÂå¡å¨驱å¨çÂÂÃ¥ÂÂÃ¥ÂÂï¼ÂServer-driven Negotiationï¼Â
ï¼ÂæÂÂå¡å¨根æ®客æ·端çÂÂ请æ±Â头信æ¯ï¼Âä»ÂæÂÂä¾ÂçÂÂå¯éÂÂ项ä¸ÂéÂÂæ©æÂÂÃ¥ÂÂéÂÂçÂÂÃ¥ÂÂåºÂå 容ãÂÂæÂÂå¡å¨å¯以根æ®请æ±Â头ä¸Âç AcceptãÂÂAccept-LanguageãÂÂAccept-Encoding çÂÂÃ¥ÂÂ段è¿Âè¡ÂÃ¥ÂÂÃ¥ÂÂï¼Â并å¨åÂÂåºÂä¸Â使ç¨ Content-TypeãÂÂContent-LanguageãÂÂContent-Encoding çÂÂÃ¥ÂÂ段æÂ¥æÂÂ示æÂÂéÂÂå 容çÂÂç¹æ§ãÂÂ客æ·端驱å¨çÂÂÃ¥ÂÂÃ¥ÂÂï¼ÂClient-driven Negotiationï¼Â
ï¼Â客æ·端éÂÂè¿ÂÃ¥ÂÂæÂÂå¡å¨åÂÂéÂÂä¸Âç³»åÂÂå¯éÂÂ项ï¼Âå¦Â请æ±Â头ä¸Âç AcceptãÂÂAccept-LanguageãÂÂAccept-Encoding çÂÂÃ¥ÂÂ段ï¼ÂÃ¥ÂÂçÂ¥æÂÂå¡å¨èª己çÂÂé¦ÂéÂÂ项ãÂÂæÂÂå¡å¨根æ®è¿ÂäºÂé¦ÂéÂÂ项æÂ¥éÂÂæ©åÂÂéÂÂçÂÂÃ¥ÂÂåºÂå 容ï¼Â并å¨åÂÂåºÂä¸Â使ç¨ Content-TypeãÂÂContent-LanguageãÂÂContent-Encoding çÂÂÃ¥ÂÂ段æÂ¥æÂÂ示æÂÂéÂÂå 容çÂÂç¹æ§ãÂÂ
éÂÂè¿ HTTP æ°æ®åÂÂÃ¥ÂÂï¼Â客æ·端åÂÂæÂÂå¡å¨å¯以å¨请æ±ÂÃ¥ÂÂÃ¥ÂÂåºÂä¸Âè¿Âè¡Âå 容çÂÂçµ活åÂÂÃ¥ÂÂï¼Â以æÂÂä¾ÂæÂÂéÂÂÃ¥ÂÂçÂÂå 容ç»Â客æ·端ï¼Âä»ÂèÂÂæÂÂÃ¥ÂÂç¨æ·ä½ÂéªÂÃ¥ÂÂç½Âç»ÂæÂÂçÂÂãÂÂè¿Â使å¾Â客æ·端åÂÂæÂÂå¡å¨å¯以根æ®åÂÂèªçÂÂç¹æ§åÂÂéÂÂæ±Âè¿Âè¡Â交äºÂï¼Â并å¨å¯éÂÂ项ä¸ÂéÂÂæ©æÂÂä½³çÂÂå 容格å¼ÂãÂÂè¯Âè¨ÂãÂÂç¼Âç ÂçÂÂãÂÂ
éÂÂå®ÂÃ¥ÂÂ
å¨ HTTP ä¸Âï¼Âå¯以éÂÂè¿Â设置åÂÂåºÂç¶æÂÂç ÂÃ¥ÂÂÃ¥ÂÂåºÂ头æÂ¥å®Âç°éÂÂå®ÂÃ¥ÂÂãÂÂ
常è§ÂçÂÂéÂÂå®ÂÃ¥ÂÂç¶æÂÂç Âå æ¬ï¼Â
301
àMoved Permanentlyï¼Â永习éÂÂå®ÂÃ¥ÂÂï¼Â表示请æ±ÂçÂÂèµÂæºÂ已被永习移å¨å°æ°çÂÂä½Âç½®ãÂÂæµÂè§Âå¨ä¼Âèªå¨å°Â请æ±ÂçÂÂå°åÂÂæ´æ°为æ°çÂÂå°åÂÂï¼Âä¸Âä¼ÂÃ¥ÂÂÃ¥ÂÂéÂÂÃ¥ÂÂæÂ¥çÂÂ请æ±ÂäºÂï¼Âè¿Âæ¯å 302 çÂÂåºå«ï¼Â
ãÂÂ302
àFound / 307 Temporary Redirectï¼Â临æ¶éÂÂå®ÂÃ¥ÂÂï¼Â表示请æ±ÂçÂÂèµÂæºÂ临æ¶移å¨å°æ°çÂÂä½Âç½®ãÂÂæµÂè§Âå¨ä¼Â继ç»Âä¿ÂæÂÂÃ¥ÂÂå§Â请æ±ÂçÂÂæ¹æ³ÂÃ¥ÂÂ请æ±Âä½Âï¼Â并éÂÂå®ÂÃ¥ÂÂå°æ°çÂÂå°åÂÂãÂÂ303
àSee Otherï¼Â表示请æ±Â已被å¤ÂçÂÂï¼ÂåºÂ该跳转å°å¦ä¸Â个å°åÂÂãÂÂGET æ¹æ³Âç¨äºÂè·åÂÂéÂÂå®ÂÃ¥ÂÂÃ¥ÂÂçÂÂèµÂæºÂãÂÂ
å ·ä½ÂçÂÂéÂÂå®ÂÃ¥ÂÂæ¥骤å¦Âä¸Âï¼Â
-
æÂÂå¡å¨æ¶å°请æ±ÂÃ¥ÂÂï¼Âæ ¹æ®éÂÂè¦Âè¿Âè¡Âå¤ÂçÂÂï¼Â并å³å®Âæ¯å¦éÂÂè¦ÂéÂÂå®ÂÃ¥ÂÂãÂÂ
-
å¦ÂæÂÂéÂÂè¦ÂéÂÂå®ÂÃ¥ÂÂï¼ÂæÂÂå¡å¨设置åÂÂåºÂç¶æÂÂç Â为éÂÂå½ÂçÂÂéÂÂå®ÂÃ¥ÂÂç¶æÂÂç Âï¼Â妠301ãÂÂ302ãÂÂ307 æ 303ï¼ÂãÂÂï¼Âå ³é®ï¼Â
-
æÂÂå¡å¨
å¨åÂÂåºÂ头ä¸Â设置 Location Ã¥ÂÂ段ï¼ÂæÂÂå®ÂéÂÂå®ÂÃ¥ÂÂçÂÂç®栠URLãÂÂ
ï¼Âå ³é®@-
客æ·端ï¼ÂéÂÂ常æ¯æµÂè§Âå¨ï¼Âæ¶å°åÂÂåºÂÃ¥ÂÂï¼Âä¼Âæ ¹æ®åÂÂåºÂç¶æÂÂç Âè¿Âè¡Âç¸åºÂå¤ÂçÂÂãÂÂ
- 对äºÂ永习éÂÂå®ÂÃ¥ÂÂï¼Â301ï¼Âï¼Â客æ·端ä¼Âå°Â请æ±ÂçÂÂå°åÂÂæ´æ°为æ°çÂÂå°åÂÂï¼Â并å°Âä¹ÂÃ¥ÂÂçÂÂ请æ±ÂÃ¥ÂÂéÂÂå°æ°çÂÂå°åÂÂãÂÂ
- 对äºÂ临æ¶éÂÂå®ÂÃ¥ÂÂï¼Â302ãÂÂ307ï¼ÂÃ¥ÂÂæÂ¥çÂÂå ¶ä»Âï¼Â303ï¼Âï¼Â客æ·端ä¼Âæ ¹æ®åÂÂåºÂ头ä¸Âç Location Ã¥ÂÂ段éÂÂæ°åÂÂéÂÂ请æ±Âå°æ°çÂÂå°åÂÂãÂÂ
- 对äºÂå ¶ä»Âç¶æÂÂç Âï¼Â客æ·端ä¼Âæ ¹æ®堷ä½Âæ åÂ抨Âè¡Âå¤ÂçÂÂãÂÂ
以ä¸Âæ¯ä¸Â个示ä¾Âï¼Â使ç¨ Node.js ä¸ÂçÂÂàhttp
à模åÂÂå®Âç°éÂÂå®ÂÃ¥ÂÂï¼Â
const http = require('http');
const server = http.createServer((req, res) => {
// éÂÂå®ÂÃ¥ÂÂå°æ°çÂÂèµÂ溠http://localhost:8000/new
if (req.url === '/') {
res.writeHead(302, { 'Location': '/new' });
res.end();
}
if (req.url === '/new') {
res.writeHead(200, {
'Content-Type': 'text/html'
});
res.end('<h1>New Page</h1>');
}
});
server.listen(8000, () => {
console.log('Server running at http://localhost:8000/');
});
ä¸Â述示ä¾Âä¸Âï¼Âå½Â客æ·端访é®æÂÂå¡å¨æ¶ï¼ÂæÂÂå¡å¨ä¼Âè¿Âå 302 ç¶æÂÂç ÂÃ¥ÂÂàLocation
à头åÂÂ段ï¼Âå°Â客æ·端éÂÂå®ÂÃ¥ÂÂå°àhttp://localhost:8000/new
àå°åÂÂãÂÂ
301 å 302 å¨æµÂè§Âå¨ä¸Â表ç°åºæÂ¥çÂÂåºå«
æÂÂ大çÂÂåºå«就æ¯ï¼Âæ¯å¦ä¿ÂçÂÂÃ¥ÂÂæÂ¥çÂÂHTTP请æ±Â
æÂÂ们å¨æÂÂå¡端æÂÂå°àreq.url
ï¼ÂÃ¥ÂÂæ¶è§Â寠network ä¸Âç http 请æ±Â:
// server.js
// 302
// console.log(req.url)
/
/new
/favicon.ico
302 ä¿ÂçÂÂäºÂà根路å¾Â
àçÂÂ请æ±Âï¼Â没ä¸Â次访é®àhttp://localhost:8888/
ï¼ÂæÂÂå¡端é½ä¼ÂæÂÂå°åºà/
àåÂÂà/new
// server.js
// 301
// console.log(req.url)
/new
/favicon.ico
302 ä¸Âä¼Âä¿ÂçÂÂ根路å¾ÂçÂÂ请æ±ÂäºÂï¼Âä» network å¯以çÂÂåºï¼Âhttp://localhost:8888/
à请æ±Âæ¯ä»Âàdisk cache
àè·åÂÂçÂÂï¼Â表示永ä¹Â
æ§éÂÂå®ÂÃ¥ÂÂï¼ÂæÂÂ以àreq.url = '/'
ä¸Âä¼ÂÃ¥ÂÂèµ°å°æÂÂå¡端ãÂÂ
注æÂÂï¼Âå¦ÂæÂÂæÂÂ们设置äºÂà301
à永ä¹Â
éÂÂå®ÂÃ¥ÂÂï¼ÂÃ¥ÂÂç»ÂÃ¥ÂÂä¿®æ¹æÂÂå¡å¨çÂÂç¶æÂÂï¼Âæ¤æ¶æµÂè§Âå¨è¿Âè¾¹æ¯æ æ³ÂçÂ¥éÂÂçÂÂï¼Âä¾Âç¶ä¼Â使ç¨à301
à永ä¹Â
éÂÂå®ÂÃ¥ÂÂï¼Âä¹Âå°±æ¯说ï¼Âå¦ÂæÂÂç¨æ·ä¸ÂæÂÂå¨æ¸Â
çÂÂæµÂè§Âå¨ç¼ÂÃ¥ÂÂï¼Âé£ä¹Âå°±æ æ³Âæ¿å°æÂÂæ°çÂÂæÂÂå¡å¨èµÂæºÂãÂÂæÂÂ以使ç¨ÃÂ
301àç¶æÂÂç Âè¦ÂéÂÂ常谨æÂ
Âï¼Â
HTTP Content Security Policy (CSP)
ä¸Âç§Âç¨äºÂå¢Â强ç½Â页å®Âå ¨æ§ç HTTP 头é¨åÂÂ段ãÂÂ
å®ÂÃ¥Â
Â许ç½Âç«Â管çÂÂÃ¥ÂÂàæ§å¶ç½Â页ä¸Âè½å¤Âæ§è¡ÂçÂÂÃ¥ÂÂ
容æºÂÃ¥ÂÂæÂÂä½Â
ï¼Â以åÂÂå°Âæ¶æÂÂèÂÂæ¬注åÂ
¥ãÂÂè·¨ç«Âç¹èÂÂæ¾ÂȌ»ï¼ÂXSSï¼ÂçÂÂå®ÂÃ¥Â
¨å¨ÂèÂÂãÂÂ
Content Security Policy éÂÂè¿Âå®Âä¹Âä¸Âç³»åÂÂçÂÂçÂÂçÂ¥è§ÂÃ¥ÂÂï¼ÂéÂÂå¶ç½Â页ä¸Âå¯å 载çÂÂèµÂæºÂÃ¥ÂÂå¯æ§è¡ÂçÂÂæÂÂä½Â
ãÂÂè¿ÂäºÂè§ÂÃ¥ÂÂå¯以åÂÂ
æÂŒÂ
Â许çÂÂÃ¥ÂÂÃ¥ÂÂãÂÂÃ¥Â
Â许çÂÂèÂÂæ¾¥æºÂãÂÂÃ¥Â
Â许çÂÂæ ·å¼ÂæÂ¥æºÂãÂÂÃ¥Â
Â许çÂÂå¾åÂÂæÂ¥æºÂçÂÂãÂÂéÂÂè¿ÂéÂÂå¶è¿ÂäºÂèµÂæºÂçÂÂæÂ¥æºÂï¼ÂCSP å¯以æÂÂæÂÂé²æ¢æ¶æÂÂ代ç Â注åÂ
¥åÂÂÃ¥Â
¶ä»Âå®ÂÃ¥Â
¨æ¼Âæ´ÂãÂÂ
CSP çÂÂè§ÂÃ¥ÂÂå¯以éÂÂè¿ HTTP 头é¨åÂÂ段àContent-Security-Policy
àæÂÂàContent-Security-Policy-Report-Only
àæ¥设置ãÂÂÃ¥Â
¶ä¸Âï¼ÂContent-Security-Policy
àæ¯æÂÂå®Âå®ÂéÂÂ
æ§è¡ÂçÂÂçÂÂçÂ¥ï¼ÂèÂÂàContent-Security-Policy-Report-Only
àåÂÂåªç¨äºÂæÂ¥åÂÂè¿Âè§ÂæÂÂ
Ã¥Â括Âä¸Âä¼ÂéÂȾ¢èµÂæºÂå 载åÂÂæ§è¡ÂãÂÂ
以ä¸Âæ¯ä¸Â个示ä¾Âï¼Âå±Â示å¦Âä½Â使ç¨ CSP 头é¨åÂÂ段ï¼Â
Content-Security-Policy: default-src 'self'; script-src 'self' https://example.com; style-src 'self' 'unsafe-inline'
ä¸Â述示ä¾Âä¸Âï¼ÂCSP è§ÂÃ¥ÂÂå æ¬ï¼Â
default-src 'self'
ï¼Âé»Â认çÂÂçÂ¥è¦Âæ±ÂæÂÂæÂÂèµÂæºÂä»Âå½ÂÃ¥ÂÂÃ¥ÂÂÃ¥ÂÂ
å 载ãÂÂscript-src 'self' https://example.com
ï¼ÂæÂÂå®ÂèÂÂæλè½ä»Âå½ÂÃ¥ÂÂÃ¥ÂÂÃ¥ÂÂÃ¥ÂÂÃÂhttps://example.com
àå 载ãÂÂstyle-src 'self' 'unsafe-inline'
ï¼ÂæÂÂå®Âæ ·å¼Âåªè½ä»Âå½ÂÃ¥ÂÂÃ¥ÂÂÃ¥ÂÂå 载ï¼Âä½Âå Â许å èÂÂæ ·å¼Âï¼Â'unsafe-inline'
ï¼ÂãÂÂ
éÂÂè¿Âé Âç½®éÂÂå½Âç CSP è§ÂÃ¥ÂÂï¼Âç½Âç«Â管çÂÂÃ¥ÂÂå¯以éÂÂå¶ç½Â页ä¸ÂçÂÂèµÂæºÂÃ¥ÂÂæÂÂä½Âï¼Âä»ÂèÂÂÃ¥ÂÂå°Âæ½Âå¨çÂÂå®Âå ¨é£Âé©ãÂÂ
示ä¾Â
æÂÂ们å¨ html ä¸Âï¼Âå 载ä¸Âå¼ å¤Âç½ÂçÂÂå¾çÂÂï¼ÂÃ¥ÂÂæ¶æÂÂå¡端设置 CSPàdefault-src self
ï¼ÂçÂÂçÂÂä¼ÂæÂÂä»Âä¹ÂæÂÂæÂÂ
éÂÂ便æ¾张å¾çÂÂ
<img src="http://www.fangfa.net/public/uploads/ueditor/images/20141111/14156729795697.png" />
const http = require('http')
const fs = require('fs')
const server = http.createServer((req, res) => {
if (req.url === '/') {
res.writeHead(200, {
'Content-Type': 'text/html',
'Content-Security-Policy': "default-src self" // 设置 CSPï¼ÂæÂÂæÂÂçÂÂ请æ±Âåªè½å 载æÂŒÂÂÃ¥ÂÂä¸ÂçÂÂèµÂæºÂ
})
const html = fs.readFileSync('index.html')
res.end(html)
}
})
server.listen(8888, () => {
console.log('server running at port 8888...')
})
å·æ°页é¢åÂÂï¼ÂÃ¥ÂÂç°å¾çÂÂ没åºæÂ¥ï¼Âæ§å¶å°è¿ÂæÂ¥éÂÂäºÂ
Refused to load the image 'http://www.fangfa.net/public/uploads/ueditor/images/20141111/14156729795697.png' because it violates the following Content Security Policy directive: "default-src self". Note that 'img-src' was not explicitly set, so 'default-src' is used as a fallback.
åºç°亠CSP éÂÂ误ï¼Âå¦Âä½ÂæÂ¥åÂÂéÂÂ误ï¼Â
éÂ
Â置àreport-uri /report
'Content-Security-Policy': "default-src 'self'; report-uri /report"
设置æÂ¥åÂÂéÂÂ误åÂÂï¼Ânetwork ä¸Âå°±ä¼Âåºç°à/report
àç http 请æ±ÂãÂÂ
{
"csp-report": {
"document-uri": "http://localhost:8888/",
"referrer": "",
"violated-directive": "style-src-elem",
"effective-directive": "style-src-elem",
"original-policy": "default-src 'self'; report-uri /report",
"disposition": "enforce",
"blocked-uri": "inline",
"line-number": 9,
"source-file": "http://localhost:8888/",
"status-code": 200,
"script-sample": ""
}
}
meta æ Âç¾ä¹Âå¯以é Âç½® CSP
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; img-src https://*; child-src 'none';" />
ä¸Âè¿ meta æ Âç¾ä¸Âè½éÂ
Â置àreport-uri
ï¼ÂæÂÂ以æÂÂ好è¿Âæ¯éÂÂè¿ http çÂÂÃ¥ÂÂåºÂ头æÂ¥éÂ
Â置àCSP
ãÂÂ
ä¸Â起交æµÂ
ä¸Â管你éÂÂå°ä»Âä¹Âé®é¢Âï¼ÂæÂÂè æ¯æ³交个æÂÂÃ¥ÂÂä¸Âèµ·æ¢讨æÂÂæ¯ï¼Â=ãÂÂ=ï¼Âï¼Âé½å¯以å 堥æÂÂ们çÂÂç»Âç»Âï¼ÂÃ¥ÂÂæÂÂ们ä¸Âèµ· ~
Ã¥ÂÂ欢è¿Âé¨åÂÂå 容ï¼Âå°±å 堥æÂÂ们çÂÂQQ群ï¼ÂÃ¥ÂÂ大家ä¸Â起交æµÂæÂÂæ¯å§~
QQ群ï¼Â1032965518