RE:NODE

ვებ ჰოსტინგი11 წუთის საკითხავი

HTTP caching header-ები ახსნილი: Cache-Control და ETag

რას აკეთებს Cache-Control-ის თითოეული დირექტივა, როგორ მუშაობს ETag და 304 და ორსაფეხურიანი წესი, რომელიც საიტს აჩქარებს ძველი HTML-ის მიწოდების გარეშე.

0 მკითხველი

თითქმის ყველა საიტს ერთი და იგივე ორი წესი სჭირდება. ფაილებს, რომელთა სახელში კონტენტის hash დევს - app.9f2c1b.js - ეძლევა Cache-Control: public, max-age=31536000, immutable, რადგან სახელი იცვლება, როცა კონტენტი იცვლება, და ბრაუზერს აღარასოდეს სჭირდება კითხვა. HTML-ს ეძლევა Cache-Control: no-cache, რომელიც გვერდს ინახავს, მაგრამ ხელახლა ამოწმებს, ამიტომ deploy მაშინვე ჩანს და განმეორებითი ვიზიტი ერთ იაფ 304-ს ჯდება სრული ჩამოტვირთვის ნაცვლად.

ეს ვებ ქეშირების ოთხმოცდაათი პროცენტია. ამ პოსტის დანარჩენი ნაწილი დანარჩენი ათი პროცენტია: რას ნიშნავს ყოველი დირექტივა სინამდვილეში, რატომ იგნორირდება შენი header-ები და რას აკეთებს CDN ბრაუზერისგან განსხვავებულად.

ქეშები შენს სერვერსა და ვიზიტორს შორის#

პასუხი უფრო მეტ ადგილას შეიძლება შეინახოს, ვიდრე უმეტესობას წარმოუდგენია, და თითოეული ოდნავ განსხვავებულ წესებს ემორჩილება.

requestმხოლოდ miss-ისასგადაგზავნილიაწყვეტს Cache-Controlბრაუზერის ქეშიერთი ვიზიტორი, დისკზეCDN ან საერთო ქეშიბევრი ვიზიტორიReverse proxyTLS და მარშრუტიზაციაშენი სერვერიადგენს header-ებს
სად შეიძლება პასუხის შენახვა უკან მიმავალ გზაზე

განსხვავება, რომელიც მნიშვნელოვანია, არის private და shared. ბრაუზერის ქეში ერთ ადამიანს ეკუთვნის, ამიტომ მას შეუძლია მისი ანგარიშის გვერდი შეინახოს. CDN ყველას საერთოა, ამიტომ არ უნდა შეინახოს - და private დირექტივა არის გზა, ამის სათქმელად. ამის შებრუნება არის გზა, რომლითაც ერთი მომხმარებლის შეკვეთის დადასტურება მეორეს მიეწოდება, რაც ცუდი დღეა, რომელიც header-ით იწყება.

შენი reverse proxy შუაში დგას და ჩვეულებრივ საერთოდ არ ქეშირებს, თუ არ დააკონფიგურირებ. RE:NODE-ზე proxy სლოტი TLS-ს წყვეტს და შენს სერვერზე აგზავნის; ქეშირების გადაწყვეტილებები შენს აპლიკაციასა და იმ CDN-ს რჩება, რომელსაც წინ დააყენებ.

Cache-Control, დირექტივა-დირექტივა#

Cache-Control არის პასუხის header, რომელიც მძიმეებით გამოყოფილ სიას ატარებს. ეს დირექტივებია, რომლებიც ადგილს იმსახურებენ:

დირექტივაეხებარას ნიშნავს
max-age=600ყველა ქეშსახალია 600 წამი ახლიდან
s-maxage=600მხოლოდ საერთო ქეშებსCDN-ებისა და proxy-ებისთვის max-age-ს გადაფარავს
publicყველა ქეშსშეიძლება შეინახოს მაშინაც, თუ მოთხოვნა ავტორიზებული იყო
privateმხოლოდ ბრაუზერსსაერთო ქეშმა არ უნდა შეინახოს
no-cacheყველა ქეშსშეინახე, მაგრამ ყოველი ხელახლა გამოყენებამდე შეამოწმე
no-storeყველა ქეშსსაერთოდ არ ჩაწერო
must-revalidateყველა ქეშსგაფუჭების შემდეგ არასოდეს მიაწოდო შემოწმების გარეშე
immutableბრაუზერსარ შეამოწმო, გადატვირთვისასაც კი
stale-while-revalidate=60ყველა ქეშს60 წამი მოძველებული მიაწოდე, სანამ ახალს იღებ
stale-if-error=86400ყველა ქეშსმოძველებული მიაწოდე, თუ origin ვარდება

