初始express與使用總結(jié)

1.hello world

1.1.安裝express

1.進(jìn)入到自己的項(xiàng)目目錄, 我這里是express-demo
cd express-demo
2.初始化項(xiàng)目,生成package.json文件
npm init -y
3.安裝express
npm install express --save

1.2.簡(jiǎn)單使用

在當(dāng)前項(xiàng)目下新建app.js文件

// app.js內(nèi)容
// 引入express
var express = require('express')
var app = express()
app.get('/hi', function (req, res, next){
  res.send('hello world!!!')
})
app.listen(8090, function (error) {
  console.log('listening on 8090')
})

1.3.自動(dòng)監(jiān)聽(tīng)文件,并且重啟

安裝,可以全局安裝也可以局部安裝
npm install -g nodemon
使用nodemon監(jiān)聽(tīng)文件變化,自動(dòng)重啟服務(wù)
nodemon app.js

2.請(qǐng)求和響應(yīng)

2.1.請(qǐng)求相關(guān)

2.1.1.返回一個(gè)html頁(yè)面

app.get('/', function (req, res){
  res.sendFile(path.resolve('./views/index.html'))
})

注意path模塊需要先引入
path模塊可以把一個(gè)路徑解析成一個(gè)對(duì)象,對(duì)象中包含了很多屬性。

2.1.2.接收前臺(tái)get方式發(fā)送過(guò)來(lái)的數(shù)據(jù)

// get方式發(fā)送過(guò)來(lái)的數(shù)據(jù) 使用req.query接收
app.get('/getuser', function (req, res) {
  console.log(req.query.userid)
})
// 完整代碼
// 引入express
var express = require('express')
var path = require('path')
var app = express()
var userArr = [
  {"id": 1, "name": "xiaoqiang", "age": 18},
  {"id": 2, "name": "xiaoli", "age": 19},
  {"id": 3, "name": "xiaowang", "age": 20},
  {"id": 4, "name": "xiaozhang", "age": 21}
]
app.get('/', function (req, res){
  res.sendFile(path.resolve('./views/index.html'))
})
app.get('/user', function (req, res) {
  res.sendFile(path.resolve('./views/login.html'))
})

app.get('/getuser', function (req, res) {
  res.send(userArr.filter(function (item) {
    console.log(item.id, req.query.userid)
    return item.id == req.query.userid
  }))
})
app.listen(8090, function (error) {
  console.log('listening on 8090')
})

2.1.3.接收前臺(tái)post方式發(fā)送過(guò)來(lái)的數(shù)據(jù)

接收post數(shù)據(jù),我們可以使用一個(gè)叫做body-parser的模塊來(lái)幫我們完成

1.第一步,先安裝這個(gè)模塊
npm install body-parser --save

2.第二步,引入這個(gè)模塊,并且作為插件使用

var bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({extend: false}))

3.第三步,獲取數(shù)據(jù)

app.post('/login', function (req, res) {
  res.send(req.body.user)
})

2.1.4.文件上傳

文件上傳需要用到multer插件,先安裝multer
npm install multer --save
接下來(lái)需要引入multer
var multer = require('multer')
配置multer
var upload = multer({dest: './upload'})
dest 表示 設(shè)置上傳文件目錄
會(huì)在當(dāng)前目錄下自動(dòng)生成一個(gè)upload文件夾,用來(lái)存放上傳的文件
接下來(lái)我們?cè)谑褂眠@個(gè)multer的時(shí)候不能用app.use,因?yàn)槿绻怯胊pp.use的方式使用的話,會(huì)多次觸發(fā),而我們只希望在對(duì)應(yīng)的請(qǐng)求處理的時(shí)候進(jìn)行使用。

  • 單文件上傳
app.post('/upload', upload.single('fl'), function (req, res) {
  res.send(req.file)
})

處理文件上傳請(qǐng)求
f1是指的文件上傳的input的name

  • 多文件上傳
app.post('/upload', upload.array('fl', 3), function (req, res) {
  res.send(req.files)
})
  • 自定義文件路徑和文件名

node里面一般帶有sync的都象征著是同步方法

