עבור לתוכן
cutty.dev
All posts

Auto-prefix URL — פרט קטן שחוסך דקות

cutty.dev מזהה כשמדביקים כתובת ללא https:// ומוסיף אותה בעצמו. זה נשמע תפל. בפועל, זה ההבדל בין שתי שניות לבין לחיצה על 'נסה שוב'.

אתה מקליד בטופס allegro.pl. לוחץ. ומה עכשיו?

ברוב המקצרים אתה מקבל ברגע זה הודעת שגיאה. משהו בסגנון "זה לא כתובת URL תקינה". כי חסר ה-https:// בהתחלה. אז אתה חוזר אחורה, מוסיף את הפרוטוקול, לוחץ שוב, ורק עכשיו יש לך את הקישור הקצר שלך.

cutty.dev לא עושה את זה. הוא פשוט מצמיד https:// וממשיך הלאה, כאילו כלום לא קרה.

אני יודע איך זה נשמע. כפי שזה נשמע, פיצ'ר שבקושי ראוי לפסקה, שלא לדבר על פוסט שלם. ובכל זאת אני יושב וכותב על זה, כי הפרט הקטן הזה הוא עבורי מניפסט קטן של הדרך שבה אני חושב בכלל על בניית כלי ה-auto-prefix URL וכל שאר אותן הקלות הבלתי נראות.

שתי שניות מול עשרים

בואו נחשב. באמת, על המספרים, כי אחרת זה רק דיבורים.

המסלול הראשון: מדביקים, מקבלים קישור, סוגרים את החלון. שתי שניות. אולי שלוש.

מסלול שני: מדביקים, שגיאה, קוראים את ההודעה (שנייה או שתיים כדי להבין מה קרה), מוסיפים פרוטוקול, לוחצים שוב, ורק עכשיו הקישור. חמש עשרה, עשרים שניות. בתוספת הרגע הקטן הזה של תסכול, ה"אה כן, פרוטוקול" השקט הזה, שבודד הוא לא עולה כלום, אבל מצטבר.

ועכשיו תכפיל בזה כמה פעמים בחודש אתה מדביק כתובת כלשהי. אצלי זה עשרות. אצל מישהו שמנהל קישורים באופן מקצועי — מאות. פתאום ה"פרט הזה שכמעט ולא שווה אזכור" מצטבר לדקות בחודש. לאדם.

זו בדיוק האריתמטיקה שרוב האנשים מפספסים, כי כל מקרה בודד נראה קטן מדי מכדי לדאוג לו.

מה באמת נמצא שם למטה

המנגנון הוא פשוט ביותר ואני בכלל לא מסתיר זאת. מדביקים את הטקסט לשדה. לפני שכל דבר נשלח לשרת, קטע של JavaScript בודק אם מה שהקלדת מתחיל בפרוטוקול כלשהו — http://, https://, ftp://, mailto:, לא משנה מה. אם הוא לא מתחיל בכך, המערכת מניחה שהתכוונת לדומיין רגיל ומדביקה https:// בהתחלה.

בפועל:

  • allegro.pl הופך ל-https://allegro.pl
  • github.com/twoj-profil/projekt ל-https://github.com/twoj-profil/projekt
  • www.gazeta.pl ל-https://www.gazeta.pl

ואם הפרוטוקול כבר נמצא שם, אפילו אם הוא מוזר, המערכת לא דורסת אותו. היא משאירה אותו וממשיכה לבדוק מה לעשות איתו. http://example.com עובר (מותר). ftp://example.com נזרק לפח, כי אנחנו מקבלים רק http ו-https. ו-javascript:alert(1) יוצא מיד, כי זה לא כתובת, זו ניסיון להזרקת משהו רע (XSS קלאסי, תודה, לא).

למה יש לי את זה, ולמחצית מהשוק לא

כאן זה נהיה מעניין, כי התשובה היא קצת מצחיקה.

הדרך הסטנדרטית לאימות כתובת בדפדפן היא הקונסטרקטור new URL(string). והקונסטרקטור הזה קשיח. חסר פשרות. אין פרוטוקול — הוא זורק שגיאה. new URL("allegro.pl") פשוט מחזיר לך TypeError וזהו.

ואתה יודע מה? זה התנהגות נכונה. עבור הרוב המוחלט של האפליקציות בדיוק לזה אתה רוצה. אבל בטופס לקיצור קישורים, שבו אדם מעתיק כתובת מסרגל הכתובות בדפדפן או מהודעה של מישהו אחר, הנוקשות הזו הופכת מיתרון למכשול. פתאום כלי שאמור לחסוך לך זמן, גורם לך לתקן אחרי עצמך משהו שהוא הרי מבין מצוין.

מעקף של זה הוא ממש כמה שורות:

function sanitizeUrl(input) {
  const trimmed = input.trim();
  const hasProtocol = /^[a-z][a-z0-9+.-]*:/i.test(trimmed);
  const normalized = hasProtocol ? trimmed : "https://" + trimmed;
  // dalej leci normalna walidacja przez new URL(normalized)
}

חמש שורות. כמה עשרות שניות פחות חיכוך, מדי יום, עבור כל מי שמדביק כתובות. בכנות אני לא יודע למה זה לא הסטנדרט בכל מקום. אני חושד שזה בגלל ש"ככה פשוט עובד ה-URL constructor" ולאף אחד לא היה כוח לגעת בזה. אינרציה, לא חוסר רצון.