ამათგან ორს მუდმივად არასწორად კითხულობენ. `no-cache` არ ნიშნავს „ნუ ქეშირებ“. ის ნიშნავს: ქეშირება და ყოველთვის ჯერ კითხვა, რაც HTML-ისთვის ზუსტად ის არის, რაც გინდა: მოგზაურობა პატარაა, როცა არაფერი შეცვლილა. no-store არის ის, რაც ნიშნავს „ასლი არ შეინახო“, და ის განკუთვნილია პასუხებისთვის, რომლებიც დისკს არასოდეს უნდა შეეხოს - საბანკო ამონაწერი, ერთჯერადი token, პაროლის აღდგენის გვერდი.

immutable არის დირექტივა, რომელიც hash-იან asset-ებს განმეორებით ვიზიტზე ნამდვილად უფასოს ხდის. მის გარეშე ბრაუზერის გადატვირთვა ყველა ქეშირებულ ფაილს ხელახლა ამოწმებს და თითო asset-ზე ერთ მოგზაურობას იხდი, რომ გითხრან, არაფერი შეცვლილა. მასთან ბრაუზერი შემოწმებას max-age-ის მთელი ხანგრძლივობის განმავლობაში მთლიანად ტოვებს. ის უსაფრთხოა მხოლოდ URL-ზე, რომლის კონტენტიც არასოდეს შეიძლება შეიცვალოს, და ზუსტად ამას იძლევა კონტენტის hash.

stale-while-revalidate არის ყველაზე იაფი წარმადობის მოგება, რომელსაც უმეტესი საიტი არასოდეს რთავს. max-age=60, stale-while-revalidate=600 ნიშნავს, რომ ქეშირებული გვერდი მყისიერად მიეწოდება უარეს შემთხვევაში თერთმეტი წუთის განმავლობაში, ხოლო განახლება ფონზე ხდება და არა ვიზიტორის თვალწინ.

თუ ქეშირების header-ებს საერთოდ არ აგზავნი, ქეშებს გამოცნობის უფლება აქვთ. RFC 9111 ეურისტიკულ სიახლეს Last-Modified-ის საფუძველზე უშვებს - ჩვეულებრივ დოკუმენტის ბოლო ცვლილებიდან გასული დროის ათი პროცენტი - ამიტომ ფაილი, რომელიც ერთი წლის წინ შეიცვალა, შეიძლება გზაზე მყოფმა რამემ კვირების განმავლობაში ქეშოს. დუმილი არ არის იგივე, რაც „ნუ ქეშირებ“.

ETag, Last-Modified და 304#

სიახლე ამბობს, რამდენ ხანს შეუძლია ქეშს პასუხის ხელახლა გამოყენება კითხვის გარეშე. ვალიდაცია არის ის, რაც ხდება, როცა ის კითხულობს.

  • Last-Modified: Wed, 10 Sep 2026 09:41:12 GMT - დროის ნიშნული ერთი წამის სიზუსტით.
  • ETag: "6f9a2c-1b4d" - გაუმჭვირვალე token, რომელიც იცვლება, როცა კონტენტი იცვლება. W/"..." სუსტ tag-ს აღნიშნავს, რაც ნიშნავს სემანტიკურად ექვივალენტურს და არა ბაიტ-ბაიტ იდენტურს.

შემდეგ მოთხოვნაზე ბრაუზერი აგზავნის If-Modified-Since-ს ან If-None-Match-ს იმ მნიშვნელობით, რომელიც უჭირავს. თუ არაფერი შეცვლილა, სერვერი პასუხობს 304 Not Modified-ით header-ებით და სხეულის გარეშე, და ბრაუზერი იყენებს ასლს, რომელიც უკვე აქვს.

bash
$ curl -sI https://example.com/style.css | grep -i -E "etag|cache-control|last-modified"$ curl -sI -H 'If-None-Match: "6f9a2c-1b4d"' https://example.com/style.css | head -1HTTP/2 304