var fs = require('fs')
// 檢查目錄是否存在,不存在就創(chuàng)建,如果存在,就直接使用
var  createFolder = function(folder) {
  try {
      //accessSync如果沒(méi)有檢測(cè)到,就會(huì)報(bào)錯(cuò)
      //如果報(bào)錯(cuò)了,就會(huì)被catchh抓獲
    fs.accessSync(folder)
  } catch (e) {
    fs.mkdirSync(folder)
      //異步方法通常都是需要用到回調(diào)函數(shù)的,所以這里我們要用同步方法,       
      //也就是要加上sync
  }
}
//設(shè)置好路徑和文件名
var uploadFolder = './upload'
// 先創(chuàng)建好上傳目錄
createFolder(uploadFolder)
//去自定義文件上傳后的路徑和自定義文件名字
var storage = multer.diskStorage({
    //cb就是callback的縮寫(xiě),回調(diào)函數(shù)
  destination: function (req, file, cb) {
     //下面這行代碼的意思:有文件就按照uploadFolder進(jìn)行上傳就行了
    cb(null, uploadFolder)
  }, 
  filename: function (req, file, cb) {
      //cb(null,file.originalname)    --->這樣傳的話,文件原來(lái)是什么名字,上傳之后就還是什么名字
    cb(null, file.fieldname + '-' + new Date().getTime() + path.extname(file.originalname))
  }
})
//第一個(gè)storage就是storage定義,第二個(gè)storage是我們定義的上面的那幾行代碼
var upload = multer({storage: storage})

app.post('/upload', upload.array('fl', 3), function (req, res) {
  res.send(req.files)
})

2.2.響應(yīng)相關(guān)

2.2.1.send方法

send方法可以返回多種類(lèi)型數(shù)據(jù)

// 返回一個(gè)對(duì)象
res.send({"name":"老張", age: 48})
 // 返回?cái)?shù)組
// res.send([1, 2, 3])
// 報(bào)錯(cuò)
// res.write({"name": "xiaoqiang"})
// res.end()

2.2.2.sendStatus

返回狀態(tài)碼
res.sendHeader(404)
如果沒(méi)有這個(gè)方法,你會(huì)這樣寫(xiě):

res.writeHead(404, {'Content-Type': 'text/plain'})
res.write("not found!!!!")
res.end()

很明顯第一種寫(xiě)法更簡(jiǎn)潔。

2.2.3.redirect

redirect用于重定向

app.get('/re', function (req, res) {
  res.redirect('http://nodeing.com')
})

如果不使用redirect,而使用原生的語(yǔ)法,需要這樣寫(xiě):

res.setHeader('location', 'http://nodeing.com')
res.writeHead(301)
res.end()
  • 301 永久重定向 瀏覽器會(huì)記住
    • a.com b.com
    • a 瀏覽器不會(huì)請(qǐng)求 a 了
    • 直接去跳到 b 了
    • 通過(guò)看status code,可以發(fā)現(xiàn)后面寫(xiě)著from cache
  • 302 臨時(shí)重定向 瀏覽器不記憶
    • a.com b.com
    • a.com 還會(huì)請(qǐng)求 a
    • a 告訴瀏覽器你往 b

3.路由

路由到底是什么呢?不管官方定義到底是什么,咱通俗的說(shuō)就是根據(jù)不同的url,執(zhí)行不同的代碼,類(lèi)似于編程語(yǔ)言中的分支結(jié)構(gòu)

3.1.express規(guī)劃路由

稍微復(fù)雜點(diǎn)的應(yīng)用,通常都是分模塊進(jìn)行的

我們從中挑選幾個(gè)模塊進(jìn)行路由規(guī)劃,在我們的后臺(tái)模塊里面,可以實(shí)現(xiàn)用戶的管理,課程的管理,友情鏈接管理等,我們的訪問(wèn)地址可能是這樣的

// 1.用戶管理
// 用戶列表
http://localhost:8090/admin/user/list
// 添加用戶
http://localhost:8090/admin/user/add
// 刪除用戶
http://localhost:8090/admin/user/delete
// 編輯用戶
http://localhost:8090/admin/user/edit

// 2.課程管理
// 課程列表
http://localhost:8090/admin/course/list
// 添加用戶
http://localhost:8090/admin/course/add
// 刪除用戶
http://localhost:8090/admin/course/delete
// 編輯用戶
http://localhost:8090/admin/course/edit

...

在沒(méi)有拆分路由的情況下,我們需要在app.js里面寫(xiě)這些代碼

/**
 * 用戶管理模塊
 */
app.get('/admin/user/list', function (req, res) {
  res.send('用戶列表')
})
app.get('/admin/user/add', function (req, res) {
  res.send('添加用戶')
})
app.get('/admin/user/delete', function (req, res) {
  res.send('刪除用戶')
})
app.get('/admin/user/edit', function (req, res) {
  res.send('更新用戶')
})

