שיעור 5
תקציר: אנו באמצע לכתוב אתר "משוכלל" בו יוכלו להוסיף פריט לרשימה ולצפות כמובן ברשימה.
החלטנו על שני כתובות, אחת להוספת פריט, ואחת לרשימה כולה. בדקנו איך אנו יכולים לדעת בתוך הפונקציה את ה"פרט" הזה שנקרא כתובת, ומצאנו אותו כמאפיין url בפרמטר req. כיון שכן נתחיל בבניית שלד לקוד האתר:
const http = require('http');
var list = [];
function handleAllRequest(req, res) {
if (req.url == '/')
res.write('Hello To List Page!');
else if (req.url == '/add-item')
res.write('Hello To Item-Add Page!');
else
res.write('Opss... Not Found!');
res.end();
}
var server = http.createServer(handleAllRequest);
server.listen(3000);
הכרזנו פה בשורה 3 על משתנה בשם list ושמנו בו מערך ריק. בו יהיו הפריטים של הרשימה.
להזכיר, נוד מריץ את הקוד פעם אחת בלבד. הפוקנציה handleAllRequest יוצאת דופן כי אותה ביקשנו להריץ לכשתהיה בקשה, וליתר דיוק כל פעם שתהיה. לכן, המשתנה list בעצם מוכרז ומאוכלס במערך ריק פעם אחת, אבל הוא נגיש מתוך הפוקנציה handleAllRequest לאורך כל חיי האתר.
בשורות 6-11 אנו בודקים את ערכו של המאפיין url ופועלים בהתאם (אחד לשורש האתר, add-item יביא לדף יכיל טופס להוספת ערך, וכל כתובת אחרת תיתקל בסוג של 404...). בינתיים זה רק שלד, בהמשך נצטרך לעשות יותר בכל מצב.
קצת html וגם על content-type וכותרות (headers)
בשביל שצד הלקוח יתקשר עם צד השרת, אנו חייבים טופס בו ניתן לרשום ערך, וכפתור שליחה יפה.
בשביל זה אנו צריכים לעבוד עם HTML ולא עם טקסטים כמו שעשינו עד עכשיו.
בשביל לשלוח ללקוח HTML לא די לשנות את הטקסט לHTML אלא יש להסביר לדפדפן שהתוכן הוא HTML, עושים את זה באמצעות כותרת בשם content-type (דיברנו על כותרות קצת בעבר, ונייחד לזה שוב דיבור כשנגיע למושג עוגיות שם נרחיב, כך שכעת אפשר לחפף). וזה אומר שנכתוב בפונקציה שלנו כזה קוד:
function handleAllRequest(req, res) {
res.setHeader('Content-Type', 'text/html');
if (req.url == '/')
res.write('Hello To List Page!');
else if (req.url == '/add-item')
res.write(`<form>
Enter the item value: <input type="text" name="the-name" >
<br>
<input type="submit" >
</form>`);
else
res.write('Opss... Not Found!');
res.end();
}
בלגן. ובכן,
בשורה 2 אנו מגדירים (דרך הפרמטר res שמייצג את אובייקט התשובה) כותרת באובייקט התשובה. בגלל פונקציה זו תתנוסס במכתב-התשובה שלנו השורה content-type: text/html דבר שישפיע מאוד על יחס הדפדפן לתוכן - הוא לא יציג תגיות, אלא טקסט מובנה/מעוצב בהתאם לתגיות.
בשורות 6-11 השתמשנו עם טילדה (התו הזה: `) כדי לעשות מחרוזת טקסט מרובת שורות, בה כתבנו טופס HTML צנוע (ובלתי חוקי, כי הרי מסמך HTML יש לו כללי פתיחה והמינימום שלו ארוך בהרבה! אבל כל עוד הדפדפן מגלה יחס סובלני, וזה טוב ללימוד דוגמה קומפקטית, אז למי אכפת?). מייד נדון על תוכנו של הטופס שכתבנו.
תריצו ותיכנסו לכתובת http://localhost:3000/add-item ותראו את הטופס הHTML היפה שיצרנו.
HTML, הקדמת רשות (קצרה ולא מסבירה, רק ריענון. להרחבה אנא שאלו בפורום):
HTML הוא פורמט/תחביר כתיבה שכולל תגיות (הסוגריים הזויותיות הללו <>), תכונות (מפתח ערך, בסגנון הזה אני="אתה"
) וערכים (התוכן שבין צמתי התגיות והערכים של התכונות.
זה קובץ טקסט עלוב, ככל טקסט אחר, אלא שהדפדפן קורא אותו ואינו מציג אותו כפי שהוא, אלא אחרי "הבנה" של המוסכמות על התגיות והתכונות והערכים שבהם.
הוא נוצר בראשית ימי האינטרנט להצגת מסמכים. מסמך טקסט רגיל הוא "שטוח" חסר מבנה ויכולת לעצבו.
לעמות זאת מסמך HTML מאפשר להגידר היררכיה וחלקים במסמך, לתאר אותם הן ע"י שמות התגיות והן ע"י התכונות וגם ע"י מיקומם בהיררכיה של התגיות. בהתחלה השתמשו חזק מאוד בHTML כדי לעצב ישירות את מראה המסמך הסופי, אך מאוחר יותר הבינו שלא חכם לערבב חזות עם מבנה, וכיום מאוד משתדלים שHTML ישמש נטו לעיצוב מבני (כמו כותרת, קטע, כפתור וכו'), ולא לצרכי עיצוב (כמו טקסט אדום).
בראשית ימי האינטרנט שרת היה יודע תמיד למפות נתיב של בקשה לקבוץ הנכון וככה להגיש קבצים סטטייים- בלתי משתנים. בהמשך התפתחות האינטרנט התחילו לפתח שרתים דינמיים שהגיבו לבקשות חיפוש למשל, וייצרו דף HTML שהכיל תוצאות מחיפוש שבוצע בצד השרת. בשביל זה הכניסו בפרומט הHTML תגיות ותכונות מיוחדות שאפשר להכליל אותם בכותרת "טפסים". ועל כך בקטע הבא. סיום ההקדמה.
טפסי HTML, ומתודות HTTP
טפסי HTML הם מכלול התגיות והתכונות שרלוונטיות ליצירת אינטראקציה בין הדף לבין השרת.
האלמנט הראשי של טפסי HTML הוא התגית Form. היא נדרשת תמיד בטופס HTML, וכל הקלט של המשתמש צריך להיות "עטוף" בה.
אלמנט שני וכמעט אחרון זה הinput. זה אלמנט שבו המשתמש יכול להזין/לפעול ערך/פעולה שהטופס ישלח לצד השרת. יש המון סוגים של input שנקבעים לפי הtype, כמו text, number email וכו'. יש סוג שנקרא submit שהוא סוג שמוצג ככפתור "שליחה". לחיצה עליו בטופס תשלח את הטופס על ערכיו לצד השרת.
מאי משמע "תשלח"? בדואר אויר? איך, ולאיפה?
ובכן הערכים יישלחו בבקשת אינטרנט, שאנו לא מפסיקים לדבר עליה.
נחזור לבקשת אינטרנט:
השורה הראשונה של בקשת כניסה לדף http://localhost:3000/add-item נראית ככה:
GET /add-item HTTP/1.1
המילה GET היא המתודה, אחת מכמה מתודות שיש בפרוטוקול HTTP. מתודה אחרת שמעניינת אותנו כעת היא POST.
בקצרה נאמר בGET זה בקשה "ריקה", כמו כל הזנת כתובת בדפדפן ואנטר, וPOST זה בקשה "מלאה, אפשר לשים בה תוכן מעבר לכתובת ולכותרות (התוכן נמצא אחרי הכותרות - מה שמבדיל ביניהם זו שורה ריקה).
עוד הבדל חושב: מתודת GET נועדה עבור בקשות "קריאה בלבד" כלומר בקשות שלא נועדו לעשות שינוי כל שהוא בעולם. למשל בקשת רשימת ערכים זו בקשת קריאה. בקשת הוספה מחיקה ועדכן הם בקשות שמבקשות לעשות שינוי, ואמורים שלא להתשמש במתודה GET עבורם (אין לכם במועדפים כתובת שלחיצה עליה שולחת מייל למשל, נכון?).
למרות שהמתודה GET לא עשויה לשלוח נתונים של ממש, אבל אי אלו פרמטרים לבקשה. במתודת GET הדרך להעביר אותם היא בquery, אותו חלק אפשרי של הURL שפעם סיפרנו עליו שמתחיל בסימן השאלה, עד לסופוף הכתובת (או לסולמית אם ישנה)
נחזור לטופס שלנו, הוא נראה ככה:
<form>
Enter the item value: <input type="text" name="the-name" >
<br>
<input type="submit" >
</form>
תגית הטופס (form), היא המפתח לפעולה של הדפדפן בעת השליחה.
בטופס הזה יש רק שני רכיבי קלט משתמש, אחת לטקסט ואחת לכפתור השליחה. לכפתור הטקסט יש תכונה (attribute) שנקראת name שעשויה להצמדה על הערך שהמשתמש יכניס, שנדע תחת איזה שדה בטופס הוא הוזן (שהרי יכולים להיות כמה וכמה שדות).
באלמנט הform יש שני תכונות אופציונליות (=בלתי נדרשות לפעולה תקינה) אחת בשם action והשניה בשם method.
action קובע לאיזה כתובת הדפדפן ישלח את הבקשה ובהתאם יקבע את הכתוב בשורת הכתובת.
במידה והactio לא קיים, הברירת מחדל היא הכתובת הנוכחית. זה מה שיקרה אצלנו.
method קובע באיזה מתודת HTTP תהיה הבקשה, GET או POST. אם שולחים בPOST הערכים יהיו ב"מכתב" הבקשה, אחרי שורה ריקה שאחרי הכותרות. במקרה של GET הנתונים יישלחו בכתובת עצמה, אחרי סימן שאלה להפרדה בין הכתובת לנתונים.
בשני המקרים, הנתונים יעוצבו בפומט כזה שם=ערך&שם-אחר-ערך&שם-נוסף=ערך.
תוכלו לנסות לשים ערך בטופס שלנו בכתובת http://localhost:3000/add-item ולצפות בכתובת שהדפדפן הוביל אליה. התשובה שמתקבלת היא לא מעניינת (אנו מקבלים Opss... Not Found! כי לא תכנוו אפשרות של כתובת עם סימן שאלה אחרי הadd-item).
המתודה GET לא מתאימה עבורינו, כי אנו הולכים לעשות שינויים בצד שרת, לכן בא נכתוב בטופס ככה:
res.write(`<form method="POST">
Enter the item value: <input type="text" name="the-name" >
<br>
<input type="submit" >
</form>`);
שינינו פה רק שתי מילים, שהוספנו את התכונה method="POST"
לאלמנט הטופס.
כעת נריץ שוב (בעת הרצה בVSCODE יש סרגל צף של אפשרות הפסקת ההרצה, ויש גם כפתור להתחיל מחדש, שימושי!) וניכנס לכתובת http://localhost:3000/add-item נכניס ערך ולחץ על ה"שלח", לא יקרה משהו מיוחד, אבל עשינו כל מה שדרוש בצד לקוח!
בשיעור הבא נדבר על טיפול בטפסי HTML בצד שרת.
כמו"כ נראה לי שנעביר את הקוד של הHTML לקבצים בפני עצמם.