AMP

AMP'de CORS

Birçok AMP bileşeni ve uzantısı, kökler arası kaynak paylaşımı (CORS) isteklerini kullanarak uzak uç noktalardan yararlanır. Bu belge, AMP'de CORS kullanmanın temel yönlerini açıklamaktadır. CORS hakkında bilgi edinmek için bkz: W3 CORS Teknik Özellikleri.

Kaynağım için neden CORS'a ihtiyacım var?

Kendi kaynağınıza yönelik talepler için neden CORS'a ihtiyacınız olduğu konusunda kafanız karışabilir, hadi konuyu inceleyelim.

Dinamik verilerini (ör. amp-form, amp-list vb.) alan AMP bileşenleri, verileri almak için uzak uç noktalara CORS isteklerinde bulunur. AMP sayfanız bu tür bileşenler içeriyorsa, bu isteklerin başarısız olmaması için CORS'u işlemeniz gerekir.

Bunu bir örnekle gösterelim:

Fiyatları olan ürünleri listeleyen bir AMP sayfanız olduğunu varsayalım. Sayfadaki fiyatları güncellemek için, kullanıcı bir json uç noktasından en son fiyatları alan bir düğmeye tıklar (amp-list bileşeni aracılığıyla yapılır). JSON sizin etki alanınızda.

Tamam, yani sayfa etki alanımda ve JSON'da etki alanımda. Ben bir sorun göremiyorum!

Peki, ama kullanıcınız AMP sayfanıza nasıl ulaştı? Eriştikleri önbelleğe alınmış bir sayfa mı? Kullanıcınız büyük olasılıkla AMP sayfanıza doğrudan erişmemiş, bunun yerine sayfanızı başka bir platform aracılığıyla keşfetmiştir. Örneğin, Google Araması, AMP sayfalarını hızlı bir şekilde oluşturmak için Google AMP önbelleğini kullanır; bunlar, farklı etki alanı olan Google AMP Önbelleğinden sunulan önbelleğe alınmış sayfalardır. Kullanıcınız sayfanızdaki fiyatları güncellemek için düğmeye tıkladığında, önbelleğe alınmış AMP sayfası, kaynaklar (önbellek -> kaynak etki alanı) arasında bir uyumsuzluk olan fiyatları almak için kaynak etki alanınıza bir istek gönderir. Bu tür çapraz kaynaklı isteklere izin vermek için CORS'u işlemeniz gerekir, aksi takdirde istek başarısız olur.

Peki, ne yapmalıyım?

  1. Dinamik veri getiren AMP sayfaları için, bu sayfaların önbelleğe alınmış sürümünü test ettiğinizden emin olun; sadece kendi etki alanınızda test etmeyin. (Aşağıdaki AMP'de CORS'u Test Etme bölümüne bakın)
  2. CORS isteklerini ve yanıtlarını işlemek için bu belgedeki yönergeleri izleyin.

CORS istekleri için çerezleri kullanma

CORS isteklerini kullanan çoğu AMP bileşeni, kimlik bilgileri modunu otomatik olarak ayarlar veya yazarın isteğe bağlı olarak etkinleştirmesine izin verir. Örneğin, amp-list bileşeni, bir cors JSON uç noktasından dinamik içerik getirir ve yazarın credentials özniteliği aracılığıyla kimlik bilgisi modunu ayarlamasına izin verir.

Örnek: Çerezler aracılığıyla bir amp-list öğesine kişiselleştirilmiş içerik eklemek

<amp-list
credentials="include"
src="<%host%>/json/product.json?clientId=CLIENT_ID(myCookieId)"

>   <template type="amp-mustache">

    Your personal offer: ${{price}}
  </template>
</amp-list>

Kimlik bilgileri modunu belirterek; kaynak, CORS isteğine çerezleri ekleyebilir ve ayrıca yanıtta çerezler ayarlayabilir (üçüncü taraf çerez kısıtlamalarına tabidir).

Üçüncü taraf çerez kısıtlamaları

