---
title: 'Güvenlik Başlıkları ve TLS'
source: 'https://academia.sh/tr/kurslar/backend-uretim/guvenlik-basliklari-ve-tls'
course: 'Sunucu Güvenliği ve Üretime Alma'
language: tr
updated: '2026-08-17T18:06:49+00:00'
license: 'CC BY-SA 4.0'
---

# Güvenlik Başlıkları ve TLS

Taşıma katmanı sertleştirmesinin sunucu tarafındaki ölçüsü: altı güvenlik başlığının on uçta kaç kayıt noktasında durduğu, tek katmana taşımanın dokunduğu on bir dosya, eksik başlık ile yazılmış ama etkisiz değerin hata üretmeden düşürdüğü yükümlülük sayısı ve aktarılan protokol başlığının üç ayar altında ürettiği yanlış geçme ile yanlış kalma.

Önceki ders sunucunun kaynaklar arası paylaşımdaki tek sözünün yanıt başlıkları olduğunu ve asıl
sorunun başlığın **hangi katmanda üretildiği** olduğunu gösterdi. Bu ders aynı soruyu yanıtın
taşıdığı öteki başlıklara taşıyor ve üç şey ölçüyor: bu başlıkların kaç uçta tekrarlandığı ve tek
katmana taşımanın kaç dosyaya dokunduğu; eksik ya da yanlış yazılmış bir başlığın hata üretmeden
ne düşürdüğü; uygulamanın "bu bağlantı şifreli" varsayımını nereden okuduğu ve o kaynak taklit
edilebildiğinde ne olduğu.

## Başlığın Sözleşmesi

Bir güvenlik başlığı, sunucunun uyumlu bir istemciye verdiği tek cümlelik bir yükümlülüktür;
yazılmadığında ortada bir hata değil, bir yükümlülüğün yokluğu vardır. Ölçülen şey cümlenin
kendisidir: yazılmış mı, yazılmışsa değeri o cümleyi gerçekten kuruyor mu.

```js
// sertlestirme.mjs — baslik kumesi
const tanim = (deger, eksikse, kural) => ({ deger, eksikse, etkili: (v) => kural.test(v.trim()) });

export const KUME = {
  "strict-transport-security":
    tanim("max-age=31536000; includeSubDomains", "ilk istek sifresiz denenebilir", /max-age=\s*[1-9]\d*/),
  "content-security-policy":
    tanim("default-src 'self'; frame-ancestors 'none'", "kaynak ve cerceve kisiti yok", /default-src(?![^;]*\*)/),
  "x-content-type-options":
    tanim("nosniff", "icerik turu tahmin edilebilir", /^nosniff$/i),
  "referrer-policy":
    tanim("no-referrer", "adres ve sorgu dizesi disariya tasinir", /^(no-referrer|same-origin|strict-origin)$/i),
  "x-frame-options":
    tanim("DENY", "gomulme kisiti yok", /^(deny|sameorigin)$/i),
  "permissions-policy":
    tanim("geolocation=(), camera=()", "yetenek kisiti yok", /=\(\)/),
};

export function denetle(b) {
  const eksik = [], etkisiz = [];
  for (const [ad, k] of Object.entries(KUME)) {
    if (b[ad] === undefined) eksik.push(ad);
    else if (!k.etkili(b[ad])) etkisiz.push(ad);
  }
  return { eksik, etkisiz, saglam: Object.keys(KUME).length - eksik.length - etkisiz.length };
}
```

`etkili` alanı dersin ikinci ölçüsünü taşıyor: bir başlık yok, var ve etkili ya da **var ama
etkisiz** olabilir. Üçüncüsü ayrı sayılır, çünkü yanıta bakıldığında ikinciyle karışır — başlık
listede görünür, adı doğrudur, yalnız değeri hiçbir yükümlülük kurmaz.

**BG6 (varsayım):** istemcinin yükümlülüğü sözleşme olarak yazıldı, tarayıcı davranışı olarak
değil; web tarafı Frontend Kalitesi kursunda kuruldu. Ölçülen şey yanıtın kendisidir: `node:http`
ile okunan başlıklar.

## Kaç Uçta Tekrarlanıyor

Ödünç sistemi dört servise bölünmüş ve dışarıya on uç veriyor. Başlıklar bugün her uç
işleyicisinin içinde ayrı ayrı yazılıyor.

