URL形式チェックは「“リンクとして成立しているか”を早めにはじく」ための技
ユーザーに「ホームページURL」「コーポレートサイト」「SNSのURL」などを入力してもらう場面、結構ありますよね。
ここで何もチェックしないと、aaa や example のような、明らかにURLじゃない文字列がDBに入ってしまいます。
後でリンクとして表示しても飛べないし、外部連携でエラーになったりもします。
そこで使うのが URL形式チェック。
これは「この文字列が“URLとしてあり得る形かどうか”をざっくり判定する」ためのユーティリティです。
完璧な判定ではなく、まずは
「明らかにおかしいものを早めにはじく」
というフィルタだと考えると、ちょうどいいです。
まずは「URLのざっくりルール」を押さえる
完璧を目指さず“現場で困らないライン”を決める
URLの正式な仕様(RFC)はかなり複雑です。http, https だけでなく、ftp, mailto, tel などもあるし、
クエリパラメータやフラグメント、IPv6アドレス、IDN(日本語ドメイン)なども絡んできます。
でも、実務でそこまで全部を完璧に扱おうとすると、
正規表現が怪物になって、誰も読めなくなります。
だからまずは、こんな「ざっくりルール」を決めてしまうのが現実的です。
スキーム(http:// や https://)が付いていること
その後にホスト名(example.com など)があること
最低限、「http://example.com ならOK」「example.com だけはNG」くらいの線引き
このくらいでも、「明らかにURLじゃないもの」はかなり弾けます。
Java標準の java.net.URL を使ったシンプルなチェック
「パースできるかどうか」で判定する
URL形式チェックで、まず覚えてほしいのは
「自分で正規表現を書かなくても、Java標準ライブラリでかなり戦える」
ということです。
java.net.URL クラスは、文字列をURLとして解釈できるかどうかをチェックしてくれます。
import java.net.MalformedURLException;
import java.net.URL;
public final class UrlValidator {
private UrlValidator() {}
public static boolean isValidUrl(String url) {
if (url == null || url.isBlank()) {
return false;
}
try {
new URL(url);
return true;
} catch (MalformedURLException e) {
return false;
}
}
}
Java使い方はこうなります。
System.out.println(UrlValidator.isValidUrl("https://example.com")); // true
System.out.println(UrlValidator.isValidUrl("http://example.com/path")); // true
System.out.println(UrlValidator.isValidUrl("ftp://example.com/file.txt")); // true
System.out.println(UrlValidator.isValidUrl("example.com")); // false
System.out.println(UrlValidator.isValidUrl("http//example.com")); // false
System.out.println(UrlValidator.isValidUrl("http:/example.com")); // false
System.out.println(UrlValidator.isValidUrl("")); // false
Javaここで深掘りしたい重要ポイントは二つです。
一つ目は、「“URLとしてパースできるかどうか”を、例外の有無で判定している」ことです。new URL(url) が成功すれば「形式としてはOK」、MalformedURLException が投げられたら「形式としてNG」と判断しています。
二つ目は、「この時点では“スキームの種類”までは絞っていない」ことです。ftp:// や file:/ なども、URLとしては有効なので true になります。
もし「http と https だけ許可したい」なら、もう一段階絞り込みが必要です。
http / https だけに絞りたい場合
スキームをチェックして“Web用URL”に限定する
多くのWebシステムでは、
「ユーザーに入力してほしいのは http か https のURLだけ」
というケースが多いです。
その場合は、URL でパースしたあとに、スキームをチェックします。
import java.net.MalformedURLException;
import java.net.URL;
public final class UrlValidator {
private UrlValidator() {}
public static boolean isHttpOrHttps(String url) {
if (url == null || url.isBlank()) {
return false;
}
try {
URL u = new URL(url);
String protocol = u.getProtocol();
return "http".equalsIgnoreCase(protocol) || "https".equalsIgnoreCase(protocol);
} catch (MalformedURLException e) {
return false;
}
}
}
Java使い方はこうです。
System.out.println(UrlValidator.isHttpOrHttps("https://example.com")); // true
System.out.println(UrlValidator.isHttpOrHttps("http://example.com")); // true
System.out.println(UrlValidator.isHttpOrHttps("ftp://example.com")); // false
System.out.println(UrlValidator.isHttpOrHttps("file:/path/to/file")); // false
System.out.println(UrlValidator.isHttpOrHttps("example.com")); // false
Javaここでのポイントは、「“URLとして成立しているか”と“自分たちが許したいURLか”を分けて考える」ことです。
isValidUrl は「URLとして成立しているか」を見ているだけ。isHttpOrHttps は「その中から、Web用URLだけを許可する」というフィルタです。
この二段構えにしておくと、
用途に応じてどちらを使うか選べるので、コードの意図がとても分かりやすくなります。
正規表現で「最低限の形」だけをチェックする方法
ライブラリを使えない場面向けの“軽量版”
何らかの理由で java.net.URL を使いたくない、
あるいは「もっとざっくりでいいから軽くチェックしたい」という場合は、
正規表現で「最低限の形」だけを見る方法もあります。
例えば、こんなルールを考えます。
http:// または https:// で始まる
その後に、空白を含まない文字が1文字以上続く
これを正規表現にすると、こうなります。
import java.util.regex.Pattern;
public final class UrlValidatorRegex {
private UrlValidatorRegex() {}
private static final Pattern SIMPLE_HTTP_URL =
Pattern.compile("^https?://\\S+$");
public static boolean isSimpleHttpUrl(String url) {
if (url == null || url.isBlank()) {
return false;
}
return SIMPLE_HTTP_URL.matcher(url).matches();
}
}
Java使い方はこうです。
System.out.println(UrlValidatorRegex.isSimpleHttpUrl("https://example.com")); // true
System.out.println(UrlValidatorRegex.isSimpleHttpUrl("http://example.com/path")); // true
System.out.println(UrlValidatorRegex.isSimpleHttpUrl("ftp://example.com")); // false
System.out.println(UrlValidatorRegex.isSimpleHttpUrl("example.com")); // false
System.out.println(UrlValidatorRegex.isSimpleHttpUrl("http://exa mple.com")); // false(空白NG)
Javaここでの重要ポイントは、「この正規表現は“かなりざっくり”だという自覚を持つこと」です。
ホスト名が正しいかどうか、ポート番号が正しいかどうか、
パスやクエリの中身が正しいかどうかまでは見ていません。
あくまで「http:// か https:// で始まっていて、空白が含まれていない」
という最低限の条件だけを見ています。
「形式チェック」と「到達可能かどうか」は別物だと理解する
URL形式チェックユーティリティがやっているのは、
あくまで「文字列の形がURLとして成立しているかどうか」の判定だけです。
https://example.com/unknown が形式的に正しくても、
そのURLにアクセスしたときに 404 になるかもしれません。
「本当に存在するページかどうか」を知りたければ、
実際にHTTPリクエストを投げてステータスコードを見る必要があります。
ここで大事なのは、
「形式チェックは“明らかにおかしいものを弾くフィルタ”であって、“正しいことの保証”ではない」
という感覚を持っておくことです。
例題:入力フォームでのURL形式チェック
ユーザー登録フォームで、「ホームページURL」を入力してもらう場面を考えます。
サーバ側では、こんな感じで使えます。
String url = request.getParameter("homepageUrl");
if (url == null || url.isBlank()) {
// 任意入力ならスキップ、必須ならエラー
// errors.add("ホームページURLを入力してください。");
} else if (!UrlValidator.isHttpOrHttps(url.trim())) {
errors.add("URLの形式が正しくありません。(例:https://example.com)");
}
Javaここでのポイントは二つです。
一つ目は、「未入力かどうか」と「形式が正しいかどうか」を分けている」ことです。
任意入力なら、未入力はOK・形式だけチェック、
必須入力なら、未入力もエラー、というように分けて考えられます。
二つ目は、「チェックに通ったら、そのままDBに保存してもよい状態になっている」ことです。
少なくとも「http / https で始まる」「URLとしてパースできる」
という条件を満たしているので、
後続処理で「明らかにおかしい文字列」に悩まされる可能性がかなり減ります。
まとめ:URL形式チェックユーティリティで身につけたい感覚
URL形式チェックは、「完璧な判定」を目指すものではなく、
「明らかにおかしいものを早めにはじくためのフィルタ」 です。
まずは、
java.net.URL を使って「パースできるかどうか」で判定する
必要なら、スキームを見て http / https に絞る
というシンプルなユーティリティを用意してみてください。
そのうえで、どうしても正規表現でやりたい場面では、^https?://\\S+$ のような「最低限の形」だけを見る軽量版を使う。
もしあなたのコードのどこかに、
String url = request.getParameter("homepageUrl");
// そのままDBに保存
Javaのような箇所があれば、
そこを題材にして、ここで作った UrlValidator.isHttpOrHttps を一度挟んでみてください。
それだけで、「明らかにURLじゃない文字列がシステムに入り込む」リスクを、かなり減らすことができます。

