رفتن به محتوا
cutty.dev
All posts

Auto-prefix URL — جزئیاتی که دقیقه‌ها را ذخیره می‌کند

cutty.dev تشخیص می‌دهد که وقتی آدرسی را بدون https:// می‌چسبانید، خودش آن را اضافه می‌کند. شاید ناچیز به نظر برسد، اما در عمل تفاوت بین دو ثانیه و کلیک کردن روی «دوباره تلاش کن» است.

شما در فرم عبارت allegro.pl را تایپ می‌کنید. کلیک می‌کنید. و بعد چه؟

در اکثر کوتاه‌کننده‌ها، در این لحظه با یک پیام خطا مواجه می‌شوید. چیزی شبیه به "این یک آدرس URL معتبر نیست". چون https:// در ابتدا وجود ندارد. بنابراین به عقب برمی‌گردید، پروتکل را اضافه می‌کنید، دوباره کلیک می‌کنید و تازه حالا لینک کوتاه خود را دارید.

cutty.dev این کار را انجام نمی‌دهد. فقط خودش https:// را می‌چسباند و بدون هیچ مشکلی ادامه می‌دهد.

می‌دانم چطور به نظر می‌رسد. مثل ویژگی‌ای که به‌سختی لیاقت یک پاراگراف را دارد، چه برسد به یک پست کامل. با این حال، من اینجا نشسته‌ام و درباره آن می‌نویسم، چون دقیقاً همین جزئیات برای من مانیفست کوچکی است از اینکه اصلاً چگونه به ساخت ابزار auto-prefix URL و تمام آن تسهیلات نامرئی دیگر فکر می‌کنم.

دو ثانیه در مقابل بیست ثانیه

بیایید محاسبه کنیم. واقعاً، با اعداد، چون در غیر این صورت فقط حرف است.

مسیر اول: پیست می‌کنید، لینک را دارید، پنجره را می‌بندید. دو ثانیه. شاید سه ثانیه.

مسیر دوم: چسباندن (paste)، خطا، خواندن پیام (یک یا دو ثانیه برای درک اینکه موضوع چیست)، اضافه کردن پروتکل، کلیک مجدد، و تازه حالا لینک. پانزده، بیست ثانیه. به اضافه آن لحظه کوچک عصبانیت، آن «آهان درست است، پروتکل» که به تنهایی هزینه‌ای ندارد، اما انباشته می‌شود.

و حالا این را در تعداد دفعاتی که در ماه یک آدرس را کپی می‌کنید، ضرب کنید. برای من، این ده ها بار است. برای کسی که به صورت حرفه‌ای لینک‌ها را مدیریت می‌کند — صدها بار. ناگهان این جزئیات «که به سختی ارزش ذکر کردن دارند»، به چندین دقیقه در ماه تبدیل می‌شوند. به ازای هر نفر.

این دقیقاً همان محاسباتی است که اکثر مردم از آن چشم‌پوشی می‌کنند، زیرا هر مورد به تنهایی بسیار کوچک به نظر می‌رسد که بخواهند نگران آن باشند.

در واقع زیر آن چه می‌گذرد

مکانیزم بسیار ساده است و اصلاً این را پنهان نمی‌کنم. متن را در کادر می‌چسبانید. قبل از اینکه چیزی به سرور ارسال شود، تکه‌ای از 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 تبدیل می‌شوند
  • حروف لهستانی در انتهای اختصاصی (slug) به 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:// را به تو اضافه کرد. فقط یک حس کلی به یاد داری که «به نوعی خوب کار می‌کند» یا «اعصاب خردکن نیست». این حس از هیچ کجا نمی‌آید. این حس از ده‌ها تصمیم پنج‌خطی ساخته شده است که هیچ‌کس به تنهایی نمی‌تواند آن‌ها را در برابر خود به عنوان چیزی که «ارزش وقت گذاشتن داشته باشد» دفاع کند.

شاید اصالتِ حرفه دقیقاً در همین باشد. نه در آن یک حرکت بزرگ، بلکه در پافشاری برای اینکه بارها و بارها در کنار انسان در مقابل فرم‌ها ایستادگی کنیم — حتی اگر بحث از دو ثانیه‌ی ناچیز باشد. و تو؟ اخیراً چه چیزی در یک ابزار آنقدر کوچک باعث عصبانیتت شد که حتی از اعتراف کردن به آن خجالت می‌کشی؟ چون معمولاً بهترین کار برای انجام دادن، دقیقاً همان‌جا نهفته است.