亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

深入koa-bodyparser原理解析

2019-11-19 12:17:10
字體:
來源:轉載
供稿:網友

一、前置知識

在理解koa-bodyparser原理之前,首先需要了解部分HTTP相關的知識。

1、報文主體

HTTP報文主要分為請求報文和響應報文,koa-bodyparser主要針對請求報文的處理。

請求報文主要由以下三個部分組成:

  • 報文頭部
  • 空行
  • 報文主體

而koa-bodyparser中的body指的就是請求報文中的報文主體部分。

2、服務器端獲取報文主體流程

HTTP底層采用TCP提供可靠的字節流服務,簡單而言就是報文主體部分會被轉化為二進制數據在網絡中傳輸,所以服務器端首先需要拿到二進制流數據。

談到網絡傳輸,當然會涉及到傳輸速度的優化,而其中一種優化方式就是對內容進行壓縮編碼,常用的壓縮編碼方式有:

  • gzip
  • compress
  • deflate
  • identity(不執行壓縮或不會變化的默認編碼格式)

服務器端會根據報文頭部信息中的Content-Encoding確認采用何種解壓編碼。

接下來就需要將二進制數據轉換為相應的字符,而字符也有不同的字符編碼方式,例如對于中文字符處理差異巨大的UTF-8和GBK,UTF-8編碼漢字通常需要三個字節,而GBK只需要兩個字節。所以還需要在請求報文的頭部信息中設置Content-Type使用的字符編碼信息(默認情況下采用的是UTF-8),這樣服務器端就可以利用相應的字符規則進行解碼,得到正確的字符串。

拿到字符串之后,服務器端又要問了:客戶端,你這一段字符串是啥意思?。?/p>

根據不同的應用場景,客戶端會對字符串采用不同的編碼方式,常見的編碼方式有:

  • URL編碼方式: a=1&b=2
  • JSON編碼方式: {a:1,b:2}

客戶端會將采用的字符串編碼方式設置在請求報文頭部信息的Content-Type屬性中,這樣服務器端根據相應的字符串編碼規則進行解碼,就能夠明白客戶端所傳遞的信息了。

下面一步步分析koa-bodyparser是如何處理這一系列操作,從而得到報文主體內容。

二、獲取二進制數據流

NodeJS中獲取請求報文主體二進制數據流主要通過監聽request對象的data事件完成:

// 示例一const http = require('http')http.createServer((req, res) => { const body = [] req.on('data', chunk => {  body.push(chunk) })  req.on('end', () => {  const chunks = Buffer.concat(body) // 接收到的二進制數據流  // 利用res.end進行響應處理  res.end(chunks.toString()) })}).listen(1234)

而koa-bodyparser主要是對co-body 的封裝,而【co-body】中主要是采用raw-body 模塊獲取請求報文主體的二進制數據流,【row-body】主要是對上述示例代碼的封裝和健壯性處理。

三、內容解碼

客戶端會將內容編碼的方式放入請求報文頭部信息Content-Encoding屬性中,服務器端接收報文主體的二進制數據了時,會根據該頭部信息進行解壓操作,當然服務器端可以在響應報文頭部信息Accept-Encoding屬性中添加支持的解壓方式。

而【row-body】主要采用 inflation 模塊進行解壓處理。

四、字符解碼

一般而言,UTF-8是互聯網中主流的字符編碼方式,前面也提到了還有GBK編碼方式,相比較UTF-8,它編碼中文只需要2個字節,那么在字符解碼時誤用UTF-8解碼GBK編碼的字符,就會出現中文亂碼的問題。

NodeJS主要通過Buffer處理二進制數據流,但是它并不支持GBK字符編碼方式,需要通過 iconv-lite 模塊進行處理。

【示例一】中的代碼就存在沒有正確處理字符編碼的問題,那么報文主體中的字符采用GBK編碼方式,必然會出現中文亂碼:

