עודכן לפני חודש
כשאתם מבקשים משהו משרת, התגובה מגיעה בשני חלקים. הגוף הוא מה שביקשתם — ה-HTML, התמונה, נתוני ה-JSON. הכותרות הן השרת מספר לכם מה הוא נתן לכם ומה לעשות איתו.
חשבו על זה כמו קבלת חבילה. תוכן החבילה הוא הגוף. הכותרות הן הוראות הטיפול המודבקות בחוץ: "שביר." "לאחסן במקרר לאחר הפתיחה." "זו מתנה — אל תציגו את המחיר."
השאלות שכל תגובה עונה עליהן
כל תגובת HTTP עונה במשתמע על סדרת שאלות:
מה זה? כותרת ה-Content-Type מספרת לדפדפן אם הוא מסתכל על HTML, JSON, תמונה או PDF. בלעדיה, הדפדפן מקבל זרם של בתים ואין לו מושג איך לפרש אותם.
כמה גדול זה? Content-Length מאפשר לדפדפנים להציג התקדמות הורדה ולדעת מתי קיבלו את הכל.
האם זה דחוס? Content-Encoding אומר לדפדפנים לפתוח את הדחיסה של התגובה לפני השימוש בה.
אפשר לשמור אותו במטמון? Cache-Control וכותרות קשורות קובעות האם דפדפנים ו-CDN יכולים לאחסן עותקים, ולכמה זמן.
אילו כללי אבטחה חלים? כותרות כמו Content-Security-Policy ו-Strict-Transport-Security מספרות לדפדפנים מה לחסום ומה לאכוף.
האם לאחסן עוגיות? כותרות Set-Cookie יוצרות מצב מתמיד בין בקשות.
האם ללכת למקום אחר? כותרות Location (עם קודי סטטוס הפניה) אומרות לדפדפנים לבקש כתובת URL אחרת.
כל כותרת תגובה היא תשובה לאחת מהשאלות האלה.
כותרות תוכן: מה אתם מקבלים
Content-Type
כותרת התגובה הבסיסית ביותר. היא אומרת לדפדפן איך לפרש את הבתים שקיבל:
בלי Content-Type, הדפדפן מקבל זרם של בתים ואין לו מושג מה הוא מסתכל עליו. האם זה HTML לעיבוד? JSON לניתוח? תמונה להצגה? הבתים עצמם לא אומרים.
ערכים נפוצים:
text/html— לעיבוד כדף אינטרנטapplication/json— לניתוח כנתונים מובניםimage/png— להצגה כתמונהapplication/pdf— להצגה או הורדה כ-PDFtext/css— להחלה כגיליון סגנוןapplication/javascript— להרצה כקוד
החלק charset=utf-8 מציין קידוד תווים. שגיאה כאן תגרום לטקסט להיראות כתווים מקולקלים.
Content-Length
גודל גוף התגובה בבתים:
כותרת זו מאפשרת פסי התקדמות. בלי ידיעת הגודל הכולל, דפדפנים יכולים רק להציג "טוען..." ללא כל אינדיקציה כמה נשאר. היא גם מאפשרת ללקוחות לוודא שקיבלו את התגובה המלאה.
Content-Encoding
מציינת דחיסה שהוחלה על התגובה:
הדפדפן פותח את הדחיסה אוטומטית לפני העיבוד. קידודים נפוצים:
gzip— נתמך באופן נרחב, דחיסה טובהbr— Brotli, יחסי דחיסה טובים יותר לטקסט
דחיסה יכולה להפחית את גודל ההעברה ב-70-90% לתוכן טקסטואלי כמו HTML, CSS ו-JavaScript. הבתים המועברים ברשת הם דחוסים; הדפדפן מנפח אותם חזרה לצורתם המקורית.
Content-Disposition
שולטת האם תוכן מוצג ישירות בדפדפן או מפעיל הורדה:
עם inline (ברירת המחדל לרוב התוכן), דפדפנים מציגים את התגובה ישירות. עם attachment, הם מבקשים מהמשתמש לשמור קובץ. פרמטר ה-filename מציע שם לקובץ.
כך שרת יכול לשלוח בתים זהים אבל לגרום לכתובת URL אחת להציג PDF בדפדפן בעוד אחרת מפעילה חלון הורדה.
כותרות מטמון: אפשר לשמור עותק?
Cache-Control
הכותרת הראשית השולטת כיצד ניתן לשמור תגובות במטמון:
ההנחיות החשובות:
public — כל מטמון יכול לאחסן זאת: CDN, שרתי proxy, דפדפנים. מתאים לנכסים סטטיים כמו תמונות וסקריפטים.
private — רק הדפדפן של המשתמש יכול לשמור זאת במטמון, לא מטמונים משותפים. מתאים לתוכן מותאם אישית.
max-age=3600 — התגובה טרייה למשך 3600 שניות (שעה אחת). בחלון זה, מטמונים יכולים להגיש אותה ללא בדיקה מול השרת.
no-cache — מטמונים חייבים לאמת מול השרת לפני שימוש בעותק מאוחסן. המטמון שומר את התגובה אבל תמיד בודק אם היא עדיין תקפה.
no-store — לא לשמור במטמון כלל. התגובה לעולם לא תיכתב לדיסק. מתאים לנתונים רגישים.
must-revalidate — ברגע שפג תוקף, מטמונים חייבים לאמת מחדש. הם אינם יכולים להגיש תוכן מיושן גם אם השרת אינו נגיש.
ETag
טביעת אצבע המזהה באופן ייחודי גרסה ספציפית של המשאב:
כך ETags הופכים את המטמון ליעיל: הדפדפן שומר את התגובה יחד עם ה-ETag שלה. מאוחר יותר, כשרשומת המטמון מיושנת, הדפדפן מבקש את המשאב שוב אבל כולל את ה-ETag בכותרת If-None-Match. אם התוכן לא השתנה, השרת מגיב עם 304 Not Modified — ללא גוף, רק אישור שהגרסה המאוחסנת עדיין תקפה.
זה הופך הורדה גדולה פוטנציאלית לבדיקת אימות קטנה.
Last-Modified
מתי המשאב שונה לאחרונה:
דומה ל-ETag אבל מבוסס על חותמות זמן ולא על טביעות אצבע של תוכן. הדפדפן שולח זאת חזרה בכותרות If-Modified-Since לאימות. פחות מדויק מ-ETags (רזולוציה של שנייה אחת בלבד) אבל פשוט יותר ליישום.
כותרות עוגיות: לזכור
Set-Cookie
מורה לדפדפן לאחסן עוגייה:
ערך העוגייה (sessionId=abc123) הוא הנתון עצמו. התכונות שולטות בהתנהגות:
Secure — שלח עוגייה זו רק דרך HTTPS. מונע יירוט בחיבורים לא מאובטחים.
HttpOnly — JavaScript אינו יכול לגשת לעוגייה זו. מגן על אסימוני סשן מהתקפות XSS שמנסות לגנוב עוגיות דרך document.cookie.
SameSite — שולט מתי עוגיות נשלחות עם בקשות בין-אתריות:
Strict— לעולם לא לשלוח בין-אתרית (ההגנה החזקה ביותר)Lax— לשלוח בניווטים ברמה העליונה אבל לא בבקשות מוטבעותNone— תמיד לשלוח (דורש Secure; משמש לתרחישים בין-אתריים לגיטימיים)
Max-Age — כמה שניות עד שתפוג העוגייה. ללא ערך זה או Expires, זוהי "עוגיית סשן" שנעלמת כשהדפדפן נסגר.
תגובה אחת יכולה לכלול מספר כותרות Set-Cookie כדי להגדיר מספר עוגיות.
כותרות אבטחה: אכוף כללים אלה
Strict-Transport-Security (HSTS)
אומר לדפדפנים להשתמש תמיד ב-HTTPS:
ברגע שדפדפן מקבל כותרת זו, הוא ממיר אוטומטית כל בקשת HTTP ל-HTTPS למשך הזמן שצוין. גם אם משתמש מקליד http:// או לוחץ על קישור HTTP, הדפדפן משדרג ל-HTTPS לפני שליחת דבר.
זה מונע מתוקפים ליירט את בקשת ה-HTTP הראשונית לפני שהפניה ל-HTTPS יכלה להתרחש.
Content-Security-Policy (CSP)
מגדיר אילו משאבים מורשה לדף לטעון:
CSP יוצר רשימה לבנה. כל משאב שלא הותר במפורש נחסם. זוהי הגנה חזקה מפני התקפות XSS — גם אם תוקף מזריק תג סקריפט זדוני, הוא לא יורץ אם מקורו אינו ברשימה הלבנה.
ההנחיות מציינות כללי מקור עבור סוגי משאבים שונים: script-src ל-JavaScript, img-src לתמונות, style-src ל-CSS, וכן הלאה. default-src קובע את ברירת המחדל לכל דבר שלא צוין במפורש.
X-Content-Type-Options
מונע מדפדפנים "להריח" את סוג התוכן. בלעדיו, דפדפנים עשויים להתעלם מכותרת Content-Type ולנחש לפי התוכן עצמו. אם תוכן שהועלה על ידי משתמש מתפרש בטעות כ-JavaScript הניתן להרצה, זו פרצת אבטחה. כותרת זו מאלצת דפדפנים לסמוך על Content-Type.
X-Frame-Options
שולטת האם הדף יכול להיות מוטבע במסגרת:
DENY— לא ניתן להטביע על ידי אף אחדSAMEORIGIN— ניתן להטביע רק על ידי דפים מאותו מקור
זה מונע התקפות clickjacking שבהן אתר זדוני מטביע את הדף שלכם ב-iframe בלתי נראה ומרמה משתמשים ללחוץ עליו.
כותרות CORS: גישה בין מקורות
כש-JavaScript ממקור אחד מנסה לגשת למשאב ממקור שונה, דפדפנים חוסמים זאת כברירת מחדל. כותרות CORS מעניקות הרשאה מפורשת.
Access-Control-Allow-Origin
הכותרת הבסיסית של CORS:
זה אומר: "JavaScript מ-https://www.example.com מורשה לקרוא תגובה זו." ללא כותרת זו, הדפדפן מביא את התגובה אבל מסרב לאפשר ל-JavaScript לגשת אליה.
התו הכללי * מאפשר לכל מקור, אבל לא ניתן להשתמש בו עם אישורים (עוגיות).
Access-Control-Allow-Methods
אילו שיטות HTTP מותרות לבקשות בין-מקוריות:
זה מופיע בתגובות לבקשות preflight, ומציין לדפדפנים אילו שיטות הבקשה בפועל יכולה להשתמש.
Access-Control-Allow-Headers
אילו כותרות בקשה מותרות:
כותרות מותאמות אישית דורשות הרשאה מפורשת. בלעדיה, דפדפנים דוחים בקשות בין-מקוריות הכוללות כותרות מעבר לרשימת הבסיס הבטוחה.
Access-Control-Max-Age
כמה זמן דפדפנים יכולים לאחסן תוצאות preflight במטמון:
בקשות preflight מוסיפות השהייה. אחסון התוצאות במטמון ל-86400 שניות (יום אחד) אומר שדפדפנים לא צריכים לשלוח preflight לכל בקשה בין-מקורית.
כותרות הפניה
Location
משמשת עם קודי סטטוס 3xx כדי לציין לאן לנווט:
כשלתגובה יש קוד סטטוס הפניה (301, 302, 307, 308), הדפדפן מבקש אוטומטית את ה-URL שבכותרת Location. קוד הסטטוס של ההפניה קובע האם הדפדפן יכול לאחסן את ההפניה במטמון ואם לשנות את שיטת ה-HTTP.
כותרות העברה
Transfer-Encoding
כיצד גוף ההודעה מועבר:
קידוד chunked מאפשר לשרתים להתחיל לשלוח לפני שהם יודעים את אורך התוכן הכולל. כל גוש מגיע עם גודלו, וגוש בגודל אפס מאותת על הסיום. זה מאפשר הזרמת תגובות ותוכן שנוצר דינמית שבו הגודל הסופי אינו ידוע מראש.
עם קידוד chunked, אין כותרת Content-Length — הגושים עצמם מגדירים את הגבולות.
מידע על השרת
Date
מתי נוצרה התגובה:
שימושי לניפוי שגיאות ולחישוב רעננות המטמון.
Age
כמה זמן התגובה יושבת במטמון:
CDN ושרתי proxy מוסיפים כותרת זו. אם Cache-Control אומר max-age=7200 ו-Age אומר 3600, לתגובה נשאר עוד שעה של רעננות.
Server
מזהה את תוכנת השרת:
מידעי, אבל לעיתים קרובות מושמט בסביבת הייצור מכיוון שחשיפת גרסאות מדויקות עוזרת לתוקפים לכוון לפגיעויות ידועות.
שאלות נפוצות על כותרות תגובה
מדוע אני רואה תווים מקולקלים במקום תוכן קריא?
בדרך כלל מדובר באי-התאמה ב-Content-Type. השרת שלח charset שגוי (לא UTF-8 כשהיה צריך) או שלא שלח charset בכלל. דפדפנים מנחשים, והניחוש לעיתים קרובות נכשל. התיקון הוא בצד השרת: יש לוודא ש-Content-Type כולל את ה-charset הנכון.
מה ההבדל בין no-cache ל-no-store?
no-cache אומר "שמור עותק אבל תמיד בדוק עם השרת לפני שימוש בו." no-store אומר "בכלל אל תשמור עותק." לנתונים רגישים כמו מידע בנקאי, השתמשו ב-no-store כדי להבטיח שהוא לעולם לא ייכתב לדיסק.
מדוע הבקשה הבין-מקורית שלי עובדת ב-Postman אבל נכשלת בדפדפן?
Postman לא אוכף CORS — הוא אינו דפדפן. דפדפנים חוסמים תגובות בין-מקוריות שחסרה בהן כותרת Access-Control-Allow-Origin מתאימה. הבקשה מצליחה ברמת הרשת; הדפדפן פשוט מסרב לאפשר ל-JavaScript לראות את התגובה.
האם אפשר להגדיר מספר עוגיות בתגובה אחת?
כן. יש לכלול כמה כותרות Set-Cookie, אחת לכל עוגייה. בניגוד לרוב הכותרות, Set-Cookie לא ניתן לשלב לרשימה מופרדת בפסיקים.
מה קורה אם Cache-Control ו-Expires לא מסכימים?
Cache-Control מנצח. זוהי הכותרת החדשה והמדויקת יותר. Expires קיים לצורך תאימות לאחור עם מטמוני HTTP/1.0 אבל בפועל מתעלמים ממנה כש-Cache-Control קיים.
האם דף זה היה מועיל?