304 ბაიტებს ზოგავს, მაგრამ მოგზაურობას - არა. 120 ms დაყოვნების კავშირზე ორმოცი asset, რომლებიც ყველა 304-ს აბრუნებს, მაინც ნელი შეგრძნების გვერდს გიჯდება. ეს არის მთელი არგუმენტი გრძელი max-age-ისა immutable-ით ხელმოწერილ ფაილებზე: ყველაზე სწრაფი მოთხოვნა ის არის, რომელიც არასოდეს ხდება.

nginx სტატიკური ფაილებისთვის ETag-ს ავტომატურად აგენერირებს ცვლილების დროისა და ზომიდან, რაც სერვერებს შორის სტაბილურია, სანამ ფაილებს ერთი და იგივე დროის ნიშნულები აქვთ. deploy, რომელიც ყველა ფაილს ახალი mtime-ით გადაწერს, საიტზე ყველა ETag-ს აუქმებს იქაც, სადაც კონტენტი იდენტურია, ამიტომ როცა ეს მნიშვნელოვანია, გამოიყენე კოპირების მეთოდი, რომელიც დროის ნიშნულებს ინარჩუნებს. აპლიკაციის framework-ები ჩვეულებრივ პასუხის სხეულს hash-ავენ, რაც სწორია, მაგრამ CPU-ს ყოველ მოთხოვნაზე ჯდება.

ორსაფეხურიანი სტრატეგია#

თითქმის ყველა საიტი აქ უნდა მივიდეს:

რაCache-Controlრატომ
HTML გვერდებიpublic, no-cacheყოველთვის ახალია, იაფი 304 განმეორებაზე
Hash-იანი CSS, JS, შრიფტებიpublic, max-age=31536000, immutableსახელი იცვლება, როცა კონტენტი იცვლება
Hash-ის გარეშე CSS და JSpublic, max-age=3600ვერ დაამტკიცებ, რომ არ შეცვლილა
ატვირთული სურათებიpublic, max-age=2592000იშვიათად იცვლება ადგილზე
შესული მომხმარებლის გვერდებიprivate, no-storeარასოდეს საერთო ქეშში
API პასუხებიprivate, max-age=0 ან no-storeგადაწყვიტე endpoint-ის მიხედვით და ნუ გამოიცნობ

ერთი წელი - 31536000 წამი - max-age-ის ჩვეულებრივი მაქსიმუმია და უფრო დიდი რიცხვით არაფერს იგებ. თუ შენი build უკვე hash-იან ფაილების სახელებს წერს, როგორც ყველა თანამედროვე bundler აკეთებს, ზედა ორი მწკრივი მთელ საიტს ფარავს; სტატიკური საიტის ჰოსტინგი შეიცავს nginx ბლოკებს კონტექსტში.

საფეხური, რომელიც პრობლემას ქმნის, მესამეა: ფიქსირებულ URL-ზე მყოფი სტილის ფაილი, რომელსაც ადგილზე ცვლი. მისთვის უსაფრთხო გრძელი ქეში არ არსებობს, რადგან ზოგი ვიზიტორი ძველ ასლს იმდენ ხანს შეინახავს, რამდენსაც უთხარი. გამოსავალი უფრო მოკლე ქეში არ არის, ეს სხვა URL-ია. ყველა build ინსტრუმენტს შეუძლია გამოსავლის fingerprint-ირება; თუ HTML-ს ხელით წერ, დაუმატე ვერსიის query - style.css?v=7 - და შეცვალე, როცა ცვლი. Query string ბრაუზერებისა და უმეტესი CDN-ის ქეშის გასაღების ნაწილია, თუმცა ზოგი CDN შეიძლება ისე დაკონფიგურირდეს, რომ მათ უგულებელყოფდეს, რაც შენს cache buster-ს არაფრად აქცევს.

Vary ქეშებს ეუბნება, მოთხოვნის რომელი header-ები ცვლის პასუხს. ის აუცილებელი და საშიშია თანაბრად, რადგან ყოველი მნიშვნელობა ქეშის მიერ შესანახი ასლების რაოდენობას ამრავლებს.

  • Vary: Accept-Encoding - სწორია და საჭიროა, როცა კომპრესიას იყენებ. მის გარეშე ქეშმა შეიძლება gzip-ით დაარქივებული სხეული ისეთ კლიენტს მისცეს, რომელსაც არ მოუთხოვია.
  • Vary: Cookie - ტექნიკურად სწორია გვერდზე, რომელიც მომხმარებლის მიხედვით განსხვავდება, და პრაქტიკაში ნიშნავს, რომ საერთო ქეში არასოდეს იღებს hit-ს, რადგან ყველა ვიზიტორს განსხვავებული cookie აქვს.
  • Vary: User-Agent - ქეშს ათასობით ვარიანტად ანაწევრებს. ერიდე.

