イラストとテキストでは、302 インターフェイスをシミュレートし、js で 302 ステータス コードが発生した後にジャンプするための axios と fetch のさまざまなソリューションを実装する方法を説明します。Axios と fetch は 302 のインターセプトに正常に応答します。

要約

  • 日常業務では、fetch または axios を使用してデータを取得するリクエストを開始しますが、特別なニーズに遭遇した場合、異なるライブラリを使用すると、ステータス コード 302、308 などの異なる結果が得られます。これら 2 つの状況はどうでしょうか?

以下に、それを段階的に実装する方法を説明します。

  • 複数のソリューションを使用してフロントエンド コード + 302 バックエンド インターフェイスを実装し、ページ ジャンプを実現するにはどうすればよいですか?
  • fetch が GET または POST リクエストを送信するときに 302 を処理するにはどうすればよいですか?あるいは、302 をインターセプトするにはどうすればよいでしょうか?
  • Axios が応答の 302 ステータス コードを傍受するための解決策は何ですか?どうやって達成するのか?

基本的な環境の準備

単純なコードで単純なnodejsバックエンドを開始する

プロジェクトの初期化
npm init
依存関係をインストールする
npm install express cors --save

いくつかの 302 リクエストをシミュレートする

ルート ディレクトリに app.js ファイルを作成します。いくつかの 302 リクエストをシミュレートします。


var express = require("express");
var app = express();
const cors = require("cors");
//跨域请求cors
app.use(
  cors({
    origin: "*",
    credentials: true,
  })
);
// code 200 请求
app.get("/success", function (req, res) {
  res.send("ok");
});
app.post("/success", function (req, res) {
  res.send("ok");
});
// code 500 请求
app.get("/error500", function (req, res) {
  res.sendStatus(500);
});
const urlInfo = {
  baidu: "https://www.baidu.com/",
  error: "http://localhost:3002/error500", // 这个接口会返回状态码500
  notFound: "http://localhost:3002/notfound", // 根本就没有这个接口
  success: "http://localhost:3002/success", // 200
};
app.get("/redirect-success", function (req, res) {
  res.redirect(302, urlInfo.success);
});
app.post("/redirect-success", function (req, res) {
  res.redirect(302, urlInfo.success);
});
app.get("/redirect-baidu", function (req, res) {
  res.redirect(302, urlInfo.baidu);
});
app.post("/redirect-baidu", function (req, res) {
  res.redirect(302, urlInfo.baidu);
});
app.get("/redirect-error", function (req, res) {
  res.redirect(302, urlInfo.error);
});
app.post("/redirect-error", function (req, res) {
  res.redirect(302, urlInfo.error);
});
app.get("/redirect-not-found", function (req, res) {
  res.redirect(302, urlInfo.notFound);
});
app.post("/redirect-not-found", function (req, res) {
  res.redirect(302, urlInfo.notFound);
});


var http = app.listen(3002, "127.0.0.1", function () {
  var httpInfo = http.address();
  console.log(`创建服务${httpInfo.address}:${httpInfo.port}成功`);
});


予防
  • 次のステータス コードについては 302 のみを試しました。バックエンド コードを変更して他の条件をテストできます~~

重定方向状態态码:
301: 完全に移動されました
302: 見つかりました
303: その他を参照 a>
307: 一時的リダイレクト
308: 永続的リダイレクト

httpサービスを開始する
node app.js

または、スーパーバイザを使用してサーバー側コードのホット アップデートを実行します

スーパーバイザーの使用方法 (コードの開始に使用することをお勧めします)
  • npmの公式ドキュメント
  • ノード スーパーバイザは、プログラムがクラッシュした場合にプログラムを再起動するために使用されます。
  • *.js ファイルが変更されたときにプログラムを再起動するためにも使用できます。
npm install supervisor -g
supervisor app.js
正常に開始されました

インターフェイスのテスト

フロントエンドの準備

ここでは例として Vue を使用しています~~、他のフレームワークでも同じです~~

プロジェクトの作成

npm create vue@latest

依存関係をダウンロードする
cd 项目名
npm install
スタートアッププロジェクト
npm run dev


基本ページを用意する
<script setup>

</script>

<template>
  <main class="main">
    <button>测试</button>
  </main>
