Çok basit önbellek semantiği ile: parametreler aynı ise (ve URL de aynı ise, elbette), bu bir hit. Mümkün mü? Önerilen?
Çok basit önbellek semantiği ile: parametreler aynı ise (ve URL de aynı ise, elbette), bu bir hit. Mümkün mü? Önerilen?
Yanıtlar:
Bölüm 9.5'teki (POST) karşılık gelen RFC 2616 , uygun başlıklar kullanırsanız POST mesajına verilen yanıtın önbelleğe alınmasına izin verir .
Yanıt uygun Önbellek Denetimi veya Süresi Sonu başlık alanlarını içermediği sürece bu yönteme verilen yanıtlar önbelleğe alınamaz. Bununla birlikte, 303 (Diğerine Bak) yanıtı, kullanıcı aracısını önbelleğe alınabilir bir kaynağı almaya yönlendirmek için kullanılabilir.
Aynı RFC'nin Bölüm 13'te (HTTP'de önbellekleme) açıkça bir önbelleğin bir POST isteğinden sonra karşılık gelen varlığı geçersiz kılması gerektiğini belirtti .
Bazı HTTP yöntemleri, bir önbelleğin bir varlığı geçersiz kılmasına neden OLMALIDIR. Bu, İstek URI'sı veya Konum veya İçerik-Konum başlıkları (varsa) tarafından belirtilen varlıktır. Bu yöntemler:
- PUT - DELETE - POST
Bu spesifikasyonların nasıl anlamlı önbelleklemeye izin verebileceği net değil.
Bu aynı zamanda RFC 2616'yı geçersiz kılan RFC 7231'de (Bölüm 4.3.3.) Yansıtılır ve daha da netleştirilir .
POST isteklerine verilen yanıtlar yalnızca
açık tazelik bilgileri içerdiklerinde önbelleğe alınabilir (bkz. [RFC7234] Bölüm 4.2.1).
Ancak, POST önbellekleme yaygın olarak uygulanmaz. Kaynak sunucunun istemcinin POST sonucunu daha sonraki bir GET tarafından yeniden kullanılabilecek şekilde önbelleğe almasını istediği durumlarda, kaynak sunucu sonucu ve bir İçerik Konumunu içeren 200 (Tamam) yanıtı gönderebilir POST'un etkin istek URI'sı ile aynı değere sahip başlık alanı (Bölüm 3.1.4.2).
Buna göre, önbelleğe alınmış bir POST sonucu (bu yetenek sunucu tarafından belirtilirse) daha sonra aynı URI için bir GET isteğinin sonucu olarak kullanılabilir.
RFC 2616 Bölüm 9.5'e göre:
"POST yöntemine verilen yanıtlar önbelleğe alınamaz, yanıtın uygun Cache-Control veya Expires üstbilgisi alanlarını içermediği sürece."
Bu nedenle, EVET, POST istek yanıtını ancak uygun üstbilgilerle birlikte geldiğinde önbelleğe alabilirsiniz. Çoğu durumda yanıtı önbelleğe almak istemezsiniz. Ancak bazı durumlarda - sunucuya herhangi bir veri kaydetmiyorsanız gibi - bu tamamen uygundur.
Bununla birlikte, geçerli Firefox 3.0.10 dahil olmak üzere birçok tarayıcının, başlıklardan bağımsız olarak POST yanıtını önbelleğe almayacağını unutmayın. IE bu konuda daha akıllı davranır.
Şimdi, burada RFC 2616 S. 13.10 ile ilgili bazı karışıklıkları gidermek istiyorum. Bir URI üzerindeki POST yöntemi, burada belirtildiği gibi "önbellekleme kaynağını geçersiz kılmaz". Önbellek kontrol başlıkları daha uzun süre tazelik göstermiş olsa bile, bu URI bayatının önceden önbelleğe alınmış bir sürümünü yapar.
GET
ve POST
isteklerde aynı URI'yi kullandığınız durumlarda geçerlidir . İstemci ve sunucu arasında oturan bir GET /foo
önbelleyseniz, yanıtı görür ve önbelleğe alırsınız. Gördüğünüz Sonraki POST /foo
ardından edilir gerekli dan önbelleğe yanıtı geçersiz GET /foo
olsa bile POST
yanıtı hiç önbellek denetim başlıklarını içermez aynı URI çünkü böylece bir sonraki, GET /foo
orijinal başlıkları önbellek hala olacağını göstermiştir bile tekrar doğrulamak zorunda kalacak canlı ( POST /foo
isteği görmediyseniz )
But in some cases - such as if you are not saving any data on the server - it's entirely appropriate.
. Öyleyse ilk etapta böyle bir POST API'sının anlamı nedir?
Genel:
Temel olarak POST, idempotent bir işlem değildir . Bu yüzden önbelleğe almak için kullanamazsınız. GET idempotent bir işlem olmalıdır, bu nedenle genellikle önbellekleme için kullanılır.
Lütfen HTTP 1.1 RFC 2616 S'nin 9.1 bölümüne bakın . 9.1 .
GET yönteminin semantiği dışında:
POST yönteminin kendisi anlamsal olarak bir kaynağa bir şeyler göndermek içindir. POST önbelleğe alınamaz çünkü bir kerede iki kez veya üç kez bir şey yaparsanız, sunucunun kaynağını her seferinde değiştirirsiniz. Her istek önemlidir ve sunucuya teslim edilmelidir.
PUT yönteminin kendisi anlamsal olarak bir kaynak koymak veya oluşturmak içindir. Bu idempotent bir işlemdir, ancak bu arada bir DELETE oluşmuş olabileceği için önbellekleme için kullanılmaz.
DELETE yönteminin kendisi anlamsal olarak bir kaynağı silmek içindir. Bu idempotent bir işlemdir, ancak önbelleğe alma için kullanılmaz çünkü bu arada bir PUT oluşmuş olabilir.
İstemci tarafı önbelleğe alma ile ilgili:
Bir web tarayıcısı, önceki bir POST işleminden yanıt almış olsa bile isteğinizi her zaman yönlendirir. Örneğin gmail ile birkaç gün arayla e-posta gönderebilirsiniz. Aynı konu ve beden olabilirler, ancak her iki e-posta da gönderilmelidir.
Proxy önbelleğe alma ile ilgili:
İletinizi sunucuya ileten proxy HTTP sunucusu, GET veya HEAD isteği dışında hiçbir şeyi önbelleğe almaz.
Sunucu önbelleğe alma ile ilgili:
Bir sunucu varsayılan olarak bir POST isteğini önbelleğini kontrol ederek otomatik olarak işlemez. Ancak elbette, uygulamanıza veya eklentinize bir POST isteği gönderilebilir ve parametreler aynı olduğunda okuduğunuz kendi önbelleğiniz olabilir.
Bir kaynağı geçersiz kılma:
HTTP 1.1'in kontrol edilmesi RFC 2616 S. 13.10 , POST yönteminin kaynağı önbellekleme için geçersiz kılması gerektiğini gösterir.
Bir POST yanıtını önbelleğe alırsanız, web uygulamasının yönünde olmalıdır. "Bu yönteme verilen yanıtlar, önbellek denetimi veya Expires üstbilgisi alanlarını içermiyorsa, önbelleğe alınamaz."
Bir POST sonucunun idempotent olup olmadığını bilen uygulamanın gerekli ve uygun önbellek kontrol başlıklarının eklenip eklenmeyeceğine karar verdiğini güvenle varsayabiliriz. Önbelleğe alınmaya izin veren başlıklar varsa, uygulama POST'un gerçekte bir süper GET olduğunu; POST kullanımının yalnızca idempotent işlemi gerçekleştirmek için gerekli olan gereksiz ve alakasız (URI'nin önbellek anahtarı olarak kullanılması) verilerin miktarı nedeniyle gerekli olduğunu.
Aşağıdaki GET'ler bu varsayım altında önbellekten sunulabilir.
Önbelleğe alınabilen ve alınamayan POST yanıtları arasında ayrım yapmak için gerekli ve doğru başlıkları ekleyemeyen bir uygulama, geçersiz önbellek sonuçları için hatalıdır.
Bununla birlikte, önbelleğe çarpan her POST için koşullu üstbilgiler kullanılarak doğrulama gerekir. Bu, nesnenin ömrü sona erene kadar bir POST sonucunun isteklere verilen yanıtlara yansıtılmasını önlemek için önbellek içeriğini yenilemek için gereklidir.
Mark Nottingham, bir POST yanıtını önbelleğe almanın mümkün olduğunu analiz etti. Önbelleklemeden yararlanmak isteyen sonraki isteklerin GET veya HEAD istekleri olması gerektiğini unutmayın. Ayrıca bkz. Http semantiği
POST'lar 100 üzerinden 99 kez belirlenen devletin temsillerini ele almazlar. Bununla birlikte, böyle bir durum söz konusudur; sunucu, bu POST yanıtının, istek URI'sıyla aynı olan bir Content-Location üstbilgisi ayarlayarak URI'sinin bir temsili olduğunu söylemek için yola çıktığında. Bu olduğunda, POST yanıtı aynı URI'ye bir GET yanıtı gibidir; önbelleğe alınabilir ve yeniden kullanılabilir - ancak yalnızca gelecekteki GET istekleri için.
Bir gönderi isteğini önbelleğe alıp alamayacağınızı merak ediyorsanız ve bu sorunun cevabını araştırmayı deneyiyorsanız, büyük olasılıkla başarılı olamayacaksınız. "Önbellek sonrası isteği" arandığında ilk sonuç bu StackOverflow sorusudur.
Yanıtlar, önbelleğe almanın nasıl çalışması, RFC'ye göre önbelleğe almanın nasıl çalıştığı, RFC'ye göre önbelleğe almanın nasıl çalışması ve pratikte önbelleğe almanın nasıl çalıştığı konusunda karışık bir karışımdır. RFC ile başlayalım, tarayıcının gerçekte nasıl çalıştığını gösterelim, ardından CDN'ler, GraphQL ve diğer endişe alanları hakkında konuşalım.
RFC uyarınca, POST istekleri önbelleği geçersiz kılmalıdır:
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
Bu dil, POST isteklerinin önbelleğe alınamayacağını, ancak bu doğru olmadığını gösterir (bu durumda). Önbellek yalnızca önceden depolanmış veriler için geçersiz kılınır. RFC (görünüşe göre) açıkça evet, açıktır, POST
istekleri önbelleğe alabilirsiniz :
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.
Bu dile rağmen, Cache-Control
sonraki POST
istekleri aynı kaynağa önbelleğe almamak gerekir . POST
isteklerin sunucuya gönderilmesi gerekir:
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.
Bu nasıl bir anlam ifade ediyor? POST
İsteği önbelleğe almıyorsunuz , kaynağı önbelleğe alıyorsunuz.
POST yanıt gövdesi yalnızca aynı kaynağa GET istekleri için önbelleğe alınabilir. Set Location
veyaContent-Location
Vücudun temsil ettiği kaynağı iletmek için POST yanıtında üstbilgisini . Bu nedenle, bir POST isteğini önbelleğe almanın teknik olarak geçerli tek yolu, daha sonra aynı kaynağa giden GET'ler içindir.
Doğru cevap her ikisi de:
RFC aynı kaynağa önbellek isteklerine izin verse de, pratikte tarayıcılar ve CDN'ler bu davranışı uygulamamakta ve POST isteklerini önbelleğe almanıza izin vermemektedir.
Kaynaklar:
Aşağıdaki örnek JavaScript uygulaması (index.js) verildiğinde:
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!')
})
Ve aşağıdaki örnek web sayfası (index.html) verildi:
<!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'i yükleyin ve JavaScript uygulamasını başlatın. Web sayfasını tarayıcınızda açın. Tarayıcı davranışını test etmek için birkaç farklı senaryo deneyin:
Bu, Cache-Control
ve Content-Location
yanıt başlıklarını ayarlayabilseniz bile , tarayıcı önbelleğini HTTP POST isteği yapmanın bir yolu olmadığını gösterir.
Tarayıcı davranışı yapılandırılamaz, ancak bir tarayıcı değilseniz, RFC kurallarına bağlı olmanız gerekmez.
Uygulama kodu yazıyorsanız, POST isteklerini (sözde kod) açıkça önbelleğe almanızı engelleyen hiçbir şey yoktur:
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'lerin, proxy'lerin ve ağ geçitlerinin de RFC'yi izlemesi gerekmez. Örneğin, CDN'niz olarak Hızlı'yı kullanırsanız, POST isteklerini önbelleğe almak için Hızlıca özel VCL mantığı yazmanıza izin verir .
POST isteğinizin önbelleğe alınıp alınmayacağı bağlama bağlıdır.
Örneğin, temel sorgunuzun hatalı olduğu POST kullanarak Elasticsearch veya GraphQL'i sorgulayabilirsiniz. Bu durumlarda, kullanım durumuna bağlı olarak yanıtı önbelleğe almak mantıklı olabilir veya olmayabilir.
RESTful API'sinde, POST istekleri genellikle bir kaynak oluşturur ve önbelleğe alınmamalıdır. Bu aynı zamanda RFC'nin POST'un idempotent bir operasyon olmadığı anlayışıdır.
GraphQL kullanıyorsanız ve CDN'ler ve tarayıcılar arasında HTTP önbelleğe almanız gerekiyorsa, GET yöntemini kullanarak sorgu göndermenin POST yerine gereksinimlerinizi karşılayıp karşılamadığını düşünün . Bir uyarı olarak, farklı tarayıcılar ve CDN'ler farklı URI uzunluk sınırlarına sahip olabilir, ancak dışa dönük üretim GraphQL uygulamaları için en iyi uygulama olarak işlem güvenliği (sorgu beyaz listesi) URI'leri kısaltabilir.
Sitenizdeki verileri gerçekten değiştirmeyen bir şeyse, bir GET isteği olmalıdır. Bu bir form olsa bile, yine de alma isteği olarak ayarlayabilirsiniz. Diğerlerinin de belirttiği gibi, bir POST'un sonuçlarını önbelleğe alabiliyor olsanız da, anlamsal bir anlam ifade etmez çünkü tanım gereği bir POST verileri değiştiriyor.
Firefox 27.0 ve httpfox ile, 19 Mayıs 2014'te, bunun bir satırını gördüm: 00: 03: 58.777 0.488 657 (393) POST (Önbellek) metni / html https://users.jackiszhp.info/S4UP
Açıkça, bir gönderi yönteminin yanıtı önbelleğe alınır ve https biçimindedir. Inanılmaz!
POST durum bilgisi olan Ajax'ta kullanılır. POST için önbelleğe alınmış bir yanıt döndürülmesi iletişim kanalını ve mesaj almanın yan etkilerini yener. Bu Çok Çok Kötü. Ayrıca izini sürmek gerçek bir acıdır. Karşı tavsiye.
Önemsiz bir örnek, bir yan etki olarak, şu anki maaşınızı 10.000 $ ödeyen bir mesaj olacaktır. "Tamam, geçti!" geçen hafta önbelleğe alınan sayfa. Diğer, daha karmaşık gerçek dünyadaki vakalar da benzer komikliğe yol açar.