日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【node进阶】深度解析express框架---编写接口|解决跨域问题

發(fā)布時(shí)間:2024/3/24 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【node进阶】深度解析express框架---编写接口|解决跨域问题 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? 作者簡介:一名普通本科大三的學(xué)生,致力于提高前端開發(fā)能力
? 個(gè)人主頁:前端小白在前進(jìn)的主頁
🔥 系列專欄 : node.js學(xué)習(xí)專欄
?? 個(gè)人社區(qū) : 個(gè)人交流社區(qū)
🍀 學(xué)習(xí)格言: ?? 打不倒你的會(huì)使你更強(qiáng)!??


🔥前言

我們?cè)谧銮昂蠖朔蛛x項(xiàng)目的時(shí)候,我們經(jīng)常調(diào)用后端所給我們的接口,從而獲取接口中的信息,這一篇文章將帶領(lǐng)大家做自己的后端,給大家講解怎么去運(yùn)用node給自己寫接口,同時(shí)幫助大家解決經(jīng)常遇到的跨域問題

📃目錄

  • 學(xué)前先知:req.body | req.query | req.params
    • req.body
    • req.query
    • req.params
  • 使用express編寫接口
  • 跨域問題
    • 什么是跨域
    • 為什么會(huì)產(chǎn)生跨域問題
  • 解決跨域的兩種方案
    • 1. CORS 解決跨域
      • 什么是 CORS
      • 使用 cors 中間件解決跨域問題
      • cors的三個(gè)響應(yīng)頭
        • Access-Control-Allow-Origin
        • Access-Control-Allow-Headers
        • Access-Control-Allow-Methods
      • CORS請(qǐng)求的分類
        • 簡單請(qǐng)求
        • 預(yù)檢請(qǐng)求
        • 簡單請(qǐng)求與預(yù)檢請(qǐng)求的區(qū)別
    • 2. jsonp解決跨域
      • jsonp的概念
      • jsonp的原理
      • 創(chuàng)建 JSONP 接口的注意事項(xiàng)
      • 實(shí)現(xiàn)jsonp接口的步驟
  • 小結(jié)

學(xué)前先知:req.body | req.query | req.params

想要從web的后臺(tái)中獲取接口的數(shù)據(jù),傳參是必不可少的,后臺(tái)想要接收前臺(tái)傳來的數(shù)據(jù)需要借助一些內(nèi)置的方法:

req.body

在express框架中,用req.body接收post客戶端的數(shù)據(jù),該屬性主要用于post()方法時(shí)傳遞參數(shù)使用,用法最廣泛,在你想使用這個(gè)方法的時(shí)候必須要導(dǎo)入第三方中間件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測(cè)試工具,打印出來的req.body為前臺(tái)傳給后臺(tái)的參數(shù),后臺(tái)告訴了前臺(tái)接收到了參數(shù),打印了ok


req.query

req.query用來獲取get方法傳遞的參數(shù),在這里就無需載入中間件了。

演示代碼:

const express = require('express');const app = express(); // 測(cè)試地址: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中測(cè)試地址為http://127.0.0.1?name=james,通過req.query取到了一個(gè)對(duì)象{name : 'james'},隨后拿到name屬性即可


req.params

有時(shí)候我們遇到的地址欄可能會(huì)是這種形式:http://127.0.0.1/user/1,這時(shí)候就需要我們的req.params去接收前臺(tái)傳來的參數(shù)

演示代碼:

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中自創(chuàng)地址http://127.0.0.1/user/1,通過req.query獲取到一個(gè)對(duì)象{id:1},隨后取出對(duì)象中的屬性即可