</template>
<style scoped>
.main {
  display: flex;
  align-items: center;
  justify-items: center;
  flex-wrap: wrap;
  flex-direction: column;
  margin-top: 20px;
}

button {
  font-size: 16px;
  display: block;
  margin-bottom: 15px;
  cursor: pointer;
  border: none;
  color: hsla(160, 100%, 37%, 1);
  padding: 10px;
  width: 300px;
}
</style>

機能 1: フロントエンド コード + 302 バックエンド インターフェイスを使用してページ ジャンプを実現するにはどうすればよいですか?

オプション 1 - window.location.assign (現在のページにジャンプ)

次のコードをプロジェクトに追加します

<script setup>
const urlInfo = {
  baidu: 'http://localhost:3002/redirect-baidu'
}
const toBaidu = () => {
  console.log(1)
  window.location.assign(urlInfo.baidu)
}
</script>

<template>
  <main class="main">
    <button @click="toBaidu">点击此处跳转百度</button>
  </main>
</template>
オプション 2 - window.open (新しいページを開くか、現在のページを開きます。パラメータを自分で制御できます)

コアコードは次のとおりです(詳細なコードは後で貼り付けます)。

 window.open(urlInfo.baidu, '_blank');
オプション 3 - window.location.href

コアコードは次のとおりです(詳細なコードは後で貼り付けます)。

 window.open(urlInfo.baidu, '_blank');
機能 1 全体のコード
<script setup>
const urlInfo = {
  baidu: 'http://localhost:3002/redirect-baidu'
}
const toBaidu1 = () => {
  window.location.assign(urlInfo.baidu)
}
const toBaidu2 = () => {
  window.open(urlInfo.baidu, '_blank');
}
const toBaidu3 = () => {
  window.location.href = urlInfo.baidu
}
</script>

<template>
  <main class="main">
    <button @click="toBaidu1">点击此处跳转百度-1</button>
    <button @click="toBaidu2">点击此处跳转百度-2</button>
    <button @click="toBaidu3">点击此处跳转百度-3</button>
  </main>
</template>
<style scoped>
.main {
  display: flex;
  align-items: center;
  justify-items: center;
  flex-wrap: wrap;
  flex-direction: column;
  margin-top: 20px;
}

button {
  font-size: 16px;
  display: block;
  margin-bottom: 15px;
  cursor: pointer;
  border: none;
  color: hsla(160, 100%, 37%, 1);
  padding: 10px;
  width: 300px;
}
</style>

機能 2: fetch が GET または POST リクエストを送信するときに 302 を処理する方法は?あるいは、302 をインターセプトするにはどうすればよいでしょうか?

いくつかのシミュレートされた URL を使用していくつかの状況を表示し、返された結果に基づいて、誰もが 302 状況に対処する方法を知ることができます。」

ケース 1:
<script setup>
const urlInfo = {
  baidu: 'http://localhost:3002/redirect-baidu',
  error: 'http://localhost:3002/redirect-error',
  notFound: 'http://localhost:3002/redirect-not-found',
}
const currentUrl = urlInfo.baidu
const fetchGet = () => {
  fetch(currentUrl).then(_ =>{
    console.log('fetch get ---then--- current url:', currentUrl)
    console.log(_)
  }).catch(e=>{
    console.log('fetch get ---catch--- current url:', currentUrl)
    console.log(e)
  })
}
const fetchPost = () => {
  fetch(currentUrl,{method:'post'}).then(_ =>{
    console.log('fetch post ---then--- current url:', currentUrl)
    console.log(_)
  }).catch(e=>{
    console.log('fetch post ---catch--- current url:', currentUrl)
    console.log(e)
  })
}

</script>

<template>
  <main class="main">
    <button @click="fetchGet">Fetch-Get-302</button>
    <button @click="fetchPost">Fetch-Post-302</button>
  </main>
</template>
<style scoped>
.main {
  display: flex;
  align-items: center;
  justify-items: center;
  flex-wrap: wrap;
  flex-direction: column;
  margin-top: 20px;
}

button {
  font-size: 16px;
  display: block;
  margin-bottom: 15px;
  cursor: pointer;
  border: none;
  color: hsla(160, 100%, 37%, 1);
  padding: 10px;
  width: 300px;
}
</style>


ケース 2:

URLを切り替える

