【node进阶】深度解析express框架---编写接口|解决跨域问题
? 作者簡介:一名普通本科大三的學生,致力于提高前端開發能力
? 個人主頁:前端小白在前進的主頁
🔥 系列專欄 : node.js學習專欄
?? 個人社區 : 個人交流社區
🍀 學習格言: ?? 打不倒你的會使你更強!??
🔥前言
我們在做前后端分離項目的時候,我們經常調用后端所給我們的接口,從而獲取接口中的信息,這一篇文章將帶領大家做自己的后端,給大家講解怎么去運用node給自己寫接口,同時幫助大家解決經常遇到的跨域問題
📃目錄
- 學前先知:req.body | req.query | req.params
- req.body
- req.query
- req.params
- 使用express編寫接口
- 跨域問題
- 什么是跨域
- 為什么會產生跨域問題
- 解決跨域的兩種方案
- 1. CORS 解決跨域
- 什么是 CORS
- 使用 cors 中間件解決跨域問題
- cors的三個響應頭
- Access-Control-Allow-Origin
- Access-Control-Allow-Headers
- Access-Control-Allow-Methods
- CORS請求的分類
- 簡單請求
- 預檢請求
- 簡單請求與預檢請求的區別
- 2. jsonp解決跨域
- jsonp的概念
- jsonp的原理
- 創建 JSONP 接口的注意事項
- 實現jsonp接口的步驟
- 小結
學前先知:req.body | req.query | req.params
想要從web的后臺中獲取接口的數據,傳參是必不可少的,后臺想要接收前臺傳來的數據需要借助一些內置的方法:
req.body
在express框架中,用req.body接收post客戶端的數據,該屬性主要用于post()方法時傳遞參數使用,用法最廣泛,在你想使用這個方法的時候必須要導入第三方中間件body-parser.
演示代碼:
const express = require('express') const app = express() const body_parser = require('body-parser') app.use(body_parser.urlencoded({extended : false})) app.post('/user',(req,res)=>{console.log(req.body); //[Object: null prototype] { name: 'james', age: '37', gender: '男' }res.send('ok') })app.listen(80,()=>{console.log('http://127.0.0.1'); })這里使用了postman測試工具,打印出來的req.body為前臺傳給后臺的參數,后臺告訴了前臺接收到了參數,打印了ok
req.query
req.query用來獲取get方法傳遞的參數,在這里就無需載入中間件了。
演示代碼:
const express = require('express');const app = express(); // 測試地址:http://127.0.0.1/user/?name=jamesapp.get('/user', function(req, res){let param = req.query.name; console.log(param) //jamesres.send('ok'); }); app.listen(80,()=>{console.log('http://127.0.0.1'); })在postman中測試地址為http://127.0.0.1?name=james,通過req.query取到了一個對象{name : 'james'},隨后拿到name屬性即可
req.params
有時候我們遇到的地址欄可能會是這種形式:http://127.0.0.1/user/1,這時候就需要我們的req.params去接收前臺傳來的參數
演示代碼:
const express = require('express') const app = express()app.get('/user/:id', function(req, res){let param = req.params.id; //1console.log(param)res.send('ok'); }); app.listen(80,()=>{console.log('http://127.0.0.1'); })在postman中自創地址http://127.0.0.1/user/1,通過req.query獲取到一個對象{id:1},隨后取出對象中的屬性即可
使用express編寫接口
-
創建基本的服務器
const express = require('express') //創建express實例 const app = express() //在這里寫下你的業務代碼...//調用app.listen 方法,指定端口號并啟動web服務器 app.listen('80',()=>{console.log('http://127.0.0.1'); }) -
創建api路由模塊
const express = require('express') const apiRouter = express.Router() //在這里寫下你所創建的路由...//將apiRouter導出為一個模塊 module.exports = apiRouter -
將模塊導入創建基本服務的文件中
const express = require('express')const app = express() const apiRouter = require('./16.apiRouter') app.use('/api',apiRouter) app.listen('80',()=>{console.log('http://127.0.0.1'); }) -
編寫get接口
apiRouter.get('/get',(req,res)=>{// 通過 req.query 獲取客戶端通過查詢字符串,發送到服務器的數據const query = req.query// 調用 res.send() 方法,向客戶端響應處理的結果res.send({status : 0, // 0 表示處理成功,1 表示處理失敗msg : 'GET請求成功!', // 狀態的描述data : query // 需要響應給客戶端的數據}) }) -
編寫post接口
apiRouter.post('/post',(req,res)=>{// 通過 req.body 獲取請求體中包含的 url-encoded 格式的數據const body = req.body// 調用 res.send() 方法,向客戶端響應結果res.send({status : 0, msg : 'post請求成功!',data : body}) })注意:如果要獲取 URL-encoded 格式的請求體數據,須配置中間件:app.use(express.urlencoded({ extended: false }))
-
編寫delete接口
// 定義 DELETE 接口 apiRouter.delete('/delete', (req, res) => {res.send({status: 0,msg: 'DELETE請求成功',})})
跨域問題
什么是跨域
我們剛才編寫的接口,存在一個很嚴重的問題:不支持跨域請求。那么什么是跨域(CORS)呢?
當一個請求url的協議、域名、端口號三者之間任意一個與當前頁面url不同即為跨域.
舉個例子:我當前的url為:http://127.0.0.1/user,但是我想訪問url為https://127.0.0.1/admin中的數據,我能訪問的到嗎?顯然是不可能的,這就產生了跨域問題!
為什么會產生跨域問題
出于瀏覽器的同源策略限制。同源策略(Sameoriginpolicy)是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能可能都會受到影響。
可以說Web是構建在同源策略基礎之上的,瀏覽器只是針對同源策略的一種實現。同源策略會阻止一個域的javascript腳本和另外一個域的內容進行交互。
所謂同源(即指在同一個域)就是兩個頁面具有相同的協議(protocol),主機(host)和端口號(port)
解決跨域的兩種方案
1. CORS 解決跨域
什么是 CORS
CORS (Cross-Origin Resource Sharing,跨域資源共享)由一系列HTTP 響應頭組成,這些 HTTP 響應頭決定瀏覽器是否阻止前端 JS 代碼跨域獲取資源。
瀏覽器的同源安全策略默認會阻止網頁“跨域”獲取資源。但如果接口服務器配置了 CORS 相關的 HTTP 響應頭,就可以解除瀏覽器端的跨域訪問限制。
上圖中,如果我們網頁對服務器發送了跨域請求,服務器受到請求后返回書記,但是在返回的時候,瀏覽器的同源策略安全機制攔截了響應的數據,這就導致了跨域。
上圖中,使用cors后,配置了響應頭Access-Control-Allow-*,這樣的話解除了瀏覽器對響應的攔截,也就是解除了跨域。
注意:
CORS 主要在服務器端進行配置。客戶端瀏覽器無須做任何額外的配置,即可請求開啟了 CORS 的接口。
CORS 在瀏覽器中有兼容性。只有支持XMLHttpRequest Level2 的瀏覽器,才能正常訪問開啟了 CORS 的服務端接口(例如:IE10+、Chrome4+、FireFox3.5+)。
使用 cors 中間件解決跨域問題
cors 是 Express 的一個第三方中間件。通過安裝和配置 cors 中間件,可以很方便地解決跨域問題。
使用步驟分為如下 3 步:
代碼示例:
const express = require('express')const app = express() app.use(express.urlencoded({extended : false}))//一定要在路由之前,配置cors 這個中間件,從而解決接口跨域問題 const cors = require('cors') app.use(cors()) //將上方的apiRouter模塊導入進來 const apiRouter = require('./16.apiRouter') //訪問加上前綴 app.use('/api',apiRouter) app.listen('80',()=>{console.log('http://127.0.0.1'); })cors的三個響應頭
Access-Control-Allow-Origin
響應頭部中可以攜帶一個 Access-Control-Allow-Origin 字段,其語法如下:
Access-Control-Allow-Origin : <origin> | *其中,origin 參數的值指定了允許訪問該資源的外域 URL。
如果指定了 Access-Control-Allow-Origin 字段的值為通配符 *,表示允許來自任何域的請求。
例如,下面的兩個字段值將分別允許來自 http://127.0.0.1/user 和任何url的請求:
Access-Control-Allow-Headers
默認情況下,CORS 僅支持客戶端向服務器發送如下的 9 個請求頭:
Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width 、Content-Type (值僅限于 text/plain、multipart/form-data、application/x-www-form-urlencoded 三者之一)
如果客戶端向服務器發送了額外的請求頭信息,則需要在服務器端,通過 Access-Control-Allow-Headers 對額外的請求頭進行聲明,否則這次請求會失敗!
該設置的目的是:允許客戶端額外向服務器發送 Content-Type 請求頭和X-Custom-Header 請求頭
注意:多個請求頭之間使用英文逗號隔開進行分割。
Access-Control-Allow-Methods
默認情況下,CORS 僅支持客戶端發起 GET、POST、HEAD 請求。
如果客戶端希望通過 PUT、DELETE 等方式請求服務器的資源,則需要在服務器端,通過 Access-Control-Alow-Methods來指明實際請求所允許使用的 HTTP 方法。
示例代碼如下:
//只允許 POST、GET、DELETE、HEAD 請求方法 res.setHeader('Access-Control-Allow-Methods','POST','GET','DELETE','HEAD') //允許所有的HTTP請求方法 res.setHeader('Access-Control-Allow-Methods','*')CORS請求的分類
客戶端在請求 CORS 接口時,根據請求方式和請求頭的不同,可以將 CORS 的請求分為兩大類,分別是:簡單請求和預檢請求
簡單請求
同時滿足以下兩大條件的請求,就屬于簡單請求:
預檢請求
只要符合以下任何一個條件的請求,都需要進行預檢請求:
在瀏覽器與服務器正式通信之前,瀏覽器會先發送 OPTION 請求進行預檢,以獲知服務器是否允許該實際請求,所以這一次的 OPTION 請求稱為“預檢請求”。服務器成功響應預檢請求后,才會發送真正的請求,并且攜帶真實數據。
簡單請求與預檢請求的區別
簡單請求的特點:客戶端與服務器之間只會發生一次請求。
預檢請求的特點:客戶端與服務器之間會發生兩次請求,OPTION 預檢請求成功之后,才會發起真正的請求。
2. jsonp解決跨域
jsonp的概念
瀏覽器端通過 <script> 標簽的 src (讓src)屬性,請求服務器上的數據,同時,服務器返回一個函數的調用。這種請求數據的方式叫做 JSONP。
注意:
jsonp的原理
動態創建script標簽,src屬性指向沒有跨域限制(重點!!!),指向一個接口,接口返回的格式一定是 ****() 函數表達式。
創建 JSONP 接口的注意事項
如果項目中已經配置了 CORS 跨域資源共享,為了防止沖突,必須在配置 CORS 中間件之前聲明 JSONP 的接口。否則 JSONP 接口會被處理成開啟了 CORS 的接口。示例代碼如下:
// 必須在配置 cors 中間件之前,配置 JSONP 的接口【這個接口不會被處理成cors接口】 app.get('/api/jsonp', (req, res) => {...}) //一定要在路由之前,配置cors 這個中間件,從而解決接口跨域問題【后續的所有接口,都會被處理為 cors接口】 const cors = require('cors') app.use(cors())//在這里開啟了一個 cors 的接口 app.get('api/get',(req,res)=>{...})實現jsonp接口的步驟
具體代碼如下:
app.get('/api/jsonp', (req, res) => {// TODO: 定義 JSONP 接口具體的實現過程// 1. 得到函數的名稱const funcName = req.query.callback// 2. 定義要發送到客戶端的數據對象const data = { name: 'zs', age: 22 ,req:req.query}// 3. 拼接出一個函數的調用const scriptStr = `${funcName}(${JSON.stringify(data)})`// 4. 把拼接的字符串,響應給客戶端res.send(scriptStr)})隨后在網頁中發送jsonp請求即可,這里用的是$.ajax():
<button id="btnJSONP">JSONP</button> $('#btnJSONP').on('click', function () {$.ajax({type: 'GET',url: 'http://127.0.0.1/api/jsonp',dataType: 'jsonp',success: function (res) {console.log(res) //{ name: 'zs', age: 20 }},}) })小結
本篇的內容主要就是針對express的接口編寫和解決跨域的,接口的編寫非常的容易上手,現階段并沒有到數據庫銜接,等后續文章更新數據庫之后,就可以真正做一個全棧開發者了,前端中,跨域的問題必須要會,這里提供了最常用的cors解決跨域,jsonp在實際開發中使用較少,還有一種反向代理的方式,如果有機會更新vue的時候會詳細講解反向代理,好了,少年,繼續加油吧!😀😀
👑書寫不易,希望大家能夠給予三連支持,期待我更好的文章喲👑
總結
以上是生活随笔為你收集整理的【node进阶】深度解析express框架---编写接口|解决跨域问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深度学习环境配置5——windows下的
- 下一篇: 硬盘已删除的数据怎么恢复?磁盘数据恢复,