/**
 * 課程模塊
 */
app.get('/admin/course/list', function (req, res) {
  res.send('課程列表')
})
app.get('/admin/course/add', function (req, res) {
  res.send('添加課程')
})
app.get('/admin/course/delete', function (req, res) {
  res.send('刪除課程')
})
app.get('/admin/course/edit', function (req, res) {
  res.send('更新課程')
})

當(dāng)上面的代碼都寫(xiě)到app.js中,代碼會(huì)顯得非常臃腫,最佳的實(shí)踐是把這些模塊拆分出去,express中提供了拆分的方法

第一步,我們?cè)陧?xiàng)目根目錄下面,新建一個(gè)router目錄,在這個(gè)目錄下面按模塊名字分別創(chuàng)建user.js和course.js

第二步,在user.js文件中,創(chuàng)建router,并導(dǎo)出

var express = require('express')
var router = express.Router()

// ...  中間寫(xiě)對(duì)應(yīng)的路由方法

module.exports = router

第三步,把對(duì)應(yīng)的路由方法添加到user.js中

var express = require('express')
var router = express.Router()

router.get('/admin/user/list', function (req, res) {
  res.send('用戶列表')
})
router.get('/admin/user/add', function (req, res) {
  res.send('添加用戶')
})
router.get('/admin/user/delete', function (req, res) {
  res.send('刪除用戶')
})
router.get('/admin/user/edit', function (req, res) {
  res.send('更新用戶')
})

module.exports = router

經(jīng)過(guò)前面步驟,我們完成了user模塊路由拆分

接下來(lái),我們可以按照這種方式,把course模塊拆分出來(lái)

// course.js文件代碼

var express = require('express')
var router = express.Router()

router.get('/admin/course/list', function (req, res) {
  res.send('課程列表')
})
router.get('/admin/course/add', function (req, res) {
  res.send('添加課程')
})
router.get('/admin/course/delete', function (req, res) {
  res.send('刪除課程')
})
router.get('/admin/course/edit', function (req, res) {
  res.send('更新課程')
})

module.exports = router

當(dāng)我們各個(gè)路由模塊都拆分完成后,如何使用這些模塊呢?

在app.js中,我們需要引入創(chuàng)建好的路由模塊

var userRouter = require('./router/user')
var courseRouter = require('./router/course')

接下來(lái),掛載到express上

app.use('/', userRouter)
app.use('/', courseRouter)

經(jīng)過(guò)以上步驟,我們已經(jīng)把路由模塊完全拆分出去了

3.2.對(duì)路由模塊進(jìn)行多級(jí)拆分

前面我們已經(jīng)把模塊劃分出來(lái)了,我們?cè)趯?xiě)路由方法的時(shí)候是這樣的:

router.get('/admin/user/list', function (req, res) {
  res.send('用戶列表')
})

從代碼中我們可以看成,寫(xiě)路徑的時(shí)候會(huì)寫(xiě)一長(zhǎng)串,/admin/user/list,這樣寫(xiě)比較麻煩,同時(shí),我們更希望大模塊直接有更好的劃分,例如,我們的系統(tǒng)總體上劃分為前臺(tái)模塊和后臺(tái)模塊,那我們的router文件夾中應(yīng)該再分home和admin兩個(gè)文件夾

admin文件夾下面放的都是關(guān)于后臺(tái)路由的模塊,home目錄下面放的都是前臺(tái)路由的模塊,這個(gè)時(shí)候,我們需要對(duì)路由做進(jìn)一步拆分,以拆分admin為例:

第一步:在admin/index.js下面 引入其他admin下面的模塊,把其他admin下面的模塊都掛在index.js這個(gè)模塊上然后導(dǎo)出

var express = require('express')
var router = express.Router()
var course = require('./course')
var user = require('./user')

// 掛載user模塊
router.use('/', user)
// 掛載course模塊
router.use('/', course)

module.exports = router

第二步:在app.js中引入admin模塊

//這里的index.js可以不寫(xiě).js,瀏覽器加載時(shí)會(huì)自動(dòng)加上后綴
var adminRouter = require('./router/admin/index')

第三步:把a(bǔ)dminRouter掛到app對(duì)象上

//如果我們請(qǐng)求/admin的話,會(huì)自動(dòng)去找到adminRouter模塊
app.use('/admin', adminRouter)