```js
// sistem.mjs — uclar ve iki sapma
export const SERVIS = {
  katalog: ["ara", "kitap", "oneri"],
  odunc: ["al", "uzat", "iade"],
  uye: ["profil", "ceza"],
  rapor: ["gunluk", "aylik"],
};
export const UCLAR = Object.entries(SERVIS).flatMap(([s, us]) => us.map((u) => `/${s}/${u}`));

export const EKSIK = { "/rapor/aylik": 2 };   // son iki baslik yazilmamis
export const YANLIS = { "/odunc/uzat": ["x-content-type-options", "no-sniff"] };
```

```js
// dagilim.mjs — kayit noktasi ve tasima
import { mkdirSync, writeFileSync, readFileSync, readdirSync, rmSync } from "node:fs";
import { KUME } from "./sertlestirme.mjs";
import { UCLAR, EKSIK, YANLIS } from "./sistem.mjs";

const D = new URL("./uc/", import.meta.url).pathname;
rmSync(D, { recursive: true, force: true });
mkdirSync(D);

// her uc kendi yaziyor
for (const uc of UCLAR) {
  const [yh, yv] = YANLIS[uc] ?? [];
  const satir = Object.entries(KUME)
    .slice(0, Object.keys(KUME).length - (EKSIK[uc] ?? 0))
    .map(([h, k]) => `  y.setHeader(${JSON.stringify(h)}, ${JSON.stringify(h === yh ? yv : k.deger)});`);
  writeFileSync(D + uc.slice(1).replace("/", "-") + ".mjs",
    `export function isle(q, y) {\n${satir.join("\n")}\n  y.end(JSON.stringify({ uc: ${JSON.stringify(uc)} }));\n}\n`);
}

const tara = () => readdirSync(D).map((f) => {
  const eslesme = [...readFileSync(D + f, "utf8").matchAll(/setHeader\("([^"]+)",\s"([^"]*)"\)/g)];
  return { f, kayit: eslesme.length, saglam: eslesme.filter(([, h, v]) => KUME[h]?.etkili(v)).length };
});

const once = tara();
const tam = Object.keys(KUME).length;
console.log(`${once.length} uc dosyasi, ${tam} baslik`);
console.log(`kayit noktasi: ${once.length}   kayit satiri: ${once.reduce((t, d) => t + d.kayit, 0)}`);
console.log(`kumesi tam ve etkili olan dosya: ${once.filter((d) => d.saglam === tam).length}/${once.length}`);
for (const d of once.filter((d) => d.saglam !== tam))
  console.log(`  ${d.f.padEnd(16)} kayit ${d.kayit}, etkili ${d.saglam}`);

// tasima: satirlar silinir, katman yazilir
let dokunulan = 0;
for (const { f } of once) {
  const eski = readFileSync(D + f, "utf8"), yeni = eski.replace(/^\s*y\.setHeader\(.*\n/gm, "");
  if (yeni !== eski) { writeFileSync(D + f, yeni); dokunulan++; }
}
const katman = Object.entries(KUME)
  .map(([h, k]) => `  y.setHeader(${JSON.stringify(h)}, ${JSON.stringify(k.deger)});`).join("\n");
writeFileSync(D + "katman.mjs", `export function sertlestir(q, y) {\n${katman}\n}\n`);
dokunulan++;

const sonra = tara().filter((d) => d.f !== "katman.mjs");
console.log(`\ntasimada dokunulan dosya: ${dokunulan} (${once.length} uc + 1 katman)`);
console.log(`tasima sonrasi kayit noktasi: 1   uclarda kalan kayit satiri: ${sonra.reduce((t, d) => t + d.kayit, 0)}`);
console.log(`yeni bir uc eklendiginde yazilacak baslik satiri: uc basina ${tam}, tek katmanda 0`);
```

```
10 uc dosyasi, 6 baslik
kayit noktasi: 10   kayit satiri: 58
kumesi tam ve etkili olan dosya: 8/10
  odunc-uzat.mjs   kayit 6, etkili 5
  rapor-aylik.mjs  kayit 4, etkili 4

tasimada dokunulan dosya: 11 (10 uc + 1 katman)
tasima sonrasi kayit noktasi: 1   uclarda kalan kayit satiri: 0
yeni bir uc eklendiginde yazilacak baslik satiri: uc basina 6, tek katmanda 0
```

