Koa2 フレームワークを通じて CORS を使用してクロスドメイン Ajax リクエストを実装する方法

亚连
リリース: 2018-06-01 11:17:23
オリジナル
1565 人が閲覧しました

この記事では主に、CORS を使用してクロスドメイン Ajax リクエストを完了するための Koa2 フレームワークを紹介し、参考として提供します。

クロスドメイン Ajax リクエストを実装するには多くの方法がありますが、その 1 つは CORS を使用することであり、この方法の鍵はサーバー側で設定することです。

この記事では、通常のクロスドメイン Ajax 応答を完了できる最も基本的な設定のみを説明します (詳細な設定の方法はわかりません)。

CORS はリクエストを単純なリクエストと単純でないリクエストに分割します。単純なリクエストは、追加のリクエスト ヘッダーのない get リクエストと post リクエストであると考えることができます。post リクエストの場合、リクエストの形式は application/json にすることはできません。この部分については私は深く理解していませんが、間違いがある場合は、誰かが間違いを指摘し、修正を提案してくれることを願っています。)残りの put リクエストと post リクエスト、Content-Type application/json を含むリクエスト、およびカスタム リクエスト ヘッダーを含むリクエストは、単純ではないリクエストです。

単純なリクエストの構成は非常に簡単で、目的を達成するために応答を完了する必要がある場合は、応答ヘッダーで Access-Control-Allow-Origin を構成するだけです。

http://localhost:3000 ドメイン名の下にある http://127.0.0.1:3001 ドメイン名にアクセスしたい場合。次の設定を行うことができます:

app.use(async (ctx, next) => {
 ctx.set('Access-Control-Allow-Origin', 'http://localhost:3000');
 await next();
});
ログイン後にコピー

次に、ajax を使用して post リクエストなどの単純なリクエストを開始すると、サーバーから正しい応答を簡単に取得できます。

実験用コードは以下のとおりです:

$.ajax({
  type: 'post',
  url: 'http://127.0.0.1:3001/async-post'
 }).done(data => {
  console.log(data);
})
ログイン後にコピー

サーバー側コード:

router.post('/async-post',async ctx => {
 ctx.body = {
 code: "1",
 msg: "succ"
 }
});
ログイン後にコピー

これにより、正しい応答情報を取得できます。

このときのリクエストとレスポンスのヘッダー情報を見ると、リクエストヘッダーには追加のorigin(リクエストのURLアドレスのリファラーもあります)があり、レスポンスヘッダーには追加の Access-Control-Allow-Origin。

これで単純なリクエストを送信できるようになりましたが、単純でないリクエストを送信するには他の設定が必要です。

初めて非単純リクエストが発行されると、実際には 2 つのリクエストが発行されます。最初のリクエストは、このリクエストのリクエスト メソッドが OPTIONS であるかどうかによって決まります。リクエストが正常に応答できるかどうか。

サーバー上でこの OPTIONS タイプのリクエストを照合するには、この事前チェックを通過できるように、それに照合して応答を返すミドルウェアを作成する必要があります。

app.use(async (ctx, next) => {
 if (ctx.method === 'OPTIONS') {
 ctx.body = '';
 }
 await next();
});
ログイン後にコピー

このようにして、OPTIONS リクエストを渡すことができます。

プリフライトリクエストのリクエストヘッダーを確認すると、さらに 2 つのリクエストヘッダーがあることがわかります。

Access-Control-Request-Method: PUT
Origin: http://localhost:3000
ログイン後にコピー

これら 2 つのヘッダー情報を介してサーバーとネゴシエートし、サーバーの応答条件を満たしているかどうかを確認します。

理解するのは簡単ですが、リクエストヘッダーにはさらに 2 つの情報が含まれているため、レスポンスヘッダーには当然、対応する 2 つの情報が含まれます。 2 つの情報は次のとおりです。

Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: PUT,DELETE,POST,GET
ログイン後にコピー
ログイン後にコピー

最初の情報は同じです。が原点であるため、通過します。 2 番目の情報は Access-Controll-Request-Method に対応し、サーバーが許可する応答メソッドにリクエスト メソッドが含まれている場合、この情報も渡されます。両方の制約が満たされるため、リクエストは正常に開始されます。

ここまでは、事前チェックのみを完了し、実際のリクエストを送信しないことと同じです。

もちろん、実際のリクエストもレスポンスを正常に受信しており、レスポンスヘッダーは次のとおりです(重要でない部分は省略しています)

Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: PUT,DELETE,POST,GET
ログイン後にコピー
ログイン後にコピー

リクエストヘッダーは次のとおりです:

Origin: http://localhost:3000
ログイン後にコピー

これは非常に明白であり、レスポンスヘッダー情報は次のように設定されています私たちはサーバー上にいます、そうです。

クライアントは、Access-Control-Request-Method リクエスト ヘッダーを送信する必要はありません。これは、直前に事前チェックされているためです。

この例のコードは次のとおりです:

$.ajax({
   type: 'put',
   url: 'http://127.0.0.1:3001/put'
  }).done(data => {
   console.log(data);
});
ログイン後にコピー

