回答:
セクション9.5(POST)の対応するRFC 2616では、適切なヘッダーを使用する場合、POSTメッセージへの応答をキャッシュできます。
このメソッドへの応答は、応答に適切なCache-ControlまたはExpiresヘッダーフィールドが含まれていない限り、キャッシュできません。ただし、303(その他を参照)応答を使用して、ユーザーエージェントにキャッシュ可能なリソースを取得するように指示できます。
注同じRFCが(HTTPでのキャッシング)部13で明示的に述べていることをキャッシュがPOSTの後に、対応するエンティティを無効にしなければならないことを要求。
一部のHTTPメソッドは、キャッシュによってエンティティを無効にする必要があります。これは、Request-URI、またはLocationまたはContent-Locationヘッダー(存在する場合)によって参照されるエンティティです。これらのメソッドは次のとおりです。
- PUT - DELETE - POST
これらの仕様が意味のあるキャッシングをどのように可能にするかは、私には明らかではありません。
これは、RFC 2616を廃止するRFC 7231(セクション4.3.3)にも反映され、さらに明確になっています。
POST要求への応答は、
明示的な鮮度情報が含まれている場合にのみキャッシュ可能です([RFC7234]のセクション4.2.1を参照)。
ただし、POSTキャッシングは広く実装されていません。オリジンサーバーがクライアントがPOSTの結果を後のGETで再利用できる方法でキャッシュできることを望む場合、オリジンサーバーは結果とContent-Locationを含む200(OK)応答を送信してもよい(MAY) POSTの有効なリクエストURIと同じ値を持つヘッダーフィールド(セクション3.1.4.2)。
これによると、キャッシュされたPOSTの結果(この機能がサーバーによって示されている場合)は、同じURIに対するGET要求の結果として後で使用できます。
RFC 2616セクション9.5によれば、
「POSTメソッドへの応答はキャッシュできません。応答に適切なCache-ControlまたはExpiresヘッダーフィールドが含まれていない限り。」
したがって、はい、POSTリクエストの応答をキャッシュできますが、適切なヘッダーが付いている場合のみです。ほとんどの場合、応答をキャッシュする必要はありません。ただし、サーバーにデータを保存しない場合など、完全に適切な場合もあります。
ただし、現在のFirefox 3.0.10を含む多くのブラウザーは、ヘッダーに関係なくPOST応答をキャッシュしません。IEはこの点でよりスマートに動作します。
ここで、RFC 2616 S. 13.10に関する混乱を解消したいと思います。URIのPOSTメソッドは、「キャッシュのためにリソースを無効にする」ことはありません。そのキャッシュ制御ヘッダーがより長い期間の鮮度を示していたとしても、そのURIの以前にキャッシュされたバージョンを古くします。
GET
とPOST
リクエストに使用する場合に適用されます。あなたがクライアントとサーバーの間に座っているキャッシュであるなら、あなたはあなたが見てGET /foo
、あなたは応答をキャッシュします。次に、同じURIであるために応答にキャッシュコントロールヘッダーが含まれていない場合でも、キャッシュされた応答を無効にする必要があるPOST /foo
ことがわかります。したがって、元のヘッダーがまだキャッシュであることを示している場合でも、次は再検証する必要があります。ライブ(リクエストを見ていなかった場合)GET /foo
POST
GET /foo
POST /foo
But in some cases - such as if you are not saving any data on the server - it's entirely appropriate.
。では、そもそもそのようなPOST APIのポイントは何ですか?
全体:
基本的に、POSTはべき等の操作ではありません。したがって、キャッシュに使用することはできません。GETはべき等の操作である必要があるため、一般的にキャッシュに使用されます。
HTTP 1.1 RFC 2616 S. 9.1のセクション9.1を参照してください。
GETメソッドのセマンティクス以外:
POSTメソッド自体は、意味的にリソースに何かを投稿することを目的としています。POSTはキャッシュできません。何かを1回、2回、3回行うと、サーバーのリソースが毎回変更されるためです。各リクエストは重要であり、サーバーに配信する必要があります。
PUTメソッド自体は、意味的にはリソースを配置または作成するためのものです。これはべき等の操作ですが、その間にDELETEが発生した可能性があるため、キャッシュには使用されません。
DELETEメソッド自体は、意味的にはリソースを削除するためのものです。これはべき等演算ですが、その間にPUTが発生した可能性があるため、キャッシュには使用されません。
クライアント側のキャッシングについて:
Webブラウザーは、前のPOST操作からの応答がある場合でも、常に要求を転送します。たとえば、Gmailを使用して数日間隔でメールを送信できます。件名と本文は同じでもかまいませんが、両方のメールを送信する必要があります。
プロキシキャッシングについて:
サーバーにメッセージを転送するプロキシHTTPサーバーは、GETまたはHEADリクエスト以外は何もキャッシュしません。
サーバーのキャッシュについて:
デフォルトでは、サーバーはキャッシュをチェックしてPOSTリクエストを自動的に処理しません。ただし、もちろん、POST要求をアプリケーションまたはアドインに送信することができ、パラメーターが同じである場合に、そこから読み取る独自のキャッシュを持つことができます。
リソースの無効化:
HTTP 1.1 RFC 2616 S. 13.10を確認すると、POSTメソッドがリソースをキャッシュ用に無効化する必要があることが示されています。
POST応答をキャッシュする場合、それはWebアプリケーションの指示である必要があります。これは、「適切なCache-ControlまたはExpiresヘッダーフィールドが応答に含まれていない限り、このメソッドへの応答はキャッシュできない」という意味です。
POSTの結果がべき等であるかどうかを知っているアプリケーションが、必要かつ適切なキャッシュ制御ヘッダーを添付するかどうかを決定すると、安全に想定できます。キャッシングが許可されていることを示唆するヘッダーが存在する場合、アプリケーションはPOSTが実際にはスーパーGETであることを通知しています。POSTの使用が必要なのは、べき等演算を実行するために必要な不必要で無関係な(キャッシュキーとしてのURIの使用)データが大量にあるためです。
以下のGETは、この前提の下でキャッシュから提供できます。
キャッシュ可能なPOST応答とキャッシュ不可能なPOST応答を区別するために必要な正しいヘッダーを添付できないアプリケーションは、無効なキャッシュ結果のせいです。
つまり、キャッシュにヒットする各POSTには、条件付きヘッダーを使用した検証が必要です。これは、キャッシュコンテンツを更新して、オブジェクトの有効期限が切れるまでPOSTの結果がリクエストへの応答に反映されないようにするために必要です。
マーク・ノッティンガムは、POSTの応答をキャッシュすることがいつ可能かを分析しました。キャッシュを利用したい後続のリクエストは、GETまたはHEADリクエストでなければならないことに注意してください。httpセマンティクスも参照
POSTは、識別された状態の表現を処理しません。100のうちの99倍です。ただし、1つの場合があります。サーバーが、要求URIと同じContent-Locationヘッダーを設定することにより、このPOST応答がそのURIの表現であると言うのをやめたとき。その場合、POST応答は同じURIに対するGET応答と同じです。キャッシュして再利用できますが、将来のGETリクエストでのみ使用できます。
投稿リクエストをキャッシュできるかどうか疑問に思っている場合、その質問に対する回答を調べてみると、成功しない可能性があります。「キャッシュポストリクエスト」を検索すると、最初の結果はこのStackOverflowの質問です。
答えは、キャッシングがどのように機能するか、RFCに従ってキャッシングがどのように機能するか、RFCに従ってキャッシングがどのように機能するか、および実際のキャッシングがどのように機能するかについての混乱した混合です。RFCから始めて、ブラウザが実際にどのように機能するかを示し、次にCDN、GraphQL、およびその他の懸念事項について説明します。
RFCに従って、POST要求はキャッシュを無効にする必要があります。
13.10 Invalidation After Updates or Deletions
..
Some HTTP methods MUST cause a cache to invalidate an entity. This is
either the entity referred to by the Request-URI, or by the Location
or Content-Location headers (if present). These methods are:
- PUT
- DELETE
- POST
この言語はPOSTリクエストがキャッシュ可能ではないことを示唆していますが、それは(この場合)正しくありません。キャッシュは、以前に保存されたデータに対してのみ無効になります。RFC(に見える)は、はい、POST
リクエストをキャッシュできることを明確に示しています。
9.5 POST
..
Responses to this method are not cacheable, unless the response
includes appropriate Cache-Control or Expires header fields. However,
the 303 (See Other) response can be used to direct the user agent to
retrieve a cacheable resource.
この言語にもかかわらず、を設定すると、Cache-Control
後続のPOST
リクエストを同じリソースにキャッシュしてはなりません。POST
リクエストはサーバーに送信する必要があります:
13.11 Write-Through Mandatory
..
All methods that might be expected to cause modifications to the
origin server's resources MUST be written through to the origin
server. This currently includes all methods except for GET and HEAD.
A cache MUST NOT reply to such a request from a client before having
transmitted the request to the inbound server, and having received a
corresponding response from the inbound server. This does not prevent
a proxy cache from sending a 100 (Continue) response before the
inbound server has sent its final reply.
それはどういう意味ですか?まあ、あなたはPOST
リクエストをキャッシュするのではなく、リソースをキャッシュするのです。
POST応答の本文は、同じリソースに対する後続のGETリクエストでのみキャッシュできます。POSTレスポンスのLocation
or Content-Location
ヘッダーを設定して、本文が表すリソースを伝えます。したがって、POSTリクエストをキャッシュする唯一の技術的に有効な方法は、同じリソースへの後続のGETです。
正解は両方です。
RFCでは同じリソースへのリクエストのキャッシュが許可されていますが、実際には、ブラウザとCDNはこの動作を実装しておらず、POSTリクエストをキャッシュすることはできません。
出典:
次のJavaScriptアプリケーションの例(index.js)があるとします。
const express = require('express')
const app = express()
let count = 0
app
.get('/asdf', (req, res) => {
count++
const msg = `count is ${count}`
console.log(msg)
res
.set('Access-Control-Allow-Origin', '*')
.set('Cache-Control', 'public, max-age=30')
.send(msg)
})
.post('/asdf', (req, res) => {
count++
const msg = `count is ${count}`
console.log(msg)
res
.set('Access-Control-Allow-Origin', '*')
.set('Cache-Control', 'public, max-age=30')
.set('Content-Location', 'http://localhost:3000/asdf')
.set('Location', 'http://localhost:3000/asdf')
.status(201)
.send(msg)
})
.set('etag', false)
.disable('x-powered-by')
.listen(3000, () => {
console.log('Example app listening on port 3000!')
})
また、次のWebページの例(index.html)があるとします。
<!DOCTYPE html>
<html>
<head>
<script>
async function getRequest() {
const response = await fetch('http://localhost:3000/asdf')
const text = await response.text()
alert(text)
}
async function postRequest(message) {
const response = await fetch(
'http://localhost:3000/asdf',
{
method: 'post',
body: { message },
}
)
const text = await response.text()
alert(text)
}
</script>
</head>
<body>
<button onclick="getRequest()">Trigger GET request</button>
<br />
<button onclick="postRequest('trigger1')">Trigger POST request (body 1)</button>
<br />
<button onclick="postRequest('trigger2')">Trigger POST request (body 2)</button>
</body>
</html>
NodeJS、Expressをインストールし、JavaScriptアプリケーションを起動します。ブラウザでWebページを開きます。ブラウザーの動作をテストするには、いくつかの異なるシナリオを試してください。
これは、Cache-Control
およびContent-Location
応答ヘッダーを設定できても、ブラウザーにHTTP POST要求をキャッシュさせる方法がないことを示しています。
ブラウザーの動作は構成できませんが、ブラウザーでない場合は、必ずしもRFCの規則に拘束されるわけではありません。
アプリケーションコードを記述している場合、POSTリクエスト(疑似コード)を明示的にキャッシュすることを妨げるものは何もありません。
if (cache.get('hello')) {
return cache.get('hello')
} else {
response = post(url = 'http://somewebsite/hello', request_body = 'world')
cache.put('hello', response.body)
return response.body
}
CDN、プロキシ、ゲートウェイも必ずしもRFCに従う必要はありません。たとえば、FastlyをCDNとして使用する場合、Fastlyを使用すると、カスタムVCLロジックを記述してPOSTリクエストをキャッシュできます。
POSTリクエストをキャッシュするかどうかは、コンテキストによって異なります。
たとえば、基になるクエリがべき等である場合、POSTを使用してElasticsearchまたはGraphQLにクエリを実行できます。これらのケースでは、ユースケースに応じて応答をキャッシュすることは意味がある場合とない場合があります。
RESTful APIでは、POSTリクエストは通常リソースを作成するため、キャッシュしないでください。これは、べき等演算ではないというPOSTに関するRFCの理解でもあります。
GraphQLを使用していて、CDNとブラウザー間でHTTPキャッシュが必要な場合は、GETメソッドを使用してクエリを送信することがPOSTではなく要件を満たすかどうかを検討してください。注意点として、ブラウザーやCDNによってURIの長さの制限が異なる可能性がありますが、外部向けのプロダクションGraphQLアプリのベストプラクティスとして、操作のセーフリスト(クエリのホワイトリスト)はURIを短縮できます。
それが実際にサイトのデータを変更しないものである場合は、GETリクエストである必要があります。フォームであっても、取得リクエストとして設定できます。他の人が指摘しているように、POSTの結果をキャッシュすることはできますが、POSTは定義上データを変更しているため、意味がありません。
firefox 27.0とhttpfoxを使用して、2014年5月19日に次の1行を確認しました:00:03:58.777 0.488 657(393)POST(キャッシュ)text / html https://users.jackiszhp.info/S4UP
明らかに、postメソッドの応答はキャッシュされ、httpsにも含まれます。信じられない!
POSTはステートフルAjaxで使用されます。POSTに対してキャッシュされた応答を返すと、通信チャネルおよびメッセージ受信の副作用が無効になります。これは非常に悪いです。追跡するのも大変です。に対して強くお勧めします。
自明な例としては、副作用として、今週、給与を$ 10,000支払うというメッセージがあります。あなたは「OK、それは通り抜けた!」を取得したくない 先週キャッシュされたページバック。その他の、より複雑な実世界のケースは、同様の陽気さをもたらします。