<script setup>
const urlInfo = {
  baidu: 'http://localhost:3002/redirect-baidu',
  error: 'http://localhost:3002/redirect-error',
  notFound: 'http://localhost:3002/redirect-not-found',
}
const currentUrl = urlInfo.error
const fetchGet = () => {
  fetch(currentUrl).then(_ =>{
    console.log('fetch get ---then--- current url:', currentUrl)
    console.log(_)
  }).catch(e=>{
    console.log('fetch get ---catch--- current url:', currentUrl)
    console.log(e)
  })
}
const fetchPost = () => {
  fetch(currentUrl,{method:'post'}).then(_ =>{
    console.log('fetch post ---then--- current url:', currentUrl)
    console.log(_)
  }).catch(e=>{
    console.log('fetch post ---catch--- current url:', currentUrl)
    console.log(e)
  })
}

</script>

<template>
  <main class="main">
    <button @click="fetchGet">Fetch-Get-302</button>
    <button @click="fetchPost">Fetch-Post-302</button>
  </main>
</template>
<style scoped>
.main {
  display: flex;
  align-items: center;
  justify-items: center;
  flex-wrap: wrap;
  flex-direction: column;
  margin-top: 20px;
}

button {
  font-size: 16px;
  display: block;
  margin-bottom: 15px;
  cursor: pointer;
  border: none;
  color: hsla(160, 100%, 37%, 1);
  padding: 10px;
  width: 300px;
}
</style>


この状況を分析してみましょう。302 リダイレクト URL は 500 を返す URL です。この時点で、リダイレクトされた結果が得られます。現時点での対処方法はあります。

ケース 3:

URLを切り替える

<script setup>
const urlInfo = {
  baidu: 'http://localhost:3002/redirect-baidu',
  error: 'http://localhost:3002/redirect-error',
  notFound: 'http://localhost:3002/redirect-not-found',
}
const currentUrl = urlInfo.notFound
const fetchGet = () => {
  fetch(currentUrl).then(_ =>{
    console.log('fetch get ---then--- current url:', currentUrl)
    console.log(_)
  }).catch(e=>{
    console.log('fetch get ---catch--- current url:', currentUrl)
    console.log(e)
  })
}
const fetchPost = () => {
  fetch(currentUrl,{method:'post'}).then(_ =>{
    console.log('fetch post ---then--- current url:', currentUrl)
    console.log(_)
  }).catch(e=>{
    console.log('fetch post ---catch--- current url:', currentUrl)
    console.log(e)
  })
}

</script>

<template>
  <main class="main">
    <button @click="fetchGet">Fetch-Get-302</button>
    <button @click="fetchPost">Fetch-Post-302</button>
  </main>
</template>
<style scoped>
.main {
  display: flex;
  align-items: center;
  justify-items: center;
  flex-wrap: wrap;
  flex-direction: column;
  margin-top: 20px;
}

button {
  font-size: 16px;
  display: block;
  margin-bottom: 15px;
  cursor: pointer;
  border: none;
  color: hsla(160, 100%, 37%, 1);
  padding: 10px;
  width: 300px;
}
</style>

ケース 4:

URLを200に変更します

const urlInfo = {
  baidu: 'http://localhost:3002/redirect-baidu',
  error: 'http://localhost:3002/redirect-error',
  notFound: 'http://localhost:3002/redirect-not-found',
  success: 'http://localhost:3002/redirect-success',
}
const currentUrl = urlInfo.success


要約する
  • Fetchを使用すると、302リダイレクトの対象URLがクロスドメインの場合、現時点ではリクエストの具体的な情報を取得できず、catchでエラー結果しか取得できません。
  • Fetch を使用すると、302 リダイレクトのターゲット URL はステータス コード 200、404、500 を返します。 res.redirected を通じて、現時点でインターフェイスがリダイレクトであることを正確に知ることができ、バックエンドインターフェイス。
  • 要約すると、リダイレクト ターゲット URL が正常な場合、Fetch を使用して 302 ステータス コードをインターセプトし、その後の論理処理を正常に実行できます。これは、cors 状況は非常に扱いやすく、プロキシなどの他の構成を使用することで完全に処理できるためです。これを避けてください。

機能 3: axios が GET または POST リクエストを送信するときに 302 を処理するにはどうすればよいですか? Axios が応答の 302 ステータス コードを傍受するための解決策は何ですか?どうやって達成するのか?

依存関係をダウンロードする
 npm i axios --save