דיגרסיה קטנה על המשמעות של "סטנדרטי"

כי הסיפור הזה עם new URL() הוא דוגמה מצוינת למשהו רחב יותר. המון דברים בתוכנה שנחשבים ל"ככה עושים את זה", הם בעצם "ככה יצא מההגדרות המחדל של ספרייה כלשהי שאף אחד לא ערער עליה". ה-Strict mode של הקונסטרקטור הוא לא החלטה של המתכנתים של cutty או של המתחרים — זו החלטה של כותבי מפרט ה-URL, שהתקבלה בהקשר שונה לחלוטין, עבור שימושים שונים לחלוטין.

ואז כל השוק יורש את הבחירה המוגדרת הזו וקורא לה "סטנדרט". יש לי תחושה שהמוצרים הטובים ביותר נולדים בדיוק במקומות הללו, שבהם מישהו עצר ושאל: רגע, האם ההתנהגות הזאת משרתת את המשתמש שלי, או רק את הספרייה שלי? ברוב המקרים התשובה היא: את הספרייה. ואז כדאי באמצעות חמש שורות לעבור לצד של האדם.

יש יותר מפרטים קטנים כאלה ממה שנראה לעין

Auto-prefix הוא רק אחד מתוך אינספור רכיבים כאלה שלא תמצא בשום רשימת תכונות. כי אם היו רושמים אותם שם, כל אחד בנפרד היה נראה קטן בצורה מצחיקה:

  • חיתוך רווחים לפני וולידציה, כדי שרווח מקרי בסוף כתובת שהודבקה לא יהרוס הכל
  • שמירה על עוגן (anchor), כלומר #section ב-https://example.com/page#section לא נעלם לאחר הקיצור
  • פרמטרי שאילתה (?utm_source=test) עוברים בשלמותם, שום דבר לא נחתך בדרך
  • דומיינים עם תווים פולניים, źdźbło.pl, מומרים אוטומטית ל-punycode
  • אותיות פולניות בסיומת המותאמת אישית מוחלפות ב-ASCII (różowy-link הופך ל-rozowy-link)
  • פרוטוקולים מסוכנים — javascript:, data:, file: — נדחים עם הודעה ספציפית ומובנת

(מתוכנן גם שדרוג אוטומטי של http:// ל-https://, כאשר השרת היעד תומך בהצפנה. זה בדיוק עדיין לא עובד בשידור חי, אז אני לא אעמיד פנים.)

כל אחד מהפרטים הללו חוסך למישהו חמש, עשר, שלושים שניות ונהמה אחת. בנפרד, כלום. יחד, זה ההבדל בין "עובד בסדר" לבין "אני אוהב להשתמש בזה".

מה הייתי רוצה להוסיף עוד

רשימת משאלות לעתיד, כי המחשבה על זה פשוט גורמת לי הנאה:

  • הדבקה חכמה — זיהוי כתובת המוסתרת בתוך משפט וחילוץ ה-URL בלבד מבין המילים
  • הדבקה מרוכזת — רשימת כתובות, אחת בכל שורה, וכל אחת הופכת מיד לקישור קצר נפרד
  • סיומות מוצעות — הצעה של שלושה slug-ים איכותיים לבחירה על בסיס כותרת דף היעד
  • תצוגה מקדימה של Open Graph מיד לאחר ההדבקה, עוד לפני שתלחץ על "קצר"

כל אחד מזה הוא שוב "פונקציה בת חמש שורות שנראית כמו כלום". וכולם יחד? זה בדיוק הגבול בין כלי שהוא בסדר לבין כזה שאתה משתמש בו מדי יום בלי לחשוב פעמיים. אם אתה רוצה לראות איך זה עובד עכשיו, הדבק ב-cutty.dev כל דבר ללא פרוטוקול — allegro.pl, github.com, news.ycombinator.com — ותראה ששום דבר לא מפריע לך בדרך.

לסיכום, קצת אישי

חשבתי זמן רב שמוצרים מנצחים בזכות תכונות גדולות. אותו דבר מרשים אחד, שניתן להציג בשקופית ושאנשים יכתבו עליו. וכן, לפעמים זה כך.

ככל שאני בונה את cutty זמן רב יותר, כך אני מרגיש חזק יותר שנאמנות המשתמש נולדת במקום אחר — באותם מאות מיקרו-שניות שאף אחד לא מבחין בהן באופן מודע. אתה לא זוכר שהכלי הוסיף לך בעצמו את https://. אתה רק זוכר את הרושם הכללי ש"זה מרגיש טוב להשתמש בזה", "זה לא מעצבן". הרושם הזה לא מגיע משום מקום. הוא מורכב מעשרות החלטות של חמש שורות, שאף אחד לא היה יכול להגן על כל אחת מהן בפני עצמו כ"משתלמת בזמן".

אולי בדיוק בזה טמון האומנות. לא בתנועה הגדולה והיחידה הזו, אלא בעקשנות לעמוד לצד האדם פעם אחר פעם מול הטופס — גם אם מדובר בשתי שניות עלובות. ואתה? מה הכעיס אותך לאחרונה בכלי כל כך קטנטן, עד שזה כמעט מביך להודות? כי בדרך כלל בדיוק שם מחכה העבודה הטובה ביותר לעשות.