第四步:需要注意,user.js模塊中的請(qǐng)求路徑需要改變,例如:原來(lái)的"/admin/user/list"這種寫(xiě)法,需要改成這種"/user/list"

3.3.動(dòng)態(tài)路由

動(dòng)態(tài)路由就是路由是動(dòng)態(tài)不固定的,例如:

http;//localhost:8090/user/1
http;//localhost:8090/user/2
http;//localhost:8090/user/3

上面的幾個(gè)url中,都是去訪問(wèn)某個(gè)user,前面部分(http;//localhost:8090/user)是相同的,不同的就是后面的部分

在后臺(tái)我們?cè)趺慈ケO(jiān)聽(tīng)這種形式的url呢?我們可以弄一個(gè)變量來(lái)匹配這些不同的部分,例如:

app.get('/user/:id', function (req, res) {
  console.log(req.params)
})

這其中的id就存儲(chǔ)了url中變化的部分

/user/1   id: 1
/user/2   id: 2
/user/3   id: 3

可以通過(guò)req.params.id打印出每次請(qǐng)求的動(dòng)態(tài)部分(動(dòng)態(tài)參數(shù))

4.靜態(tài)文件

4.1.普通處理靜態(tài)文件的方法

在./views/index.html文件中去引入另一個(gè)css文件index.css,index.css文件放在public/css目錄下。

index.html文件中的內(nèi)容

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    #wrap {
      width: 300px;
      margin: 100px auto;
      line-height: 150px;
      height: 150px;
      text-align: center;
      background-color: green;
    }
    #wrap a {
      color: white;
      text-decoration: none;
    }
  </style>
  <link rel="stylesheet" href="/public/css/index.css">
</head>
<body>
  <div id="wrap">
      <a href="/login">登錄 | </a>
      <a href="/user">用戶中心</a>
  </div>
</body>
</html>

根據(jù)請(qǐng)求渲染出index.html文件

app.get('/', function (req, res) {
  res.sendFile('./index.html')
})

當(dāng)我們方法 '/'這個(gè)路徑的時(shí)候,能把index.html頁(yè)面加載出來(lái),但是沒(méi)辦法把css文件加載出來(lái)

為了解決這個(gè)問(wèn)題,我們還需要單獨(dú)去寫(xiě)一個(gè)路由去返回css文件

app.get('/public/css/index.css', function (req, res) {
  res.sendFile(path.resolve('./public/css/index.css'))
})

4.2.express中處理靜態(tài)文件的插件

express中提供了處理靜態(tài)文件的插件,這里的靜態(tài)文件就是我們項(xiàng)目中需要用到的img、css、js等資源,只需要簡(jiǎn)單的配置就可以實(shí)現(xiàn)對(duì)靜態(tài)文件的處理,步驟如下:

第一步,在app中掛載插件

app.use(express.static('./public'))

第二步,使用靜態(tài)文件,在index.html文件中引入css,路徑需要修改一下

<link rel="stylesheet" href="/css/index.css">

5.ejs模版

5.1.什么是模版引擎?

為了使用戶界面與業(yè)務(wù)數(shù)據(jù)(內(nèi)容)分離而產(chǎn)生的,它可以生成特定格式的文檔,用于網(wǎng)站的模板引擎就會(huì)生成一個(gè)標(biāo)準(zhǔn)的HTML文檔。

在后端開(kāi)發(fā)中,處理數(shù)據(jù)的代碼和展示數(shù)據(jù)的代碼是分離的,這就是前面說(shuō)的,用戶界面和業(yè)務(wù)數(shù)據(jù)內(nèi)容分離,但是真的展現(xiàn)到前端給用戶看到的界面都是數(shù)據(jù)和界面融合在一起的,模版引擎的作用就是把html文件和后端的數(shù)據(jù)柔和在一起生成一個(gè)html文件返回給前端展示,這種方式又叫做服務(wù)端渲染。

模板引擎在服務(wù)端所傳遞的變量,只會(huì)在前端的html中執(zhí)行,并且只認(rèn)識(shí)自己的特定符號(hào),js代碼不會(huì)執(zhí)行模板引擎,js會(huì)直接放給瀏覽器執(zhí)行。

5.2.在express中使用ejs模版引擎

第一步,安裝ejs

npm install ejs --save

第二步,在app.js中引入ejs

var ejs = require('ejs')

第三步,設(shè)置express的模版文件夾,app.set方法,表示設(shè)置某個(gè)屬性名的value,例如:設(shè)置express的views,views指express中模版文件的路徑,路徑的值為第二個(gè)參數(shù)給的值

