本文へ移動
cutty.dev
All posts

Auto-prefix URL — 数分を節約できる些細な工夫

cutty.devは、https://なしでアドレスを貼り付けても、自動的にそれを追加して認識します。些細なことに聞こえるかもしれませんが、実際には2秒の差か、「もう一度やり直してください」というクリック操作を挟むかの違いなのです。

allegro.pl のフォームに入力します。クリックします。それで、どうなりますか?

ほとんどの短縮サービスでは、この時点でエラーメッセージが表示されます。「これは正しいURLではありません」といった内容です。なぜなら、先頭に https:// がないからです。そのため、一度戻ってプロトコルを書き加え、もう一度クリックすることで、ようやく短いリンクが手に入ります。

cutty.dev はそんなことはしません。ただ単に https:// を自分自身で付け足して、何事もなかったかのように進むだけです。

どう聞こえるかは分かっています。記事全体どころか、段落にすら値しないような機能のように聞こえるでしょう。それでも、私はこうして書き続けています。なぜなら、この些細なことが、auto-prefix URLツールやその他の目に見えない利便性を構築することについて、私が根本的にどのように考えているかを示す、私にとっての小さなマニフェストだからです。

2秒対20秒

計算してみましょう。本当に、数字で。そうでなければ、ただの口先だけの話になってしまいますから。

第1のルート:貼り付けて、リンクを取得して、ウィンドウを閉じる。2秒。あるいは3秒。

第2のルート:貼り付ける、エラーが出る、メッセージを読む(何が起きているか理解するのに1〜2秒)、プロトコルを書き足す、もう一度クリックする、そしてようやくリンク。15、20秒。それに、あの小さな苛立ちの瞬間、つまり「あ、そうだった、プロトコル」という、単体では何も問題にならないけれど、積み重なっていくあの静かな感覚。

そして、これを1ヶ月に何回アドレスを貼り付けているかに掛け合わせてみてください。私の場合、数十回です。プロとしてリンクを管理している人なら、数百回でしょう。すると、この「取るに足らない」些細なことが、一人あたり月間で数分間の蓄積へと変わります。

これこそが、ほとんどの人が見過ごしてしまう算術です。なぜなら、一つ一つの事例が、気にするにはあまりにも小さすぎると見えるからです。

実際、その下には何があるのか

メカニズムは極めて単純であり、それを隠すつもりも全くありません。テキストをフィールドに貼り付けます。何かがサーバーに送信される前に、JavaScriptの一部が、入力された内容が特定のプロトコル(http://, https://, ftp://, mailto: など)で始まっているかどうかを確認します。もし始まっていない場合、システムは単なるドメインであると判断し、先頭に https:// を付け加えます。

実務では:

  • allegro.plhttps://allegro.pl に変わります
  • github.com/twoj-profil/projekthttps://github.com/twoj-profil/projekt に変わります
  • www.gazeta.plhttps://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)
}

5行。アドレスを貼り付けるすべての人にとって、毎日数秒の摩擦が減ります。正直なところ、なぜこれがどこでも標準になっていないのか分かりません。おそらく、「URLコンストラクタがそのまま機能している」からで、誰もそれに手を加えようとしなかったのだと思います。悪意ではなく、慣性によるものです。

「標準的」とはどういう意味かについての短い余談


new URL() に関するこの話は、より広範な事象の素晴らしい例です。ソフトウェアにおいて「こうするのが当たり前」とされていることの多くは、実際には「誰も疑問を呈さなかった、あるライブラリのデフォルト設定の結果に過ぎない」のです。コンストラクタの strict mode は、cutty の設計者や競合他社による決定ではありません。それは、全く異なる文脈において、全く異なる用途のために下された URL 仕様策定者による決定なのです。