Cookie-ები ქეშის მეორე ჩუმი მკვლელია. პასუხი Set-Cookie-ით საერთო ქეშმა სხვა ადამიანების მიერ გამოსაყენებლად ვერ შეინახავს, და უმეტესი CDN ქეშს უბრალოდ გვერდს უვლის, როცა მას ხედავს. ეს სწორი ნაგულისხმევია და სწორედ ამიტომ შეუძლია ანალიტიკის ან თანხმობის სკრიპტს, რომელიც ყოველ გვერდზე cookie-ს სერვერზე აყენებს, ქეშის hit-ის მაჩვენებელი განახევროს ისე, რომ ვინმემ შეამჩნიოს.

PHP ამას ნაგულისხმევად გიკეთებს. session_start()-ის პირველი გამოძახება მთელ პასუხზე აგზავნის:

code
Expires: Thu, 19 Nov 1981 08:52:00 GMTCache-Control: no-store, no-cache, must-revalidatePragma: no-cache

ეს არის session.cache_limiter, რომელიც თავის საქმეს აკეთებს, და სწორია გვერდისთვის, რომელიც ვინმეს ანგარიშს აჩვენებს. ის არასწორია საჯარო გვერდისთვის, რომელიც მიზეზის გარეშე სესიას იწყებს. ან ნუ დაიწყებ სესიას გვერდებზე, რომლებსაც ის არ სჭირდება, ან დააყენე session_cache_limiter('public') session_start()-მდე და აიღე პასუხისმგებლობა იმაზე, რასაც აკეთებ.

WordPress-ი და უმეტესი CMS-ის გვერდის ქეში იგივე ლოგიკას მისდევს: ყველაფერი login cookie-ით ქეშს მთლიანად გვერდს უვლის, სწორედ ამიტომ ხედავს ადმინი, რომელიც საიტს ამოწმებს, ნელ გზას და იტყობინება, რომ ქეშირება არ მუშაობს. შეამოწმე private ფანჯარაში. WordPress-ის სიჩქარე და ქეშირება ფენებს ამ კონკრეტულ შემთხვევაში გადის.

CDN-ები და საერთო ქეშები#

CDN არის საერთო ქეში ბევრ ადგილას. ის იგივე header-ებს კითხულობს, ორი დამატებით, რომლებიც ღირს ცოდნად.

s-maxage მხოლოდ საერთო ქეშებს ეხება, რაც საშუალებას გაძლევს HTML ბრაუზერებში ახალი გქონდეს და edge-ზე ქეშირებული: Cache-Control: public, max-age=0, s-maxage=600, stale-while-revalidate=3600. ბრაუზერები ყოველ ჯერზე ამოწმებენ, CDN ათი წუთი საკუთარი ასლიდან ემსახურება და ფონზე ახლდება, და შენი origin ტრაფიკის ნაწილს ხედავს. საიტისთვის, რომლის გვერდებიც ყველასთვის ერთნაირია, ეს ყველაზე დიდი ცვლილებაა, რომლის გაკეთებაც შეგიძლია.

CDN-Cache-Control მიზნობრივი header-ია, რომელსაც მხოლოდ CDN-ები კითხულობენ, ამიტომ მათ სხვა ინსტრუქციებს აძლევ იმის შეხების გარეშე, რასაც ბრაუზერები ხედავენ. ძველი ინფრასტრუქტურა იმავე მიზნით Surrogate-Control-ს იყენებს. მხარდაჭერა განსხვავდება, ამიტომ დაეყრდნობამდე შეამოწმე შენი პროვაიდერის დოკუმენტაცია - Cloudflare ვებსაიტებისა და გეიმ სერვერებისთვის აღწერს, რას აკეთებს გავრცელებული მათგანი ამათთან.