app.set('views', path.join(__dirname, 'views'))

第四步,告訴express使用ejs來(lái)作為模板引擎,并且設(shè)置模板文件后綴

app.engine('html', ejs.__express)

第五步,注冊(cè)模板引擎

app.set('view engine', 'html')

第六步,ejs模板引擎初體驗(yàn)

1.在"/"路由中,渲染"index.html"文件,并帶參數(shù)

app.get('/', function (req, res){
  // res.sendFile(path.resolve('./views/index.html'))
  res.render('index.html', {title: '螺釘課堂?。?!'})
})

2.在‘index.html’文件中去使用數(shù)據(jù)

<h1><%= title %></h1>

5.3.ejs的常用語(yǔ)法

1.基本語(yǔ)法,后臺(tái)數(shù)據(jù)是融和在html模板中的,在html模板中,通過(guò)自定義標(biāo)簽的形式來(lái)區(qū)分到底是ejs的標(biāo)簽還是html的標(biāo)簽 例如:

<%= title %>

常用的標(biāo)簽:

1、<% if|for %> 這種叫做腳本標(biāo)簽,用于寫(xiě)流程控制  

2、<%= 變量 %> 這種標(biāo)簽的作用是把數(shù)據(jù)輸出到html 

3、<%- %>這種標(biāo)簽的作用和<%= %>相同,區(qū)別是這種標(biāo)簽可以解析html,<%= %>這種標(biāo)簽會(huì)把html標(biāo)簽給轉(zhuǎn)義了

2.流程控制語(yǔ)句

  • if 語(yǔ)句
// 1.后臺(tái)傳入一個(gè) isLogin字段
app.get('/', function (req, res){
  // res.sendFile(path.resolve('./views/index.html'))
  res.render('index.html', {title: '螺釘課堂?。?!', isLogin: false})
})
// 2.在模板中使用這個(gè)isLogin字段來(lái)做判斷
<% if (isLogin) { %>
  <div id="wrap">
      <a href="/login">歡迎admin,登錄?。?!</a>
      <a href="/user">用戶中心</a>
  </div>
<% } else { %> 
  <div id="wrap">
      <a href="/login">登錄 | </a>
      <a href="/user">用戶中心</a>
  </div>
<% } %>
  • for循環(huán)渲染