On uç, on kayıt noktası. Altmış olması gereken kayıt satırı elli sekiz: `/rapor/aylik` iki
başlık geride kalmış. `/odunc/uzat` ucunda ise değer `no-sniff` yazılmış — başlık orada, adı
doğru, değeri tanımsız bir belirteç. On dosyanın sekizi tam. İki sapmanın da nedeni kayıt noktası
sayısıdır: altı başlık on ayrı yerde yazıldığında sapma için on fırsat vardır ve hiçbiri kendini
göstermez.

Taşımanın maliyeti tek seferliktir: **on bir dosya**. Sonrasında kayıt noktası bir, on birinci uç
eklendiğinde yazılacak başlık satırı sıfır; uç başına kayıtta ise her yeni uç altı satır ister.

## Eksik Başlık ve Etkisiz Değer

Kaç yerde yazıldığı dosyalarda ölçüldü; yanıtta ne göründüğü ayrı bir sorudur ve gerçek bir
süreçten okunur.

```js
// olcum.mjs — yanit basliklari
import http from "node:http";
import { KUME, denetle } from "./sertlestirme.mjs";
import { UCLAR, EKSIK, YANLIS } from "./sistem.mjs";

const tam = () => Object.fromEntries(Object.entries(KUME).map(([h, k]) => [h, k.deger]));

const AYARLAR = [
  ["uc basina kayit", (uc) => {
    const b = tam(), [yh, yv] = YANLIS[uc] ?? [];
    for (const h of Object.keys(b).slice(Object.keys(b).length - (EKSIK[uc] ?? 0))) delete b[h];
    if (yh) b[yh] = yv;
    return b;
  }],
  ["tek katman", () => tam()],
  ["tek katman, yanlis deger", () => ({ ...tam(), "strict-transport-security": "max-age=0" })],
];

const baslat = (uret) => new Promise((c) => {
  const s = http.createServer((q, y) => {
    y.writeHead(200, { "content-type": "application/json", ...uret(q.url) });
    y.end(JSON.stringify({ uc: q.url }));
  });
  s.listen(0, "127.0.0.1", () => c(s));
});

const iste = (port, uc) => new Promise((c) =>
  http.get({ host: "127.0.0.1", port, path: uc }, (y) => { y.resume(); c(y); }));

console.log(`${UCLAR.length} uc, ${Object.keys(KUME).length} baslik, ayar basina ${UCLAR.length} istek\n`);
console.log(`${"ayar".padEnd(25)}${"200".padStart(5)}${"hata".padStart(6)}${"bayt".padStart(7)}` +
  `${"sozlesmesi tam uc".padStart(19)}${"eksik".padStart(7)}${"etkisiz".padStart(9)}`);

const ayrinti = [];
for (const [ad, uret] of AYARLAR) {
  const s = await baslat(uret);
  let [iki, bayt, saglamUc, eksik, etkisiz] = [0, 0, 0, 0, 0];
  for (const uc of UCLAR) {
    const y = await iste(s.address().port, uc);
    if (y.statusCode === 200) iki++;
    for (const h of Object.keys(KUME)) if (y.headers[h]) bayt += h.length + y.headers[h].length + 4;
    const d = denetle(y.headers);
    if (d.saglam === Object.keys(KUME).length) saglamUc++;
    else ayrinti.push([ad, uc, d]);
    eksik += d.eksik.length; etkisiz += d.etkisiz.length;
  }
  s.close();
  console.log(ad.padEnd(25) + String(iki).padStart(5) + "0".padStart(6) + String(bayt).padStart(7) +
    `${saglamUc}/${UCLAR.length}`.padStart(19) + String(eksik).padStart(7) + String(etkisiz).padStart(9));
}

console.log(`\nsozlesmesi eksilen uclar ve sessiz sonuc:`);
for (const [ad, uc, d] of ayrinti.slice(0, 4)) {
  const not = ["eksik", "etkisiz"].flatMap((t) => d[t].map((h) => `${t} ${h} -> ${KUME[h].eksikse}`));
  console.log(`  ${ad.padEnd(25)}${uc.padEnd(15)}${not.join("; ")}`);
}
console.log(`  ... "tek katman, yanlis deger" ayarinda ayni satir ${UCLAR.length} ucun ${UCLAR.length} tanesinde tekrarlaniyor`);
```