CDN-ს ორი ოპერაციული ჩვევა მოჰყვება. პირველი: იცოდე, როგორ გაწმინდო, URL-ით და tag-ით, და გაწმენდა ჩადე შენს deploy სკრიპტში და არა runbook-ში, რომელსაც არავინ ხსნის. მეორე: წაიკითხე cache status header, რომელსაც შენი პროვაიდერი აგზავნის - HIT, MISS, EXPIRED, BYPASS - რადგან ის „მუშაობს თუ არა ქეშირება“ კამათიდან ფაქტად აქცევს. თუ BYPASS-ს ხედავ, მოძებნე cookie.

CDN ვერ გაასწორებს ნელ origin-ს დაუქეშავ მოთხოვნებზე. თითოეული გვერდის პირველი ვიზიტორი, თითოეულ ლოკაციაში, მაინც ელოდება შენს სერვერს, და ისევე ყოველი მოთხოვნა, რომელსაც cookie დაუქეშავს ხდის. TTFB, Core Web Vitals და ჰოსტინგი აღწერს, ლოდინის რომელი ნაწილის გამოსწორებაა შენზე.

Header-ების დაყენება#

nginx-ზე, სტატიკური asset-ები გაფართოებით და HTML ცალკე:

nginx
location ~* \.(?:css|js|woff2|avif|webp|png|jpg|svg)$ {    expires 1y;    add_header Cache-Control "public, max-age=31536000, immutable" always;    access_log off;}location ~* \.html$ {    add_header Cache-Control "public, no-cache" always;}

expires 1y; ადგენს როგორც ძველ Expires header-ს, ისე შესაბამის max-age-ს, სწორედ ამიტომ მოსდევს მას აშკარა add_header: გინდა დამატებითი დირექტივები.

nginx-ის ხაფანგი, რომელიც ყველას ეჯახება: add_header დირექტივები მშობელი ბლოკიდან მემკვიდრეობით გადადის მხოლოდ მაშინ, თუ მიმდინარე ბლოკს საკუთარი არ აქვს. დაამატე ერთი add_header location-ის შიგნით და მშობელ server ბლოკში დაყენებული ყველა header ამ პასუხებიდან ქრება - შენი უსაფრთხოების header-ების ჩათვლით. თუ location-ში add_header-ს იყენებ, გაიმეორე ყველაფერი, რაც მშობელმა დააყენა. always flag header-ს შეცდომის პასუხებზეც ავრცელებს და არა მხოლოდ 2xx-სა და 3xx-ზე.

PHP-დან დააყენე ის ნებისმიერ output-მდე და გახსოვდეს, რომ output buffering-ის პარამეტრები წყვეტს, რამდენად ადრეა „ნებისმიერ output-მდე“ - php.ini-ს პარამეტრები, რომლებიც მნიშვნელოვანია ფარავს ისეთებს, რომლებიც კბენს:

code
header('Cache-Control: public, max-age=300, stale-while-revalidate=600');

აპლიკაციის framework-იდან გამოიყენე მისი response helper-ები და არა ნედლი header-ები, რადგან framework-მა შეიძლება საკუთარი მოგვიანებით დაამატოს, და ბოლოს დაწერილი იმარჯვებს.

იმის შემოწმება, რასაც სინამდვილეში აგზავნი#

არასოდეს ენდო კონფიგურაციას; წაიკითხე მავთული. ერთი ბრძანება უმეტესს გეუბნება:

bash
$ curl -sI https://example.com/ | grep -i -E "cache-control|etag|age|vary|set-cookie"

რას უყურო, თანმიმდევრობით:

  1. `Set-Cookie` საჯარო გვერდზე. თითქმის ყოველთვის შემთხვევითობაა და საერთო ქეშირებას თიშავს.
  2. `Age`. მისი არსებობა ნიშნავს, რომ შენს წინ რაღაცამ შენახული ასლი მოგაწოდა, და მისი მნიშვნელობა ასლის ასაკია.
  3. `Vary`. ყველაფერი Accept-Encoding-ის გარდა მიზეზს საჭიროებს.
  4. წინააღმდეგობრივი დირექტივები. no-cache max-age=3600-თან ერთად დასაშვებია და დამაბნეველი; no-store ყველაფერს სჯობს.
  5. ბრაუზერის devtools-ის network პანელი. ზომის სვეტი, რომელიც აჩვენებს „disk cache“ ან „memory cache“ ქსელური დროის გარეშე, არის ის, როგორც გამოიყურება მომუშავე ქეში. გახსოვდეს, რომ hard reload ქეშს გვერდს უვლის და რეალურ გამოცდილებაზე არაფერს გეუბნება.