// 1.在后臺(tái)傳入一個(gè)數(shù)組
app.get('/', function (req, res){
  // res.sendFile(path.resolve('./views/index.html')) 
  var userList = [
    {name: '張飛', age: 29},
    {name: '關(guān)羽', age: 30},
    {name: '劉備', age: 31},
  ]
  res.render('index.html', {title: '螺釘課堂!?。?, isLogin: false, userList: userList})
})
// 2.在模板中循環(huán)出這個(gè)數(shù)組
<ul>
  <% for (var i = 0; i < userList.length; i++) {%>
  <li><%= userList[i].name %> ----> <%= userList[i].age %></li>
  <% } %>
</ul>
// 3.也可以使用forEach方法來(lái)循環(huán)
<ul>
  <% userList.forEach(function (item){%>
    <li><%= item.name %> ----> <%= item.age%></li>
  <% }) %>
</ul>

5.中間件

中間件可以理解為過(guò)濾器,我們通過(guò)一個(gè)自定義的body中間件來(lái)闡述到底什么是中間件?

中間件本質(zhì)上是一個(gè)函數(shù)

中間件都會(huì)有一個(gè)next參數(shù),讓過(guò)濾器能夠一層一層往下執(zhí)行。

中間件需要在路由之前執(zhí)行。

中間件配置必須放在router掛載的前面

在項(xiàng)目根目錄下面創(chuàng)建一個(gè)libs文件夾,然后創(chuàng)建body.js文件

body.js內(nèi)容

const queryString = require('querystring')

function body(req, res, next) {
  let arr = []
  req.on('data', (chunk, err) => {
    if (!err) {
      arr.push(chunk)
    }
  })
  req.on('end', (err) => {
      //arr沒(méi)處理之前是一個(gè)二進(jìn)制對(duì)象
      //用Buffer.concat把a(bǔ)rr數(shù)組里的二進(jìn)制對(duì)象都給連接起來(lái)
      //.toString()把前面整個(gè)轉(zhuǎn)換成字符串
      //queryString.parse把字符串解析成對(duì)象
    req.body = queryString.parse(Buffer.concat(arr).toString())
    next()
  })
}

module.exports = body

在express中使用body中間件

const express = require('express')
const app = express()
const body = require('./libs/body.js')

app.use(body)

app.post('/user', function(req, res) {
  console.log(req.body)
})

app.listen(4001)

中間件:處理請(qǐng)求的,本質(zhì)就是個(gè)函數(shù)
在 Express 中,對(duì)中間件有幾種分類(lèi)
當(dāng)請(qǐng)求進(jìn)來(lái),會(huì)從第一個(gè)中間件開(kāi)始進(jìn)行匹配
如果匹配,則進(jìn)來(lái)
如果請(qǐng)求進(jìn)入中間件之后,沒(méi)有調(diào)用 next 則代碼會(huì)停在當(dāng)前中間件
如果調(diào)用了 next 則繼續(xù)向后找到第一個(gè)匹配的中間件
如果不匹配,則繼續(xù)判斷匹配下一個(gè)中間件
不關(guān)心請(qǐng)求路徑和請(qǐng)求方法的中間件
也就是說(shuō)任何請(qǐng)求都會(huì)進(jìn)入這個(gè)中間件
中間件本身是一個(gè)方法,該方法接收三個(gè)參數(shù):
Request 請(qǐng)求對(duì)象
Response 響應(yīng)對(duì)象
next 下一個(gè)中間件
當(dāng)一個(gè)請(qǐng)求進(jìn)入一個(gè)中間件之后,如果不調(diào)用 next 則會(huì)停留在當(dāng)前中間件
所以 next 是一個(gè)方法,用來(lái)調(diào)用下一個(gè)中間件的
調(diào)用 next 方法也是要匹配的(不是調(diào)用緊挨著的那個(gè))
如果調(diào)用next方法的時(shí)候,傳err參數(shù),則會(huì)將錯(cuò)誤統(tǒng)一匹配給錯(cuò)誤處理中間件,也就是帶有四個(gè)參數(shù)的應(yīng)用程序級(jí)別的中間件。
app.use(function (err, req, res, next) {
res.status(500).send(err.message)
})

應(yīng)用程序級(jí)別中間件

萬(wàn)能匹配(不關(guān)心任何請(qǐng)求路徑和請(qǐng)求方法)

app.use( function (req, res , next){
    console.log('Time:',Date.now())
    next()
})

只要是以’/xxx/‘開(kāi)頭的

app.use ('/a',function (req,res,next){
    console.log('Time:',Date.now())
    next()
})

路徑級(jí)別中間件

get:

app.get ('/',function (req,res){
    res.end('Hello World!')
})

post:

app.post('/',function (req,res){
    res.end('Got a POST request')
})

put:

app.put( '/user',function (req,res){
    res.send ('Got a PUT request at /user')
})

express解決跨域問(wèn)題

方式一:
不用中間件的話可以這樣寫(xiě)

const express = require('express')
const app = express()

app.use((req, res, next) => {
    // 設(shè)置是否運(yùn)行客戶端設(shè)置 withCredentials
    // 即在不同域名下發(fā)出的請(qǐng)求也可以攜帶 cookie
    res.header("Access-Control-Allow-Credentials",true)
    // 第二個(gè)參數(shù)表示允許跨域的域名,* 代表所有域名  
    res.header('Access-Control-Allow-Origin', '*')
    res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, OPTIONS') // 允許的 http 請(qǐng)求的方法
    // 允許前臺(tái)獲得的除 Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma 這幾張基本響應(yīng)頭之外的響應(yīng)頭
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With')
    if (req.method == 'OPTIONS') {
        res.sendStatus(200)
    } else {
        next()
    }
})

方式二:
使用CORS,和其他中間件的用法一樣,app.use()即可:

var express = require('express')
var cors = require('cors')
var app = express()

app.use(cors())

app.get('/products/:id', function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for all origins!'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

如果要單獨(dú)為某個(gè)接口實(shí)現(xiàn)允許跨域請(qǐng)求,在回調(diào)函數(shù)之前先用cors()方法進(jìn)行跨域處理即可:

var express = require('express')
var cors = require('cors')
var app = express()

app.get('/products/:id', cors(), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for a Single Route'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

還可以自己手動(dòng)配置:

var express = require('express')
var cors = require('cors')
var app = express()

var corsOptions = {
  origin: 'http://example.com',
  optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}

app.get('/products/:id', cors(corsOptions), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for only example.com.'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容