```
10 uc, 6 baslik, ayar basina 10 istek

ayar                       200  hata   bayt  sozlesmesi tam uc  eksik  etkisiz
uc basina kayit             10     0   2591               8/10      2        1
tek katman                  10     0   2660              10/10      0        0
tek katman, yanlis deger    10     0   2400               0/10      0       10

sozlesmesi eksilen uclar ve sessiz sonuc:
  uc basina kayit          /odunc/uzat    etkisiz x-content-type-options -> icerik turu tahmin edilebilir
  uc basina kayit          /rapor/aylik   eksik x-frame-options -> gomulme kisiti yok; eksik permissions-policy -> yetenek kisiti yok
  tek katman, yanlis deger /katalog/ara   etkisiz strict-transport-security -> ilk istek sifresiz denenebilir
  tek katman, yanlis deger /katalog/kitap etkisiz strict-transport-security -> ilk istek sifresiz denenebilir
  ... "tek katman, yanlis deger" ayarinda ayni satir 10 ucun 10 tanesinde tekrarlaniyor
```

Otuz isteğin otuzu 200 döndü; hata sayısı üç ayarda da sıfır. Tek nicel fark sertleştirme
baytındadır: 2591, 2660, 2400 — ve **en az bayt üreten ayar, sözleşmesi on uçtan sıfırında tam
olan ayardır.** Yanıt boyunu izleyen bir ölçüm bu üç ayarı doğruluk sırasına koyamaz.

`uc basina kayit` dosyalardaki sapmayı yanıta taşıyor: iki eksik yükümlülük, bir etkisiz değer,
sekiz sağlam uç. `tek katman` sapmayı sıfırlıyor. Üçüncü satır ise tek katmanın öbür yüzüdür:
başlık on ucun onunda var, adı doğru, biçimi geçerli, ama `max-age` sıfır olduğu için hiçbir
yükümlülük kurmuyor — tek yerdeki tek karakterlik fark sözleşmesi tam uç sayısını 10/10'dan
0/10'a düşürdü, durum kodu ve gövde değişmeden.

Bu, kayıt noktasını teke indirme kararını geri almaz; ölçünün nereye konacağını söyler. Tek
katman sapmayı bitirir ve değer riskini yoğunlaştırır; ikisini birden yakalayan tek şey
`denetle` gibi bir denetimin yapılandırmanın yanında değil **yanıtın üzerinde** çalışmasıdır.

## Şifreli Bağlantı Varsayımı

Kümedeki ilk başlık ötekilerden bir yönüyle ayrılır: yalnız şifreli bir bağlantı üzerinde
anlamlıdır ve uygulama bağlantının şifreli olduğunu doğrudan göremez. TLS sonlandırma
uygulamanın kendisinde değil, önündeki ters vekilde yapılıyor; sonlandırmanın hangi katmanda
durduğu ve maliyeti yük dengeleme kursunda ölçüldü, burada tekrarlanmıyor. Uygulamaya kalan tek
bilgi vekilin aktardığı bir başlıktır.

**BG7 (varsayım):** yerel bağlantılar şifresizdir; vekil üzerinden gelen istek şifreli, doğrudan
ulaşan şifresiz sayılır. Ölçülen şey uygulamanın bu gerçeği ne kadar doğru tahmin ettiğidir.
**BG8 (varsayım):** üçüncü ayardaki yerel yuva, "uygulamaya ağdan yalnız vekil aracılığıyla
erişilir" kararının ölçülebilir karşılığıdır.