როცა header-ების ცვლილება თითქოს არაფერს აკეთებს, შეამოწმე ამ თანმიმდევრობით: ხომ არ გაძლევს წინ მდგომი CDN ძველ ასლს, ხომ არ გიჭერს შენი ბრაუზერი ცვლილებამდელ ასლს და ხომ არ გადაგფარავს კონფიგურაციაში უფრო ქვემოთ მდგომი location ბლოკი. დაახლოებით ოთხმოცი პროცენტი ეს ერთ-ერთი სამიდან არის.

FAQ#

რა განსხვავებაა no-cache-სა და no-store-ს შორის?

no-cache პასუხს ინახავს და ყოველი ხელახლა გამოყენებამდე ამოწმებს, ამიტომ მაინც იღებ 304-სა და სწრაფ გვერდს. no-store კრძალავს მის სადმე ჩაწერას. no-cache გამოიყენე HTML-ისთვის, რომელიც იცვლება, და no-store - მხოლოდ ნამდვილად სენსიტიური პასუხებისთვის - ის ასევე ბრაუზერის უკან/წინ ქეშს თიშავს, რაც ნავიგაციას უფრო ნელს ხდის.

ETag გამოვიყენო თუ Last-Modified?

ორივე, თუ უფასოა. Last-Modified ერთი წამის სიზუსტისაა და ფაილებისთვის კარგია; ETag ზუსტია და გენერირებულ პასუხებზეც მუშაობს. ორივეს გაგზავნა კლიენტს საშუალებას აძლევს, გამოიყენოს ის, რომელიც მას ურჩევნია. ETag-ები არ გამორთო, თუ არ გაქვს კონკრეტული მრავალსერვერიანი პრობლემა, რომელიც გაზომე.

რატომ არის ჩემი CSS ისევ ძველი ვერსია deploy-ის შემდეგ?

იმიტომ, რომ ბრაუზერებს უთხარი, შეინახონ. თუ URL არ შეცვლილა და გრძელი max-age გააგზავნე, ერთადერთი წამალი დროა ან ახალი URL. გააკეთე შენი asset-ების fingerprint-ირება, რომ ეს აღარ განმეორდეს, და გრძელი ქეში შეინახე ფაილებისთვის, რომელთა სახელებიც მათ კონტენტს აკოდირებს.

ეხმარება თუ არა ქეშირება საიტს ძალიან მცირე ტრაფიკით?

ეხმარება განმეორებით ვიზიტორებს და ეხმარება ყოველ გვერდის ჩატვირთვას პირველის შემდეგ, რაც ვიზიტორის გამოცდილების უმეტესობაა. არ ეხმარება პირველ მოთხოვნას ცივ ქეშზე. პატარა საიტისთვის უფრო დიდი მოგება ჩვეულებრივ თავად origin-ის სისწრაფეა, პლუს კომპრესია.

რამდენ ხანს უნდა ქეშირდებოდეს სურათები?

ოცდაათი დღე გონივრული ნაგულისხმევია ატვირთული მედიისთვის, ერთი წელი, თუ ფაილის სახელი hash-ს შეიცავს. მარცხის ფორმაა სურათის ადგილზე ჩანაცვლება და ძველის შენარჩუნება, ამიტომ ამჯობინე ახალი ფაილის ახალი სახელით ატვირთვა გადაწერას.

მოქმედებს ეს header-ები საძიებო რეიტინგზე?

პირდაპირ - არა. ისინი მოქმედებენ იმაზე, რამდენად სწრაფად იტვირთება გვერდები რეალური ვიზიტორებისთვის, რაც ველზე იზომება და Core Web Vitals-ის მეშვეობით რეიტინგის სიგნალებში შედის. ქეშირება მომხმარებლებისთვის ღირს გაკეთებად; რეიტინგი გვერდითი ეფექტია.


კომენტარები

სრულიად ანონიმურად: ანგარიშის, ელფოსტის და cookie-ის გარეშე. ინახება მხოლოდ სახელი, ტექსტი და დრო - სხვა არაფერი. ბმულების რაოდენობა ლიმიტირებულია.

0/2000