基本的なコードを書く
<script setup>
import axios from 'axios';
const urlInfo = {
  success: 'http://localhost:3002/redirect-success',
  baidu: 'http://localhost:3002/redirect-baidu',
  error: 'http://localhost:3002/redirect-error',
  notFound: 'http://localhost:3002/redirect-not-found',
}
const currentUrl = urlInfo.success
const axiosGet = () => {
  axios.get(currentUrl).then(_ =>{
    console.log('axios get ---then--- current url:', currentUrl)
    console.log(_)
  }).catch(e=>{
    console.log('axios get ---catch--- current url:', currentUrl)
    console.log(e)
  })
}
const axiosPost = () => {
  axios.post(currentUrl,{method:'post'}).then(_ =>{
    console.log('axios post ---then--- current url:', currentUrl)
    console.log(_)
  }).catch(e=>{
    console.log('axios post ---catch--- current url:', currentUrl)
    console.log(e)
  })
}

</script>

<template>
  <main class="main">
    <button @click="axiosGet">Axios-Get-302</button>
    <button @click="axiosPost">Axios-Post-302</button>
  </main>
</template>
<style scoped>
.main {
  display: flex;
  align-items: center;
  justify-items: center;
  flex-wrap: wrap;
  flex-direction: column;
  margin-top: 20px;
}

button {
  font-size: 16px;
  display: block;
  margin-bottom: 15px;
  cursor: pointer;
  border: none;
  color: hsla(160, 100%, 37%, 1);
  padding: 10px;
  width: 300px;
}
</style>

ケース 1:
const currentUrl = urlInfo.success

ケース 2:

クロスドメインの場合はcatchを使用し、Network Errorのエラーメッセージを取得します。

{
    "message": "Network Error",
    "name": "AxiosError",
    "stack": "AxiosError: Network Error\n    at XMLHttpRequest.handleError (http://localhost:5173/node_modules/.vite/deps/axios.js?v=e7c1b0b9:1451:14)",
    "config": {
        "transitional": {
            "silentJSONParsing": true,
            "forcedJSONParsing": true,
            "clarifyTimeoutError": false
        },
        "adapter": [
            "xhr",
            "http"
        ],
        "transformRequest": [
            null
        ],
        "transformResponse": [
            null
        ],
        "timeout": 0,
        "xsrfCookieName": "XSRF-TOKEN",
        "xsrfHeaderName": "X-XSRF-TOKEN",
        "maxContentLength": -1,
        "maxBodyLength": -1,
        "env": {},
        "headers": {
            "Accept": "application/json, text/plain, */*"
        },
        "method": "get",
        "url": "http://localhost:3002/redirect-baidu"
    },
    "code": "ERR_NETWORK",
    "status": null
}

ケース 3:

ケース 4:

結論は

統一された返品データを出力してみましょう

{
    "message": "Request failed with status code 500",
    "name": "AxiosError",
    "stack": "AxiosError: Request failed with status code 500\n    at settle (http://localhost:5173/node_modules/.vite/deps/axios.js?v=e7c1b0b9:1204:12)\n    at XMLHttpRequest.onloadend (http://localhost:5173/node_modules/.vite/deps/axios.js?v=e7c1b0b9:1421:7)",
    "config": {
        "transitional": {
            "silentJSONParsing": true,
            "forcedJSONParsing": true,
            "clarifyTimeoutError": false
        },
        "adapter": [
            "xhr",
            "http"
        ],
        "transformRequest": [
            null
        ],
        "transformResponse": [
            null
        ],
        "timeout": 0,
        "xsrfCookieName": "XSRF-TOKEN",
        "xsrfHeaderName": "X-XSRF-TOKEN",
        "maxContentLength": -1,
        "maxBodyLength": -1,
        "env": {},
        "headers": {
            "Accept": "application/json, text/plain, */*",
            "Content-Type": "application/json"
        },
        "method": "post",
        "url": "http://localhost:3002/redirect-error",
        "data": "{\"method\":\"post\"}"
    },
    "code": "ERR_BAD_RESPONSE",
    "status": 500
}
  • Axiosを利用する場合、302リダイレクトの対象URLがクロスドメインの場合、現時点ではリクエストの具体的な情報は取得できず、catchでエラー結果とエラー表示情報のみ取得できます。
  • Axios を使用している場合、302 リダイレクトのターゲット URL はステータス コード 200 を返します。res.request.responseURL と res.config.url を比較すると、現時点でインターフェイスがリダイレクトされているかどうかを正確に知ることができ、バックエンド インターフェイスを通じて返された res. request.responseURL を追加し、リダイレクトされた URL が HTML ページの場合は、それを追加して headers["content-type"] タイプに text/html が含まれているかどうかを判断して、正確なリダイレクトされた URL を取得します。
  • Axios を使用している場合、302 リダイレクトのターゲット URL はステータス コード 404,500 を返します。catch で error.request.responseURL をキャプチャし、それを error.config.url と比較することで、現時点でインターフェイスがリダイレクトされているかどうかを正確に知ることができます。バックエンド インターフェイスによって返される .request.responseURL。リダイレクトされる URL が HTML ページの場合は、これを追加して headers["content-type"] タイプに text/html が含まれるかどうかを判断して、正確なリダイレクトされる URL を取得します。
  • 要約すると、リダイレクト ターゲット URL が正常な場合、Axios を使用して 302 ステータス コードをインターセプトし、その後の論理処理を行うことができます。これは、cors 状況は非常に扱いやすく、プロキシなどの他の構成を使用することで完全に処理できるためです。この状態を避けてください。