```js
// tasima.mjs — sifreli baglanti varsayimi
import http from "node:http";
import { tmpdir } from "node:os";
import { rmSync } from "node:fs";
import { KUME } from "./sertlestirme.mjs";

const BASLIK = "x-forwarded-proto";
const yerel = (port) => ({ host: "127.0.0.1", port });
const ac = (s, adres) => new Promise((c) => s.listen(adres, () => c(s)));

// uygulama: sifresizi yonlendirir
const uygulama = (kural) => (q, y) => {
  const p = (q.headers[BASLIK] ?? "").split(",").map((s) => s.trim()).filter(Boolean)
    .at(kural === "ilk" ? 0 : -1);
  if (p !== "https") return y.writeHead(308, { location: "https://odunc.kutuphane" + q.url }).end();
  y.writeHead(200, { "strict-transport-security": KUME["strict-transport-security"].deger });
  y.end(JSON.stringify({ uc: q.url }));
};

// vekil: sonlandirir ve aktarir
function vekil(hedef, bicim) {
  const s = http.createServer((q, y) => {
    const gelen = q.headers[BASLIK], zincir = bicim === "ekleyen" && gelen ? `${gelen}, https` : "https";
    const i = http.request({ ...hedef, path: q.url, headers: { ...q.headers, [BASLIK]: zincir } },
      (c) => { y.writeHead(c.statusCode, c.headers); c.pipe(y); });
    i.end();
  });
  return ac(s, yerel(0));
}

const dinle = (kural, adres) => {
  if (typeof adres === "string") rmSync(adres, { force: true });
  return ac(http.createServer(uygulama(kural)), adres);
};

const iste = (hedef, gonderilen) => new Promise((c) => {
  const i = http.get({ ...hedef, path: "/odunc/al", headers: gonderilen ? { [BASLIK]: gonderilen } : {} },
    (y) => { y.resume(); c(y); });
  i.on("error", () => c({ statusCode: 0 }));
});

// kapali oldugu bilinen bir TCP adresi
const kapali = await ac(http.createServer(), yerel(0));
const kapaliPort = kapali.address().port;
kapali.close();

const ISTEKLER = ["vekil", "dogrudan"].flatMap((y) => [null, "https", "http"].map((g) => [y, g]));
const yuva = tmpdir() + "/odunc.sock";

const AYARLAR = [
  ["ekleyen vekil, ilk deger", "ilk", "ekleyen", null],
  ["ekleyen vekil, son deger", "son", "ekleyen", null],
  ["ustune yazan vekil, yalniz yuva", "son", "yazan", yuva],
];

console.log(`${ISTEKLER.length} istek: 3'u vekil uzerinden (gercek: sifreli), 3'u dogrudan (gercek: sifresiz)\n`);
console.log(`${"ayar".padEnd(34)}${"yanlis gecme".padStart(13)}${"yanlis kalma".padStart(14)}` +
  `${"tasima basligi/6".padStart(18)}${"ulasilamayan/3".padStart(16)}`);

for (const [ad, kural, bicim, adres] of AYARLAR) {
  const app = await dinle(kural, adres ?? yerel(0));
  const v = await vekil(adres ? { socketPath: adres } : yerel(app.address().port), bicim);
  let [gecme, kalma, tb, kopuk] = [0, 0, 0, 0];
  for (const [yol, gonderilen] of ISTEKLER) {
    const sifreli = yol === "vekil";
    const y = await iste(yerel(sifreli ? v.address().port
      : adres ? kapaliPort : app.address().port), gonderilen);
    if (y.statusCode === 0) { kopuk++; continue; }
    if (y.headers["strict-transport-security"]) tb++;
    if (!sifreli && y.statusCode === 200) gecme++;
    if (sifreli && y.statusCode === 308) kalma++;
  }
  console.log(ad.padEnd(34) + String(gecme).padStart(13) + String(kalma).padStart(14) +
    String(tb).padStart(18) + String(kopuk).padStart(16));
  v.close(); app.close();
}

// yanlis kalmanin bedeli
const app = await dinle("ilk", yerel(0));
const v = await vekil(yerel(app.address().port), "ekleyen");
const durumlar = [];
for (let i = 0; i < 5; i++) durumlar.push((await iste(yerel(v.address().port), "http")).statusCode);
console.log(`\n"ilk deger" ayarinda sifreli ama ters baslik tasiyan istek: 5 deneme -> ${durumlar.join(", ")}`);
console.log(`uygulamanin dondugu 5xx sayisi: 0; kayitta hata yok`);
v.close(); app.close();
```

```
6 istek: 3'u vekil uzerinden (gercek: sifreli), 3'u dogrudan (gercek: sifresiz)

ayar                               yanlis gecme  yanlis kalma  tasima basligi/6  ulasilamayan/3
ekleyen vekil, ilk deger                      1             1                 3               0
ekleyen vekil, son deger                      1             0                 4               0
ustune yazan vekil, yalniz yuva               0             0                 3               3

"ilk deger" ayarinda sifreli ama ters baslik tasiyan istek: 5 deneme -> 308, 308, 308, 308, 308
uygulamanin dondugu 5xx sayisi: 0; kayitta hata yok
```