Tarayıcıda belirtilen aynı üçüncü taraf çerez kısıtlamaları, AMP'deki credentialed CORS istekleri için de geçerlidir. Bu kısıtlamalar tarayıcıya ve platforma bağlıdır, ancak bazı tarayıcılar için kaynak, yalnızca kullanıcı daha önce kaynağı 1.taraf (üst) bir pencerede ziyaret ettiyse çerezleri ayarlayabilir. Veya başka bir deyişle, yalnızca kullanıcı kaynak web sitesini doğrudan ziyaret ettikten sonra. Bu göz önüne alındığında, CORS aracılığıyla erişilen bir hizmet, varsayılan olarak çerezleri ayarlayabileceğini varsayamaz.

AMP'de CORS güvenliği

AMP sayfalarınız için geçerli ve güvenli istek ve yanıtlar sağlamak için şunları yapmanız gerekir:

  1. İsteği doğrulayın.
  2. Uygun yanıt başlıklarını gönderin.

Arka uçta bir Node kullanıyorsanız, AMP Toolbox'ın bir parçası olan AMP CORS ara katman yazılımını kullanabilirsiniz.

CORS isteklerini doğrulama

Bitiş noktanız bir CORS isteği aldığında:

  1. CORS Origin başlığının izin verilen bir kaynak olduğunu doğrulayın (yayıncının kaynağı + AMP önbellekleri).
  2. Bir Origin Başlığı yoksa, isteğin aynı kaynaktan (AMP-Same-Origin aracılığıyla) olup olmadığını kontrol edin.

1) Belirli CORS kaynakları için isteklere izin verme

CORS uç noktaları, Origin HTTP üstbilgisi aracılığıyla istekte bulunan kaynağı alır. Uç noktalar yalnızca aşağıdaki isteklere izin vermelidir: (1) yayıncının kendi kaynağı ve (2) https://cdn.ampproject.org/caches.json'da listelenen her cacheDomain kaynağı.

Örneğin, uç noktalar isteklere izin vermelidir:

  • Google AMP Önbelleği alt etki alanı: https://<publisher's domain>.cdn.ampproject.org
    (örneğin, https://nytimes-com.cdn.ampproject.org )

AMP Önbellek URL biçimleri hakkında daha fazla bilgi için şu kaynaklara bakın:

2) same-origin isteklerine izin verme

Origin başlığının eksik olduğu aynı kaynak istekleri için AMP aşağıdaki özel başlığı ayarlar:

AMP-Same-Origin: true