const request = require('request')const iconv = require('iconv-lite')request.post({ url: 'http://localhost:1234/', body: iconv.encode('中文', 'gbk'), headers: {  'Content-Type': 'text/plain;charset=GBK' }}, (error, response, body) => { console.log(body) // 發生中文亂碼情況})

NodeJS中的Buffer默認是采用UTF-8字符編碼處理,這里借助【iconv-lite】模塊處理不同的字符編碼方式:

const chunks = Buffer.concat(body)  res.end(iconv.decode(chunks, charset)) // charset通過Content-Type得到

五、字符串解碼

前面已經提到了字符串的二種編碼方式,它們對應的Content-Type分別為:

  • URL編碼 application/x-www-form-urlencoded
  • JSON編碼 application/json

對于前端來說,URL編碼并不陌生,經常會用于URL拼接操作,唯一需要注意的是不要忘記對鍵值對進行decodeURIComponent()處理。

當客戶端發送請求主體時,需要進行編碼操作:

'a=1&b=2&c=3'

服務器端再根據URL編碼規則解碼,得到相應的對象。

// URL編碼方式 簡單的解碼方法實現function decode (qs, sep = '&', eq = '=') { const obj = {} qs = qs.split(sep) for (let i = 0, max = qs.length; i < max; i++) {  const item = qs[i]  const index = item.indexOf(eq)  let key, value  if (~index) {   key = item.substr(0, index)   value = item.substr(index + 1)  } else {   key = item   value = ''  }    key = decodeURIComponent(key)  value = decodeURIComponent(value)  if (!obj.hasOwnProperty(key)) {   obj[key] = value  } } return obj}console.log(decode('a=1&b=2&c=3')) // { a: '1', b: '2', c: '3' }

URL編碼方式適合處理簡單的鍵值對數據,并且很多框架的Ajax中的Content-Type默認值都是它,但是對于復雜的嵌套對象就不太好處理了,這時就需要JSON編碼方式大顯身手了。

客戶端發送請求主體時,只需要采用JSON.stringify進行編碼。服務器端只需要采用JSON.parse進行解碼即可:

const strictJSONReg = /^[/x20/x09/x0a/x0d]*(/[|/{)/;function parse(str) { if (!strict) return str ? JSON.parse(str) : str; // 嚴格模式下,總是返回一個對象 if (!str) return {}; // 是否為合法的JSON字符串 if (!strictJSONReg.test(str)) {  throw new Error('invalid JSON, only supports object and array'); } return JSON.parse(str);}

除了上述兩種字符串編碼方式,koa-bodyparser還支持不采用任何字符串編碼方式的普通字符串。

三種字符串編碼的處理方式由【co-body】模塊提供,koa-bodyparser中通過判斷當前Content-Type類型,調用不同的處理方式,將獲取到的結果掛載在ctx.request.body:

return async function bodyParser(ctx, next) {  if (ctx.request.body !== undefined) return await next();  if (ctx.disableBodyParser) return await next();  try {   // 最重要的一步 將解析的內容掛載到koa的上下文中   const res = await parseBody(ctx);   ctx.request.body = 'parsed' in res ? res.parsed : {};   if (ctx.request.rawBody === undefined) ctx.request.rawBody = res.raw; // 保存原始字符串  } catch (err) {   if (onerror) {    onerror(err, ctx);   } else {    throw err;   }  }  await next(); }; async function parseBody(ctx) {  if (enableJson && ((detectJSON && detectJSON(ctx)) || ctx.request.is(jsonTypes))) {   return await parse.json(ctx, jsonOpts); // application/json等json type  }  if (enableForm && ctx.request.is(formTypes)) {   return await parse.form(ctx, formOpts); // application/x-www-form-urlencoded  }  if (enableText && ctx.request.is(textTypes)) {   return await parse.text(ctx, textOpts) || ''; // text/plain  }  return {}; }};

其實還有一種比較常見的Content-type,當采用表單上傳時,報文主體中會包含多個實體主體:

------WebKitFormBoundaryqsAGMB6Us6F7s3SFContent-Disposition: form-data; name="image"; filename="image.png"Content-Type: image/png------WebKitFormBoundaryqsAGMB6Us6F7s3SFContent-Disposition: form-data; name="text"------WebKitFormBoundaryqsAGMB6Us6F7s3SF--

這種方式處理相對比較復雜,koa-bodyparser中并沒有提供該Content-Type的解析。(下一篇中應該會介紹^_^)

五、總結

以上便是koa-bodyparser的核心實現原理,其中涉及到很多關于HTTP的基礎知識,對于HTTP不太熟悉的同學,可以推薦看一波入門級寶典【圖解HTTP】。

最后留圖一張:

 

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
午夜精品久久久久久久99热| 国产精品成人一区二区三区吃奶| 久久久最新网址| 久久成人18免费网站| 国产精品久久久久久久久久免费| 国产成人精品一区二区在线| 日韩欧美中文免费| 国产精品91久久| 久久人91精品久久久久久不卡| 欧美日韩国产中文精品字幕自在自线| 久久久视频在线| 亚洲成人动漫在线播放| 亚洲男人天堂久| 97国产精品视频人人做人人爱| 亚洲一级一级97网| 日韩禁在线播放| 亚洲成人精品视频在线观看| 国产成人精品综合| 国产极品精品在线观看| 欧美福利在线观看| 日本精品久久久| 久久久免费av| 精品国内亚洲在观看18黄| 日韩av中文字幕在线播放| 38少妇精品导航| 亚洲人成免费电影| 欧美激情一二区| 亚洲性生活视频在线观看| 97国产精品视频人人做人人爱| 亚洲成人免费网站| 91热精品视频| 色哟哟入口国产精品| 日韩av在线免费看| 欧美精品xxx| 欧美另类极品videosbest最新版本| 成人久久一区二区三区| 国产精品成人久久久久| 成人国产精品免费视频| 日韩av最新在线观看| 这里只有精品视频| 在线不卡国产精品| 亚洲区一区二区| 亚洲美女久久久| 久久香蕉精品香蕉| 日韩美女视频在线观看| 国产精品香蕉在线观看| 国产精品91在线| 久久深夜福利免费观看| 国产日本欧美一区二区三区| 国产午夜精品视频免费不卡69堂| 国产免费久久av| 国产日韩中文在线| 亚洲国产91精品在线观看| 久久久久久中文| 亚洲精品一区二区网址| 亚洲电影天堂av| 亚洲第一中文字幕在线观看| 黑人狂躁日本妞一区二区三区| 91精品久久久久久久久久| 久久视频精品在线| 成人午夜黄色影院| 欧美美女18p| 久久中文字幕视频| 黑人极品videos精品欧美裸| 国产一区二区在线播放| 欧美激情va永久在线播放| zzjj国产精品一区二区| 久久香蕉国产线看观看av| 久久久精品2019中文字幕神马| 91亚洲精品久久久久久久久久久久| 成人高清视频观看www| 国产免费亚洲高清| 久久久久久久影视| 美女久久久久久久久久久| 亚洲人a成www在线影院| 国产精品午夜视频| 成人写真视频福利网| 久久99青青精品免费观看| 亚洲天堂第二页| 欧美午夜电影在线| 欧美精品videosex牲欧美| 日本精品视频网站| 日本高清视频精品| 久久久久久久久爱| 日韩成人中文电影| 在线视频中文亚洲| 91精品国产综合久久久久久久久| 欧美成人精品激情在线观看| 成人av电影天堂| 欧美影院成年免费版| 亚洲精品欧美极品| 一区二区三区回区在观看免费视频| 亚洲图片在区色| 国产丝袜高跟一区| 亚洲精品国产福利| 亚洲男人天堂2024| 亚洲色图av在线| 亚洲精品大尺度| 国产精品久久一区| 伦伦影院午夜日韩欧美限制| 欧美午夜精品久久久久久久| 日日骚av一区| 国产不卡av在线免费观看| 最近2019中文免费高清视频观看www99| 久久久精品亚洲| 亚洲精品xxxx| 国产第一区电影| 91精品国产91久久久久久最新| 亚洲黄色有码视频| 国产精品自产拍高潮在线观看| 精品福利在线看| 欧美大片在线免费观看| 国产精品观看在线亚洲人成网| 日本精品视频在线| 欧美最猛性xxxxx(亚洲精品)| 久久人人爽人人| 青青a在线精品免费观看| 亚洲国产精品久久精品怡红院| 亚洲国产私拍精品国模在线观看| 欧洲s码亚洲m码精品一区| 色综合久久久久久中文网| xxx一区二区| 国产成人精品国内自产拍免费看| 成人免费网视频| 国产视频亚洲视频| 国产精欧美一区二区三区| 欧美性xxxx极品高清hd直播| 久热爱精品视频线路一| 日韩美女视频免费看| 亚洲精品一区av在线播放| 91免费观看网站| 91亚洲国产精品| 福利二区91精品bt7086| 亚洲国产又黄又爽女人高潮的| 亚洲成色777777在线观看影院| 亚洲成人激情在线观看| 国产精品久久久久久久久久| 精品久久久中文| 欧美极品在线视频| 欧美激情在线狂野欧美精品| 国产成人一区二区| 精品综合久久久久久97| 中文字幕一区二区精品| 日韩精品极品在线观看| 国产欧美久久一区二区| 91视频国产高清| 欧美成人h版在线观看| 国产精品青青在线观看爽香蕉| 国产一区二区在线播放| xxxx欧美18另类的高清| 国产一区二区久久精品| 国产精品视频一区二区三区四| 国产精品www色诱视频| 国产欧美一区二区三区在线看| 欧美高清一级大片| 国产精品免费视频久久久| 日韩中文字幕在线免费观看| 久久久999国产| 国产视频久久久久久久| 久久影视电视剧免费网站清宫辞电视| 91色精品视频在线| 久久精品成人欧美大片古装| 亚洲国产小视频在线观看| 亚洲美女av网站|