Üç ayar aynı altı isteği görüyor. İlk ayar zincirin **ilk** değerini okuyor ve o değeri istemci
yazabiliyor: şifresiz gelen taklitçi istek kabul ediliyor (bir yanlış geçme), gerçekten şifreli
olan bir istek geri çevriliyor (bir yanlış kalma). İkinci ayar zincirin **son** değerini, yani
uygulamaya en yakın katmanın yazdığını okuyor; yanlış kalma sıfırlanıyor ama yanlış geçme
duruyor — doğrudan gelen istekte zincirde tek değer vardır ve onu istemci yazmıştır, "son değer"
kuralı orada ilk değeri okumakla aynı şeydir.

Üçüncü ayar iki şeyi birden değiştiriyor: vekil istemcinin gönderdiğini aktarmıyor, üstüne
yazıyor; uygulama ağdan değil yalnız yerel bir yuvadan dinliyor. Doğrudan üç istek bağlantı
kuramıyor, iki hata biçimi de sıfırlanıyor, taşıma başlığı tam olarak hak eden üç yanıta
yazılıyor. Sonuç bir başlık kuralından çok bir **yol** kuralıdır: aktarılan başlığa güvenmek, o
başlığı yazan katmanın tek giriş noktası olmasına güvenmektir.

Yanlış kalmanın bedeli de sessizdir. İlk ayarda ters başlık taşıyan şifreli istek beş denemenin
beşinde 308 döndü; yönlendirmeyi izleyen istemci aynı isteği aynı başlıkla yeniden üretir ve aynı
yanıtı alır. Uygulamanın döndüğü 5xx sayısı sıfırdır — kayıtta hata arayan biri bu döngüyü
bulamaz. Aynı karar önceki bölümü de bağlıyor: taşıma başlığı yalnız uygulama bağlantıyı şifreli
saydığında yazılıyor, ilk ayarda o üç yanıttan biri şifresiz bir bağlantıya gitti.

## Özet

- Uç başına yazımda 10 kayıt noktası ve 58 kayıt satırı vardır; iki sapma 2 dosyada durdu. Tek
  katmana taşıma 11 dosyaya dokundu, kayıt noktasını 1'e, yeni uç için yazılacak satırı 0'a indirdi.
- Üç ayarda 30 isteğin 30'u 200 döndü, hata 0; sertleştirme baytı 2591 / 2660 / 2400 ve **en az
  bayt üreten ayar sözleşmesi 0/10 uçta tam olandır** — yanıt boyu doğruluk sırası vermez.
- Yazılmış ama etkisiz değer eksik başlıktan ayrı sayılır: tek katmandaki tek yanlış değer
  sözleşmesi tam uç sayısını 10/10'dan 0/10'a düşürdü, durum kodu ve gövde değişmeden. Denetim bu
  yüzden yapılandırmanın değil **yanıtın** üzerinde çalışır.
- Aktarılan protokol başlığında ilk değer kuralı 1 yanlış geçme ve 1 yanlış kalma üretti; son
  değer kuralı yalnız yanlış kalmayı sıfırladı, çünkü doğrudan gelen istekte zincirdeki tek değeri
  istemci yazar.
- Üstüne yazan vekil ve yalnız yerel yuvadan dinleme ikisini de sıfırladı: 3 doğrudan istek
  bağlantı kuramadı, başlık yalnız hak eden 3 yanıta yazıldı. Yanlış kalmanın izi yoktur — ters
  başlık taşıyan şifreli istek 5 denemenin 5'inde 308 döndü, 5xx sayısı 0.

## Sonraki Adım

Taşıma tarafı bu dersle sertleşti: başlıklar tek katmanda toplandı, değerleri yanıt üzerinden
denetlenebilir hâle geldi ve şifreli bağlantı varsayımı tek bir yola bağlandı. Ama bu derste
kullanılan her değer kodun içine düz metin olarak yazıldı. Vekilin uygulamaya ulaştığı yol,
denetimin beklediği değerler ve şifreli bağlantının dayandığı anahtarlar aynı yerde durur:
kaynak dosyalarda. Sonraki ders bu değerleri sayar — kaçı kodda kalmış, biri değiştirildiğinde
kaç servise dokunuluyor ve döndürme sırasında eski ile yeni değerin birlikte geçerli olduğu
pencere kaç saniye sürüyor.