サーバー コード:

app.use(async (ctx, next) => {
  ctx.set('Access-Control-Allow-Origin', 'http://localhost:3000');
  ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET');
  await next();
});
ログイン後にコピー

この時点で、クロスドメイン Ajax 応答を正しく実行するための基本構成が完了しました。さらに構成できるものがいくつかあります。

たとえば、これまでのところ、すべての非単純リクエストは実際に 2 つのリクエスト (プリフライト用と実際のリクエスト用) を発行するため、パフォーマンスの低下が発生します。プリフライトリクエストを送信しないようにするには、次の応答ヘッダーを設定できます。

Access-Control-Max-Age: 86400
ログイン後にコピー

この応答ヘッダーの意味は、非単純リクエストがサーバー側のテストに合格した瞬間から、経過したミリ秒数が Access-Control-Max-Age 未満であるときの相対時間を設定することです。事前チェックの場合は、リクエストを直接送信できます。

もちろん、単純なリクエストにはプリフライトがないため、このコードは単純なリクエストには意味がありません。

現在のコードは次のとおりです:

app.use(async (ctx, next) => {
 ctx.set('Access-Control-Allow-Origin', 'http://localhost:3000');
 ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET');
 ctx.set('Access-Control-Max-Age', 3600 * 24);
 await next();
});
ログイン後にコピー

これまでのところ、クロスドメインの Ajax リクエストに応答できますが、このドメインの Cookie はリクエスト ヘッダーには含まれません。 Cookie をサーバーに持ち込み、サーバーがさらに Cookie を設定できるようにする場合は、さらに構成が必要です。

その後の検出を容易にするために、事前にドメイン名 http://127.0.0.1:3001 の下に 2 つの Cookie を設定します。間違って Cookie を中国語に設定しないように注意してください (中国語に設定したところ、エラーが報告されました。エラーの原因は長い間見つかりませんでした)

次に、2 つのステップを実行する必要があります。最初の手順では、応答ヘッダー Access-Control-Allow-Credentials を true に設定し、次にクライアント側で xhr オブジェクトの withCredentials 属性を true に設定します。

クライアントのコードは次のとおりです:

$.ajax({
   type: 'put',
   url: 'http://127.0.0.1:3001/put',
   data: {
    name: '黄天浩',
    age: 20
   },
   xhrFields: {
    withCredentials: true
   }
  }).done(data => {
   console.log(data);
  });
ログイン後にコピー

サーバーのコードは次のとおりです:

app.use(async (ctx, next) => {
  ctx.set('Access-Control-Allow-Origin', 'http://localhost:3000');
  ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET');
  ctx.set('Access-Control-Allow-Credentials', true);
  await next();
});
ログイン後にコピー

这时就可以带着cookie到服务器了,并且服务器也可以对cookie进行改动。但是cookie仍是http://127.0.0.1:3001域名下的cookie,无论怎么操作都在该域名下,无法访问其他域名下的cookie。

现在为止CORS的基本功能已经都提到过了。

一开始我不知道怎么给Access-Control-Allow-Origin,后来经人提醒,发现可以写一个白名单数组,然后每次接到请求时判断origin是否在白名单数组中,然后动态的设置Access-Control-Allow-Origin,代码如下:

app.use(async (ctx, next) => {
 if (ctx.request.header.origin !== ctx.origin && whiteList.includes(ctx.request.header.origin)) {
  ctx.set('Access-Control-Allow-Origin', ctx.request.header.origin);
  ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET');
  ctx.set('Access-Control-Allow-Credentials', true);
  ctx.set('Access-Control-Max-Age', 3600 * 24);
 }
 await next();
});
ログイン後にコピー

这样就可以不用*通配符也可匹配多个origin了。

注意:ctx.origin与ctx.request.header.origin不同,ctx.origin是本服务器的域名,ctx.request.header.origin是发送请求的请求头部的origin,二者不要混淆。

最后,我们再稍微调整一下自定义的中间件的结构,防止每次请求都返回Access-Control-Allow-Methods以及Access-Control-Max-Age,这两个响应头其实是没有必要每次都返回的,只是第一次有预检的时候返回就可以了。

调整后顺序如下:

app.use(async (ctx, next) => {
 if (ctx.request.header.origin !== ctx.origin && whiteList.includes(ctx.request.header.origin)) {
  ctx.set('Access-Control-Allow-Origin', ctx.request.header.origin);
  ctx.set('Access-Control-Allow-Credentials', true);
 }
 await next();
});

app.use(async (ctx, next) => {
 if (ctx.method === 'OPTIONS') {
  ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET');
  ctx.set('Access-Control-Max-Age', 3600 * 24);
  ctx.body = '';
 }
 await next();
});
ログイン後にコピー

这样就减少了多余的响应头。

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

webpack打包js的方法

vue 简单自动补全的输入框的示例

angular5 httpclient的示例实战

以上がKoa2 フレームワークを通じて CORS を使用してクロスドメイン Ajax リクエストを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!