Bu özel başlık, aynı kaynaktan bir XHR isteği yapıldığında AMP Çalışma Zamanı tarafından gönderilir (yani, önbellek olmayan bir URL'den sunulan belge). AMP-Same-Origin:true başlığını içeren isteklere izin verin.

CORS yanıt başlıklarını gönderme

CORS isteğini doğruladıktan sonra, ortaya çıkan HTTP yanıtı aşağıdaki üstbilgileri içermelidir:

Access-Control-Allow-Origin: <origin>

Bu başlık, bir W3 CORS Teknik Özellikleri gereksinimidir. Burada origin, CORS Origin istek başlığı aracılığıyla izin verilen talep kaynağı anlamına gelir. (Örneğin, "https://<publisher's subdomain>.cdn.ampproject.org").

W3 CORS teknik özellikleri, yanıtta * değerinin döndürülmesine izin verse de, daha iyi güvenlik için şunları yapmalısınız:

  • Origin başlığı varsa, Origin başlığının değerini doğrulayın ve yineleyin.

Durum değiştirme isteklerini işleme

İsteği işlemeden önce bu doğrulama kontrollerini gerçekleştirin. Bu doğrulama, CSRF saldırılarına karşı koruma sağlamaya yardımcı olur ve güvenilmeyen kaynak taleplerinin işlenmesini önler.

Sisteminizin durumunu değiştirebilecek istekleri işlemeden önce (Örneğin, bir kullanıcı bir posta listesine abone olur veya abonelikten çıkar), aşağıdakileri kontrol edin:

Origin başlığı ayarlanmışsa:

  1. Kaynak aşağıdaki değerlerden biriyle eşleşmiyorsa, durdurun ve bir hata yanıtı döndürün:
  • <publisher's domain>.cdn.ampproject.org
  • yayıncının kaynağı (yani sizinki)

burada * gerçek bir yıldız işaretini ( * ) değil, bir joker karakter eşleşmesini temsil eder.

  1. Aksi takdirde, isteği işleyin.

Origin bağlığı AYARLANMAMIŞSA:

  1. İsteğin AMP-Same-Origin: true başlığını içerdiğini doğrulayın. İstek bu başlığı içermiyorsa, durdurun ve bir hata yanıtı verin.
  2. Aksi takdirde, isteği işleyin.

Örnek izlenecek yol: CORS isteklerini ve yanıtlarını işleme

Uç noktanıza CORS isteklerini hesaba katmak için iki senaryo vardır:

  1. Aynı kaynaktan gelen bir istek.
  2. Önbelleğe alınmış bir kaynaktan (AMP önbelleğinden) bir istek.

Bu senaryoları bir örnekle ele alalım. Örneğimizde, article-amp.html. adlı bir AMP sayfasını barındıran example.com sitesini yönetiyoruz. AMP sayfası, yine example.com'da barındırılan bir data.json dosyasından dinamik verileri almak için bir aamp-list içeriyor. AMP sayfamızdan gelen data.json dosyamıza gelen istekleri işlemek istiyoruz. Bu istekler, aynı kaynaktaki (önbelleğe alınmamış) AMP sayfasından veya farklı bir kaynaktaki (önbelleğe alınmış) AMP sayfasından olabilir.

İzin verilen kaynaklar

CORS ve AMP hakkında bildiklerimize dayanarak (yukarıdaki CORS isteklerini doğrulamak), örneğimiz için aşağıdaki etki alanlarından gelen isteklere izin vereceğiz:

  • example.com --- Yayıncının etki alanı
  • example-com.cdn.ampproject.org --- Google AMP Önbelleği alt etki alanı

İzin verilen istekler için yanıt başlıkları

İzin verilen kaynaklardan gelen istekler için yanıtımız aşağıdaki başlıkları içerecektir:

Access-Control-Allow-Origin: <origin>

Bunlar, CORS yanıtımıza dahil edebileceğimiz ek yanıt başlıklarıdır:

Access-Control-Allow-Credentials: true
Content-Type: application/json
Access-Control-Max-Age: <delta-seconds>
Cache-Control: private, no-cache

Sözde CORS mantığı

CORS isteklerini ve yanıtlarını işleme mantığımız aşağıdaki sözde kodda basitleştirilebilir:

IF CORS header present
IF origin IN allowed-origins
allow request & send response
ELSE
deny request
ELSE
IF "AMP-Same-Origin: true"
allow request & send response
ELSE
deny request

CORS örnek kodu

CORS isteklerini ve yanıtlarını işlemek için kullanabileceğimiz örnek bir JavaScript işlevi:

function assertCors(req, res, opt_validMethods, opt_exposeHeaders) {
var unauthorized = 'Unauthorized Request';
var origin;
var allowedOrigins = [
'https://example.com',
'https://example-com.cdn.ampproject.org',
'https://cdn.ampproject.org',
];
var allowedSourceOrigin = 'https://example.com'; //publisher's origin
// If same origin
if (req.headers['amp-same-origin'] == 'true') {
origin = sourceOrigin;
// If allowed CORS origin & allowed source origin
} else if (
allowedOrigins.indexOf(req.headers.origin) != -1 &&
sourceOrigin == allowedSourceOrigin
) {
origin = req.headers.origin;
} else {
res.statusCode = 403;
res.end(JSON.stringify({message: unauthorized}));
throw unauthorized;
}

res.setHeader('Access-Control-Allow-Credentials', 'true');
res.setHeader('Access-Control-Allow-Origin', origin);
}

Not: Çalışan bir kod örneği için bkz. amp-cors.js.

Senaryo 1: Aynı kaynaktaki AMP sayfasından istek alma

Aşağıdaki senaryoda, article-amp.html sayfası data.json dosyasını ister; kaynaklar aynıdır.

İsteği incelersek şunları bulacağız:

Request URL: https://example.com/data.json
Request Method: GET
AMP-Same-Origin: true

Bu istek aynı kaynaktan geldiğinden, Origin başlığı yoktur, ancak AMP-Same-Origin: true özel AMP istek başlığı mevcuttur. Aynı kaynaktan olduğu için bu talebe izin verebiliriz (https://example.com).

Yanıt başlıklarımız şöyle olacaktır:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://example.com

Senaryo 2: Önbelleğe alınmış AMP sayfasından istek alma

Aşağıdaki senaryoda, Google AMP Önbelleğinde önbelleğe alınan article-amp.html sayfası data.json dosyasını ister; kaynaklar farklıdır.

İsteği incelersek şunları bulacağız:

Request URL: https://example.com/data.json
Request Method: GET
Origin: https://example-com.cdn.ampproject.org

Bu istek bir Origin başlığı içerdiğinden, izin verilen bir kaynaktan olduğunu doğrularız. İzin verilen bir kaynaktan olduğu için bu isteğe izin verebiliriz.

Yanıt başlıklarımız şöyle olacaktır:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://example-com.cdn.ampproject.org

Önbelleğe alınmış yazı tipleri ile çalışma

Google AMP Önbelleği, AMP sayfasının hızını optimize etmek için AMP HTML belgelerini, resimlerini ve yazı tiplerini önbelleğe alır. AMP sayfasını hızlı hale getirirken, önbelleğe alınmış kaynakların güvenliğini sağlamada da dikkatli olmak istiyoruz. AMP önbelleğinin kaynağının Access-Control-Allow-Origin değerine dikkat ederek, genellikle yazı tipleri için önbelleğe alınmış kaynaklara nasıl yanıt verdiğine dair bir değişiklik yapacağız.

Geçmiş davranış (Ekim 2019'dan önce)

Bir AMP sayfası @font-face src özniteliğinden https://example.com/some/font.ttf yüklerken, AMP Önbelleği yazı tipi dosyasını önbelleğe alacak ve aşağıdaki gibi joker karakter Access-Control-Allow-Origin'e sahip olarak kaynağı sunacaktır.

  • URL https://example-com.cdn.ampproject.org/r/s/example.com/some/font.tff
  • Access-Control-Allow-Origin: *

Yeni davranış (Ekim 2019 ve sonrası)

Mevcut uygulama izin verici olsa da, bu, çapraz kaynak sitelerden yazı tiplerinin beklenmedik şekilde kullanılmasına yol açabilir. Bu değişiklikte AMP Önbelleği, kaynak sunucunun yanıt verdiği aynı Access-Control-Allow-Origin değeriyle yanıt vermeye başlayacaktır. Yazı tiplerini önbelleğe alınmış AMP belgesinden düzgün şekilde yüklemek için, AMP Önbelleği kaynağını başlık aracılığıyla kabul etmeniz gerekir.

Örnek bir uygulama şöyle olacaktır:

function assertFontCors(req, res, opt_validMethods, opt_exposeHeaders) {
var unauthorized = 'Unauthorized Request';
var allowedOrigins = [
'https://example.com',
'https://example-com.cdn.ampproject.org',
];
// If allowed CORS origin
if (allowedOrigins.indexOf(req.headers.origin) != -1) {
res.setHeader('Access-Control-Allow-Origin', req.headers.origin);
} else {
res.statusCode = 403;
res.end(JSON.stringify({message: unauthorized}));
throw unauthorized;
}
}

Örnek olarak, https://example.com/amp.html'de /some/font.ttf dosyasını yüklemek isterseniz, kaynak sunucu aşağıdaki gibi Access-Control-Allow-Origin başlığıyla yanıt vermelidir.

Yazı tipi dosyanıza herhangi bir kaynaktan erişilebiliyorsa, joker karakter Access-Control-Allow-Origin ile yanıt verebilirsiniz, AMP Önbelleği de bu değeri yansıtacaktır. Yani bu, Access-Control-Allow-Origin: * ile yanıt vereceği anlamına gelir. Zaten bu ayara sahipseniz, hiçbir şeyi değiştirmeye gerek yoktur.

Bu değişikliği Ekim 2019 ortalarında yapmayı planlıyoruz ve kendi kendine barındırılan yazı tiplerini kullanan her AMP yayıncısının etkilenip etkilenmediğini kontrol etmesini bekliyoruz.

Yayın planı

  • 30-09-2019: Sürüm, bu değişikliğin hangi etki alanları için geçerli olduğu konusunda daha kesin denetim içerir. Bu derleme, bu hafta içinde kullanıma sunulacaktır.
  • 07/10/2019: Manuel test için test alanları etkinleştirilecektir.
  • 14/10/2019: Özellik genel olarak kullanıma sunulacaktır. (Ancak testin nasıl gittiğine bağlı olarak).

İlgili sorununu buradan takip edin.

AMP'de CORS'u test etme

AMP sayfalarınızı test ederken, AMP sayfalarınızın önbelleğe alınmış sürümlerinden testler eklediğinizden emin olun.

Sayfayı önbellek URL'si ile doğrulayın

Önbelleğe alınmış AMP sayfanızın doğru şekilde oluşturulduğundan ve çalıştığından emin olmak için:

  1. Tarayıcınızdan, AMP Önbelleğinin AMP sayfanıza erişmek için kullanacağı URL'yi açın. Önbellek URL biçimini bu araçtan Örneklerle AMP'den belirleyebilirsiniz.

Örneğin:

  • URL: https://amp.dev/documentation/guides-and-tutorials/start/create/
  • AMP Önbelleği URL biçimi: https://www-ampproject-org.cdn.ampproject.org/c/s/www.ampproject.org/docs/tutorials/create.html
  1. Tarayıcınızın geliştirme araçlarını açın; hata olmadığını ve tüm kaynakların doğru yüklendiğini doğrulayın.

Sunucu yanıtı başlıklarınızı doğrulayın

Sunucunuzun doğru HTTP yanıt başlıklarını gönderdiğini doğrulamak için curl komutunu kullanabilirsiniz. curl komutunda, istek URL'sini ve eklemek istediğiniz özel başlıkları belirtin.

Sözdizimi: curl <request-url> -H <custom-header> - I

Aynı kaynaktan test isteği

Aynı kaynaklı bir istekte, AMP sistemi özel AMP-Same-Origin:true başlığını ekler.

İşte https://ampbyexample.com'dan examples.json dosyasına (aynı etki alanında) bir isteği test etmek için curl komutumuz:

curl 'https://amp.dev/static/samples/json/examples.json' -H 'AMP-Same-Origin: true' -I

Komuttan elde edilen sonuçlar doğru yanıt başlıklarını gösterir (not: fazla bilgiler kırpılmıştır):

HTTP/2 200
access-control-allow-headers: Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token
access-control-allow-credentials: true
access-control-allow-origin: https://ampbyexample.com
access-control-allow-methods: POST, GET, OPTIONS

Önbelleğe alınmış AMP sayfasından test isteği

Aynı etki alanından (yani önbellek) olmayan bir CORS isteğinde, origin başlığı isteğin bir parçasıdır.

Google AMP Önbelleğinde önbelleğe alınmış AMP sayfasından examples.json{/code0 dosyasına bir isteği test etmek için curl komutumuz şu şekildedir:

curl 'https://amp.dev/static/samples/json/examples.json' -H 'origin: https://ampbyexample-com.cdn.ampproject.org' -I

Komuttan elde edilen sonuçlar doğru yanıt başlıklarını gösterir:

HTTP/2 200
access-control-allow-headers: Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token
access-control-allow-credentials: true
access-control-allow-origin: https://ampbyexample-com.cdn.ampproject.org
access-control-allow-methods: POST, GET, OPTIONS