使用express編寫接口

  • 創(chuàng)建基本的服務(wù)器

    const express = require('express') //創(chuàng)建express實(shí)例 const app = express() //在這里寫下你的業(yè)務(wù)代碼...//調(diào)用app.listen 方法,指定端口號(hào)并啟動(dòng)web服務(wù)器 app.listen('80',()=>{console.log('http://127.0.0.1'); })
  • 創(chuàng)建api路由模塊

    const express = require('express') const apiRouter = express.Router() //在這里寫下你所創(chuàng)建的路由...//將apiRouter導(dǎo)出為一個(gè)模塊 module.exports = apiRouter
  • 將模塊導(dǎo)入創(chuàng)建基本服務(wù)的文件中

    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 獲取客戶端通過查詢字符串,發(fā)送到服務(wù)器的數(shù)據(jù)const query = req.query// 調(diào)用 res.send() 方法,向客戶端響應(yīng)處理的結(jié)果res.send({status : 0, // 0 表示處理成功,1 表示處理失敗msg : 'GET請(qǐng)求成功!', // 狀態(tài)的描述data : query // 需要響應(yīng)給客戶端的數(shù)據(jù)}) })
  • 編寫post接口

    apiRouter.post('/post',(req,res)=>{// 通過 req.body 獲取請(qǐng)求體中包含的 url-encoded 格式的數(shù)據(jù)const body = req.body// 調(diào)用 res.send() 方法,向客戶端響應(yīng)結(jié)果res.send({status : 0, msg : 'post請(qǐng)求成功!',data : body}) })

    注意:如果要獲取 URL-encoded 格式的請(qǐng)求體數(shù)據(jù),須配置中間件:app.use(express.urlencoded({ extended: false }))

  • 編寫delete接口

    // 定義 DELETE 接口 apiRouter.delete('/delete', (req, res) => {res.send({status: 0,msg: 'DELETE請(qǐng)求成功',})})

跨域問題

什么是跨域

我們剛才編寫的接口,存在一個(gè)很嚴(yán)重的問題:不支持跨域請(qǐng)求。那么什么是跨域(CORS)呢?
當(dāng)一個(gè)請(qǐng)求url的協(xié)議、域名、端口號(hào)三者之間任意一個(gè)與當(dāng)前頁面url不同即為跨域.
舉個(gè)例子:我當(dāng)前的url為:http://127.0.0.1/user,但是我想訪問url為https://127.0.0.1/admin中的數(shù)據(jù),我能訪問的到嗎?顯然是不可能的,這就產(chǎn)生了跨域問題!

為什么會(huì)產(chǎn)生跨域問題

出于瀏覽器的同源策略限制。同源策略(Sameoriginpolicy)是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能可能都會(huì)受到影響。
可以說Web是構(gòu)建在同源策略基礎(chǔ)之上的,瀏覽器只是針對(duì)同源策略的一種實(shí)現(xiàn)。同源策略會(huì)阻止一個(gè)域的javascript腳本和另外一個(gè)域的內(nèi)容進(jìn)行交互。
所謂同源(即指在同一個(gè)域)就是兩個(gè)頁面具有相同的協(xié)議(protocol),主機(jī)(host)和端口號(hào)(port)


解決跨域的兩種方案

1. CORS 解決跨域

什么是 CORS

CORS (Cross-Origin Resource Sharing,跨域資源共享)由一系列HTTP 響應(yīng)頭組成,這些 HTTP 響應(yīng)頭決定瀏覽器是否阻止前端 JS 代碼跨域獲取資源。
瀏覽器的同源安全策略默認(rèn)會(huì)阻止網(wǎng)頁“跨域”獲取資源。但如果接口服務(wù)器配置了 CORS 相關(guān)的 HTTP 響應(yīng)頭,就可以解除瀏覽器端的跨域訪問限制。

上圖中,如果我們網(wǎng)頁對(duì)服務(wù)器發(fā)送了跨域請(qǐng)求,服務(wù)器受到請(qǐng)求后返回書記,但是在返回的時(shí)候,瀏覽器的同源策略安全機(jī)制攔截了響應(yīng)的數(shù)據(jù),這就導(dǎo)致了跨域。

上圖中,使用cors后,配置了響應(yīng)頭Access-Control-Allow-*,這樣的話解除了瀏覽器對(duì)響應(yīng)的攔截,也就是解除了跨域。

注意
CORS 主要在服務(wù)器端進(jìn)行配置。客戶端瀏覽器無須做任何額外的配置,即可請(qǐng)求開啟了 CORS 的接口。
CORS 在瀏覽器中有兼容性。只有支持XMLHttpRequest Level2 的瀏覽器,才能正常訪問開啟了 CORS 的服務(wù)端接口(例如:IE10+、Chrome4+、FireFox3.5+)。


使用 cors 中間件解決跨域問題

cors 是 Express 的一個(gè)第三方中間件。通過安裝和配置 cors 中間件,可以很方便地解決跨域問題。
使用步驟分為如下 3 步:

  • 運(yùn)行 npm install cors 安裝中間件
  • 使用 const cors = require('cors') 導(dǎo)入中間件
  • 在路由之前調(diào)用 app.use(cors()) 配置中間件
  • 代碼示例:

    const express = require('express')const app = express() app.use(express.urlencoded({extended : false}))//一定要在路由之前,配置cors 這個(gè)中間件,從而解決接口跨域問題 const cors = require('cors') app.use(cors()) //將上方的apiRouter模塊導(dǎo)入進(jìn)來 const apiRouter = require('./16.apiRouter') //訪問加上前綴 app.use('/api',apiRouter) app.listen('80',()=>{console.log('http://127.0.0.1'); })

    cors的三個(gè)響應(yīng)頭

    Access-Control-Allow-Origin

    響應(yīng)頭部中可以攜帶一個(gè) Access-Control-Allow-Origin 字段,其語法如下:

    Access-Control-Allow-Origin : <origin> | *

    其中,origin 參數(shù)的值指定了允許訪問該資源的外域 URL。
    如果指定了 Access-Control-Allow-Origin 字段的值為通配符 *,表示允許來自任何域的請(qǐng)求。
    例如,下面的兩個(gè)字段值將分別允許來自 http://127.0.0.1/user 和任何url的請(qǐng)求:

    //該設(shè)置允許來自`http://127.0.0.1/user`的請(qǐng)求 res.setHeader('Access-Control-Allow-Origin','http://127.0.0.1/user')//該設(shè)置允許所有的url的請(qǐng)求 res.setHeader('Access-Control-Allow-Origin','*')

    Access-Control-Allow-Headers

    默認(rèn)情況下,CORS 僅支持客戶端向服務(wù)器發(fā)送如下的 9 個(gè)請(qǐng)求頭:
    Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width 、Content-Type (值僅限于 text/plain、multipart/form-data、application/x-www-form-urlencoded 三者之一)
    如果客戶端向服務(wù)器發(fā)送了額外的請(qǐng)求頭信息,則需要在服務(wù)器端,通過 Access-Control-Allow-Headers 對(duì)額外的請(qǐng)求頭進(jìn)行聲明,否則這次請(qǐng)求會(huì)失敗!

    res.setHeader('Access-Control-Allow-Headers','Content-Type,X-Custom-Header')

    該設(shè)置的目的是:允許客戶端額外向服務(wù)器發(fā)送 Content-Type 請(qǐng)求頭和X-Custom-Header 請(qǐng)求頭
    注意:多個(gè)請(qǐng)求頭之間使用英文逗號(hào)隔開進(jìn)行分割。


    Access-Control-Allow-Methods

    默認(rèn)情況下,CORS 僅支持客戶端發(fā)起 GET、POST、HEAD 請(qǐng)求。
    如果客戶端希望通過 PUT、DELETE 等方式請(qǐng)求服務(wù)器的資源,則需要在服務(wù)器端,通過 Access-Control-Alow-Methods來指明實(shí)際請(qǐng)求所允許使用的 HTTP 方法。

    示例代碼如下:

    //只允許 POST、GET、DELETE、HEAD 請(qǐng)求方法 res.setHeader('Access-Control-Allow-Methods','POST','GET','DELETE','HEAD') //允許所有的HTTP請(qǐng)求方法 res.setHeader('Access-Control-Allow-Methods','*')

    CORS請(qǐng)求的分類

    客戶端在請(qǐng)求 CORS 接口時(shí),根據(jù)請(qǐng)求方式和請(qǐng)求頭的不同,可以將 CORS 的請(qǐng)求分為兩大類,分別是:簡單請(qǐng)求和預(yù)檢請(qǐng)求

    簡單請(qǐng)求

    同時(shí)滿足以下兩大條件的請(qǐng)求,就屬于簡單請(qǐng)求:

  • 請(qǐng)求方式:GET、POST、HEAD 三者之一
  • HTTP 頭部信息不超過以下幾種字段:無自定義頭部字段、Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width 、Content-Type(只有三個(gè)值application/x-www-form-urlencoded、multipart/form-data、text/plain)
  • 預(yù)檢請(qǐng)求

    只要符合以下任何一個(gè)條件的請(qǐng)求,都需要進(jìn)行預(yù)檢請(qǐng)求:

  • 請(qǐng)求方式為 GET、POST、HEAD 之外的請(qǐng)求 Method 類型
  • 請(qǐng)求頭中包含自定義頭部字段
  • 向服務(wù)器發(fā)送了 application/json 格式的數(shù)據(jù)
  • 在瀏覽器與服務(wù)器正式通信之前,瀏覽器會(huì)先發(fā)送 OPTION 請(qǐng)求進(jìn)行預(yù)檢,以獲知服務(wù)器是否允許該實(shí)際請(qǐng)求,所以這一次的 OPTION 請(qǐng)求稱為“預(yù)檢請(qǐng)求”。服務(wù)器成功響應(yīng)預(yù)檢請(qǐng)求后,才會(huì)發(fā)送真正的請(qǐng)求,并且攜帶真實(shí)數(shù)據(jù)。

    簡單請(qǐng)求與預(yù)檢請(qǐng)求的區(qū)別

    簡單請(qǐng)求的特點(diǎn):客戶端與服務(wù)器之間只會(huì)發(fā)生一次請(qǐng)求。

    預(yù)檢請(qǐng)求的特點(diǎn):客戶端與服務(wù)器之間會(huì)發(fā)生兩次請(qǐng)求,OPTION 預(yù)檢請(qǐng)求成功之后,才會(huì)發(fā)起真正的請(qǐng)求。


    2. jsonp解決跨域

    jsonp的概念

    瀏覽器端通過 <script> 標(biāo)簽的 src (讓src)屬性,請(qǐng)求服務(wù)器上的數(shù)據(jù),同時(shí),服務(wù)器返回一個(gè)函數(shù)的調(diào)用。這種請(qǐng)求數(shù)據(jù)的方式叫做 JSONP。

    注意:

  • JSONP 不屬于真正的 Ajax 請(qǐng)求,因?yàn)樗鼪]有使用 XMLHttpRequest 這個(gè)對(duì)象。
  • JSONP 僅支持 GET 請(qǐng)求(重點(diǎn)!!!),不支持 POST、PUT、DELETE 等請(qǐng)求。
  • JSONP 需要前后端共同協(xié)調(diào)

  • jsonp的原理

    動(dòng)態(tài)創(chuàng)建script標(biāo)簽,src屬性指向沒有跨域限制(重點(diǎn)!!!),指向一個(gè)接口,接口返回的格式一定是 ****() 函數(shù)表達(dá)式。


    創(chuàng)建 JSONP 接口的注意事項(xiàng)

    如果項(xiàng)目中已經(jīng)配置了 CORS 跨域資源共享,為了防止沖突,必須在配置 CORS 中間件之前聲明 JSONP 的接口。否則 JSONP 接口會(huì)被處理成開啟了 CORS 的接口。示例代碼如下:

    // 必須在配置 cors 中間件之前,配置 JSONP 的接口【這個(gè)接口不會(huì)被處理成cors接口】 app.get('/api/jsonp', (req, res) => {...}) //一定要在路由之前,配置cors 這個(gè)中間件,從而解決接口跨域問題【后續(xù)的所有接口,都會(huì)被處理為 cors接口】 const cors = require('cors') app.use(cors())//在這里開啟了一個(gè) cors 的接口 app.get('api/get',(req,res)=>{...})

    實(shí)現(xiàn)jsonp接口的步驟

  • 獲取客戶端發(fā)送過來的回調(diào)函數(shù)的名字
  • 得到要通過 JSONP 形式發(fā)送給客戶端的數(shù)據(jù)
  • 根據(jù)前兩步得到的數(shù)據(jù),拼接出一個(gè)函數(shù)調(diào)用的字符串
  • 把上一步拼接得到的字符串,響應(yīng)給客戶端的<script>標(biāo)簽進(jìn)行解析執(zhí)行
  • 具體代碼如下:

    app.get('/api/jsonp', (req, res) => {// TODO: 定義 JSONP 接口具體的實(shí)現(xiàn)過程// 1. 得到函數(shù)的名稱const funcName = req.query.callback// 2. 定義要發(fā)送到客戶端的數(shù)據(jù)對(duì)象const data = { name: 'zs', age: 22 ,req:req.query}// 3. 拼接出一個(gè)函數(shù)的調(diào)用const scriptStr = `${funcName}(${JSON.stringify(data)})`// 4. 把拼接的字符串,響應(yīng)給客戶端res.send(scriptStr)})

    隨后在網(wǎng)頁中發(fā)送jsonp請(qǐng)求即可,這里用的是$.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 }},}) })

    小結(jié)

    本篇的內(nèi)容主要就是針對(duì)express的接口編寫和解決跨域的,接口的編寫非常的容易上手,現(xiàn)階段并沒有到數(shù)據(jù)庫銜接,等后續(xù)文章更新數(shù)據(jù)庫之后,就可以真正做一個(gè)全棧開發(fā)者了,前端中,跨域的問題必須要會(huì),這里提供了最常用的cors解決跨域,jsonp在實(shí)際開發(fā)中使用較少,還有一種反向代理的方式,如果有機(jī)會(huì)更新vue的時(shí)候會(huì)詳細(xì)講解反向代理,好了,少年,繼續(xù)加油吧!😀😀


    👑書寫不易,希望大家能夠給予三連支持,期待我更好的文章喲👑

    總結(jié)

    以上是生活随笔為你收集整理的【node进阶】深度解析express框架---编写接口|解决跨域问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。