用Node編寫RESTful API接口

前言

本文將經過一個todo list先後端分離的小項目來說解如何用Node建立符合RESTful風格的API接口。css

建立HTTP服務器

咱們先來了解下如何用Node建立HTTP服務器(熟悉的讀者能夠直接跳過)。
用Node建立HTTP服務器是很是方便的,建立HTTP服務器要調用http.createServer()函數,它只有一個參數,是個回調函數,服務器每次收到HTTP請求後都會調用這個回調函數。這個回調會收到兩個參數,請求和響應對象,一般簡寫爲req和res:html

var http = require('http')
var server = http.createServer(function(req, res){
   res.end('Hello World')
})
server.listen(3000, '127.0.0.1')

運行上面的代碼,在瀏覽器中訪問http://localhost:3000。而後你應該能看到一個包含「Hello World.」的普通文本頁面。前端

服務器每收到一條HTTP請求,都會用新的req和res對象觸發回調函數。
在觸發回調函數以前,Node會解析請求的HTTP頭,並將它們做爲req對象的一部分提供給請求回調。但Node不會在回調函數被觸發以前開始對請求體的解析。這種作法跟某些服務端框架不一樣,好比PHP就是在程序邏輯運行前就把請求頭和請求體都解析出來了。vue

Node不會自動往客戶端寫任何響應。在調用完請求回調函數以後,就要由你負責用res.end()方法結束響應了(見下圖)。這樣在結束響應以前,你能夠在請求的生命期內運行任何你想運行的異步邏輯。若是你沒能結束響應,請求會掛起,直到客戶端超時,或者它會一直處於打開狀態。
圖片描述ios

搭建HTTP服務器僅僅是個開始。接下來咱們來看看如何設定響應狀態碼響應頭中的字段,如何正確處理異常ajax

設置響應頭

能夠用res.setHeader(field, value)來設置相應的響應頭,下面是代碼:json

var http = require('http')
var server = http.createServer(function(req, res){
  var body = '<h1>Hello Node</h1>'
  res.setHeader('Content-Length', body.length)
  res.setHeader('Content-Type', 'text/html')
  res.end(body)
})
server.listen(3000)

設置狀態碼

咱們常常須要返回默認狀態碼200以外的HTTP狀態碼。比較常見的狀況是當所請求的資源不存在時返回一個404 Not Found狀態碼。
這能夠經過設定res.statusCode屬性來實現。在程序響應期間能夠隨時給這個屬性賦值,但必須在第一次調用res.write()或res.end()以前。axios

var http = require('http')
var server = http.createServer(function(req, res) {
  var body = '<p>頁面丟失了</p>'
  res.setHeader('Content-Type', 'text/html;charset=utf-8')
  res.statusCode = 404
  res.end(body)
})
server.listen(3000, '127.0.0.1')

Node的策略是提供小而強的網絡API,不一樣於Rails或Django之類的框架。像會話這種高級概念以及HTTP cookies這樣的基礎組件都沒有包括在Node的內核之中。那些都要由第三方模塊提供。後端

構建 RESTful Web 服務

Roy Fielding博士在2000年提出了表徵狀態轉移 (REST)。它是一種基於 HTTP 協議的網絡應用的接口風格
依照規定,好比GET、POST、PUT和DELETE,分別與資源的獲取、建立、更新和刪除相對應。
HTTP 協議定義瞭如下8種標準的方法:跨域

  1. GET:請求獲取指定資源。
  2. HEAD:請求指定資源的響應頭。
  3. POST:向指定資源提交數據。
  4. PUT:請求服務器存儲一個資源。
  5. DELETE:請求服務器刪除指定資源。
  6. TRACE:回顯服務器收到的請求,主要用於測試或診斷。
  7. CONNECT:HTTP/1.1 協議中預留給可以將鏈接改成管道方式的代理服務器。
  8. OPTIONS:返回服務器支持的HTTP請求方法。

建立標準的REST服務須要實現四個HTTP謂詞。每一個謂詞會覆蓋一個操做:

  1. GET:獲取
  2. POST:新增
  3. PUT:更新
  4. DELETE:刪除

POST和GET請求

接下來,咱們開始編寫符合RESTful風格的GET和POST接口。

需求分析

項目決定採用先後端分離,交互數據格式約定爲json,前端添加的數據提交到服務器後,由服務器存入服務器內存中。前端界面以下:
圖片描述

首先,咱們先編寫前端部分。

前端部分

前端部分採用當今流行的vue.js做爲框架,ajax請求採用axios庫。代碼以下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>

  <script src="https://cdn.bootcss.com/vue/2.5.16/vue.js"></script>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>

<body>

<div id="app">
  <h1>Todo List</h1>
  <ul>
    <li v-for="(item, index) in items" :key="index">{{ item }}</li>
  </ul>

  <input type="text" v-model="item">
  <button @click="postApi">button</button>
</div>

<script>
  new Vue({
    el: '#app',
    data: {
      items: [],
      item: ''
    },
    created () {
      axios.get('http://localhost:3000/')
        .then(response => {
          this.items = response.data
        })
        .catch(function (error) {
          console.log(error)
        })
    },
    methods: {
      postApi () {
        axios.post('http://localhost:3000/', {
          item: this.item
        })
          .then(response => {
            this.items = response.data
          })
          .catch(function (error) {
            console.log(error)
          })
      }
    }
  })
</script>
</body>
</html>

後端部分

後端部分將用req.method獲取請求的HTTP謂詞,並分狀況對其進行處理。代碼以下:

var http = require('http')

var items = []

http.createServer(function(req, res) {
  // 設置cors跨域
  res.setHeader('Access-Control-Allow-Origin', '*')
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type')
  res.setHeader('Content-Type', 'application/json')

  switch (req.method) {
    // 設置了cors跨域
    // post請求時,瀏覽器會先發一次options請求,若是請求經過,則繼續發送正式的post請求
    case 'OPTIONS':
      res.statusCode = 200
      res.end()
      break

    case 'GET':
      let data = JSON.stringify(items)
      res.write(data)
      res.end()
      break

    case 'POST':
      let item = ''
      req.on('data', function (chunk) {
        item += chunk
      })
      req.on('end', function () {
        // 存入
        item = JSON.parse(item)
        items.push(item.item)
        // 返回到客戶端
        let data = JSON.stringify(items)
        res.write(data)
        res.end()
      })
      break
  }
}).listen(3000)

console.log('http server is start...')

小結

固然,一個完整的RESTful服務還應該實現PUT謂詞和DELETE謂詞,若是你真的讀懂了本文,那麼相信這對你已經再也不是問題了。

相關文章
相關標籤/搜索