解析図

コード
<script setup>
import axios from 'axios';
const urlInfo = {
    success: 'http://localhost:3002/redirect-success',
    baidu: 'http://localhost:3002/redirect-baidu',
    error: 'http://localhost:3002/redirect-error',
    notFound: 'http://localhost:3002/redirect-not-found',
}
const currentUrl = urlInfo.success
const consoleLog = (_, type) => {
   //  请注意下面仅限于重定向和原有url不会包含关系
    if(_.request.responseURL && _.request.responseURL.indexOf(_.config.url) === -1) {
        console.log(`------------------${type} --- 拦截302 ${_.config.method} 请求------------------`)
        console.log('请求URL:', _.config.url)
        console.log('重定向URL:', _.request.responseURL)
    }
    // 如果重定向的url是html页面的话,我们还可以加上判断headers["content-type"]类型是否包含text/html
}
const axiosGet = (url) => {
    axios.get(url).then(_ => {
        consoleLog(_, 'Then')
    }).catch(e => {
        consoleLog(e, 'Error')
    })
}
const axiosPost = (url) => {
    axios.post(url, { method: 'post' }).then(_ => {
        consoleLog(_, 'Then')
    }).catch(e => {
        consoleLog(e, 'Error')
    })
}

</script>

<template>
    <main class="main">
        <button @click="axiosGet(urlInfo.success)">Axios-Get-302-success</button>
        <button @click="axiosPost(urlInfo.success)">Axios-Post-302-success</button>

        <button @click="axiosGet(urlInfo.baidu)">Axios-Get-302-baidu</button>
        <button @click="axiosPost(urlInfo.baidu)">Axios-Post-302-baidu</button>

        <button @click="axiosGet(urlInfo.error)">Axios-Get-302-error</button>
        <button @click="axiosPost(urlInfo.error)">Axios-Post-302-error</button>

        <button @click="axiosGet(urlInfo.notFound)">Axios-Get-302-notFound</button>
        <button @click="axiosPost(urlInfo.notFound)">Axios-Post-302-notFound</button>
    </main>
</template>
<style scoped>
.main {
    display: flex;
    align-items: center;
    justify-items: center;
    flex-wrap: wrap;
    flex-direction: column;
    margin-top: 20px;
}

button {
    font-size: 16px;
    display: block;
    margin-bottom: 15px;
    cursor: pointer;
    border: none;
    color: hsla(160, 100%, 37%, 1);
    padding: 10px;
    width: 300px;
}
</style>

コードリポジトリ

今日はここまで〜
  • 友達、( ̄ω ̄( ̄ω ̄〃 ( ̄ω ̄〃)ゝまた明日~~
  • みなさんも毎日幸せに過ごしてくださいね

記事内の修正が必要な部分をぜひご指摘ください~
学習と双方にとって有益な協力に終わりはありません

ここに画像の説明を挿入します

より良い意見を提供するために通り過ぎる兄弟姉妹を歓迎します~~

おすすめ

転載: blog.csdn.net/tangdou369098655/article/details/134771029