そして、市場全体がこのデフォルトの選択を引き継ぎ、それを「標準」と呼びます。最高の製品は、まさに誰かが立ち止まって、「待てよ、この挙動はユーザーのためなのか、それとも単に自分のライブラリのためなのか?」と問いかけた場所から生まれるのだと感じています。多くの場合、その答えは「ライブラリのため」です。だからこそ、わずか5行のコードで、人間の側に立ち返る価値があるのです。

これらの細かな点は、見た目以上に多く存在します

Auto-prefixは、機能リストのどこにも載っていないような要素の、ほんの数多くあるうちの一つに過ぎません。もしそれらをすべて書き出そうとすれば、一つひとつがとても些細なものに見えてしまうからです。

  • バリデーション前にスペースをトリミングし、貼り付けたアドレスの末尾に誤ってスペースが入っていてもすべてが壊れないようにします
  • アンカー(フラグメント)を保持します。つまり、https://example.com/page#section 内の #section は短縮後も消えません
  • クエリパラメータ (?utm_source=test) はそのまま引き継がれ、途中で切り捨てられることはありません
  • ポーランド語の文字を含むドメイン(例:źdźbło.pl)は、自動的にpunycodeに変換されます
  • 独自の末尾に含まれるポーランド語の文字はASCIIに変換されます(例:różowy-linkrozowy-link になります)
  • 危険なプロトコル — javascript:, data:, file: — は、具体的で分かりやすいメッセージとともに拒否されます

(ターゲットサーバーが暗号化をサポートしている場合、http://https:// へ自動的にアップグレードする機能も計画されています。これは現時点ではまだ本番環境では動作していないため、隠さずにお伝えします。)

これらの詳細のそれぞれが、誰かの5秒、10秒、30秒、そして一度のため息を節約しています。単体では何の意味もありません。しかし合わせれば、「まあまあ動く」と「使うのが楽しい」の差となります。

これから追加したいこと

将来のウィッシュリスト、これについて考えるのはただただ楽しいからです:

  • スマート貼り付け — 文中のアドレスを検出し、単語の中からURLのみを抽出します
  • 一括貼り付け — 1行に1つのアドレスのリストから、即座に個別の短縮リンクを作成します
  • サジェスト末尾 — 遷移先ページのタイトルに基づき、選べる3つのブランド化されたスラッグを提案します
  • 貼り付け直後のOpen Graphプレビュー — 「短縮」をクリックする前にプレビューを表示します

これらはすべて、再び「何の意味もなさそうな5行の関数」に過ぎません。では、それらがすべて合わさるとどうなるでしょうか? それこそが、単に「まあまあなツール」と、「何も考えずに毎日手に取るツール」との境界線なのです。今すぐそれがどのように機能するかを確認したい場合は、cutty.dev にプロトコルなしの何でもいいので — allegro.plgithub.comnews.ycombinator.com — を貼り付けてみてください。何も邪魔されないことがわかるはずです。

最後に、少し個人的な話を

長い間、製品は素晴らしい機能によって勝利するものだと考えていました。スライドで見せることができ、人々が書き記したくなるような、あのたった一つの印象的な何かによって。そして、確かに、時にはその通りなこともあります。

cuttyを構築すればするほど、ユーザーのロイヤリティは別の場所、つまり誰も意識することのない何百ものマイクロ秒の中に生まれるのだと強く感じる。ツールが自動的に https:// を追加したことなど覚えていない。ただ、「なんとなく使い心地が良い」「イライラしない」という全体的な印象だけを覚えている。この印象はどこからともなく湧いてくるのではない。それは、単体では誰も「時間をかける価値がある」とは認めないような、数十もの5行程度の小さな決断の積み重ねによって構成されている。

おそらく、それこそが職人技の本質なのだろう。たった一度の大きな動きではなく、たとえわずか2秒間であっても、フォーム入力の際に繰り返し人間の味方であり続けようとする執念のことだ。さて、君はどうだ? 最近、ツールに対して、あまりに些細すぎて認めるのが恥ずかしいくらいに腹が立ったことはないか? なぜなら、通常、最高の仕事が待っているのは、まさにそのような場所にこそあるのだから。