質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

Q&A

6回答

1717閲覧

URLチェックの精度を上げたい

study_111

総合スコア82

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

1グッド

0クリップ

投稿2020/09/23 01:58

編集2020/09/23 02:56

正規表現を用いたURLチェックを実装しているのですが、現状のチェックメソッドではhttp://aaaこちらの値を入力すると、Trueを返してしまいます。
下記がURLチェックの為に、実装したメソッドになります。

check_url(url){ let re = /https?://[\w/:%#$&?()~.=+-]+/ return re.test(url); },

どなたか、こちらの問題の解決の為、ご助言頂けましたら幸いです。

追記です

以下は、想定しているOKパターン及びNGパターンになります。

○合格のurl例

http://qiita.com
https://qiita.com
https://sample.qiita.com
https://qiita.com/sample
https://qiita.com/sample/aaaa?a=aa
https://qiita.com/sample/aaaa?a=aa&b=bb
https://b.qiita.com/sample/aaaa?a=aa&b=bb

×不合格のurl例

http://qiitaacom
javascript:alert( 'test' )

ruuuu👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2020/09/23 02:03

OKパターン、NGパターン 想定している形式を一通り出された方が良いかと思います。 提示のhttp://aaaもURLとしては一般的には成り立っていると言えます。
study_111

2020/09/23 02:24

ご指摘の部分につきまして、追記しました。
maisumakun

2020/09/23 02:52

aqiita.com」というドメインにはアクセスできてはいけないのですか?
study_111

2020/09/23 02:54 編集

あ...NGパターンいくつかおかしな部分がありました... 修正したいと思います。
study_111

2020/09/23 02:58

修正しました... 現状ですと、「check_url」メソッドには、「http://qiitaacom」こちらの形を弾く部分を追加できたらと、考えております...
think49

2020/09/23 08:02

合格の基準を日本語でも説明したほうが良いと思います。
guest

回答6

0

前も書いた気がするんですがjsでURLチェックするのは費用対効果にあわないので
最低限のものにしてください

投稿2020/09/23 02:07

yambejp

総合スコア116724

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

study_111

2020/09/23 02:41 編集

今回は、出来ましたらUXの仕様上、実装したいと考えております...
yambejp

2020/09/23 02:45

URLのチェックと、存在のチェックは別次元の話です。 またmaisumakunさんの仰るように個人のPC設定次第では 存在するとジャッジする場合もあるので、意味がありません 「https?://.」以上の判断をしたいなら個人PC設定は無視し、 サーバーサイドのプログラムを使うことは必須だと思ってください
study_111

2020/09/23 02:48

ご助言ありがとうございます。 > サーバーサイドのプログラムを使うことは必須だと思ってください はい。今回は、UX上の仕様の為実装しますが、サーバーサイド側でもチェックをかける想定でおります。
yambejp

2020/09/23 03:02

であれば、jsのチェックは「最低限」でやってください 「https?://.」以上のチェックは不要です
study_111

2020/09/23 03:06

>であれば、jsのチェックは「最低限」でやってください「https?://.」以上のチェックは不要です 先ほども記載させて頂きましたが、今回は、js側でのバリデーションはフロント側のUX上の仕様の為に実装するのみの活用を考えています
kyoya0819

2020/09/23 03:12

話がそれ違っているようですが、質問者さんは、送信する前の段階でJSによる値チェックを行いたい。送信時はサーバーサイドでチェックを行うということですよね?
yambejp

2020/09/23 03:16

私の回答は存在チェックはサーバーサイドでしかできないということです サーバーにやらせるならクライアントサイドは最低限のチェックでやります。 またサーバーサイドにAPIを用意させ、非同期にチェックさせるだけです
study_111

2020/09/23 03:20 編集

今回、フロント側でバリデーションを行うのは、送信せずともチェックを行いエラーメッセージが表示出来るメリットを想定してのことでした。まぁ些細な部分かもしれませんが。
yambejp

2020/09/23 03:27

存在のチェックは結局所定のurlにアクセスしてみないとわかりません まずはDNSに問合せ、通ったらアクセスします その上で404や301、500エラーなどをチェックして所在の有無を 確定させますが、403エラーのように実際にはあるかもしれないけど アクセス拒否される場合や、実際にあって転送を前提とする作りに なっていたりとか、所在チェックを精度をもってやるのは相当面倒です。 クライアントサイドのjsでやるのは諦めてください
study_111

2020/09/23 03:32

存在チェックに関しましては、今回は実装を行わないようにしたいと思います。 んーですが、今回でいいますと、単純に 「http://qiitaacom」これは許容せずに「http://qiitaa.com」ここの部分は許容するといった形にしたいのですよね...
yambejp

2020/09/23 03:41

でも「http://qiitaacom」が間違いだと決めつけるのは質問者さんの 思い込みです
study_111

2020/09/23 03:59 編集

maisumakunさんがおっしゃっていましたが、「http://qiitaacom」こちらもURLとして認識がされるとのことでした。 自分はここの部分が曖昧なのですが、「http://qiitaacom」ここの部分のみでURLとして、有効であるもののの、ドメインを取得する際は、トップレベルドメインも指定する必要があるのは何故なのでしょうか...?
yambejp

2020/09/23 04:01

OSは必ずしもDNSだけで名前の解決をしているわけではないからです
guest

0

http://aaaこちらの値を入力すると、Trueを返してしまいます。

それで構わないのではないでしょうか。hostsaaaを設定すれば、 http://aaaアクセス可能です。http://localhostとそんなに変わりません。

投稿2020/09/23 02:00

maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

study_111

2020/09/23 02:15 編集

ご回答ありがとうございます。 例えばなのですが、アドレスバーに「https://google」と指定し、Enterキーを押した場合、アクセス出来ないとの表示がされてしまいます。 その為、「.com」の部分も入力しなければバリデーションに通過しないように設定を行いたいと考えていました。
maisumakun

2020/09/23 02:33

上に書いたように、「https://google」でアクセスできないのは設定次第です(実際、TeratailのシステムでもURLと認識してリンクを張っています)。
study_111

2020/09/23 02:40

>「https://google」でアクセスできないのは設定次第です 設定というのは、ブラウザ側の設定ということでしょうか?
maisumakun

2020/09/23 02:45

OSレベルの設定です。
maisumakun

2020/09/23 02:54

こういう判定でいちばんやってはいけないことは、「正当な入力を拒否してしまう」ことです。 質問内容を見ている限り、正当なURLを拒否するような形が多いので、そんなものを実装するぐらいならないほうがマシです。
maisumakun

2020/09/23 02:58

(たとえば、メールアドレスでは、RFC違反のアドレスが存在してしまっているので、RFCに沿ったチェックですら不適当となる場合がありえます)
study_111

2020/09/23 03:02

現状、サーバー側でもチェックをかけているのですが、「http://qiitaacom」こちらのような形は弾いている為、JS側でも弾くように実装したいとは思っているのですよね...
study_111

2020/09/23 03:13

サーバー側では、Djangaを使用しているのですが、Djangoライブラリの「URLValidator」を使用しており、そこでも「http://qiitaacom」こちらのチェックは弾かれる為、フロント側でも出来たら弾きたいのですよね。。
maisumakun

2020/09/23 08:06

では、そのロジックを確認しましょう。
guest

0

Djangoライブラリの「URLValidator」を使用しており、そこでも「http://qiitaacom」こちらのチェックは弾かれる為、フロント側でも出来たら弾きたいのですよね。。

django/validators.py at master · django/django · GitHub

Django の URLVaridator のソースコードです。正規表現でチェックしているので、移植はそれほど難しくないと思います。

追記

Python をブラウザ上で動かすという方法も無くはありません。

https://www.publickey1.jp/blog/19/pythonwebassemblywebpythonpyodidemozilla.html
(開発中)

またはバックエンドがいじれるならバリデーション API を作り、フロントでは URL オブジェクトを作れるかどうかを判定して、それに通ったものだけ API で問い合わせるという方法もあります。

投稿2020/09/23 09:56

編集2020/09/23 23:26
Zuishin

総合スコア28669

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

文法規則

○合格のurl例

plain

1http://qiita.com 2https://qiita.com 3https://sample.qiita.com 4https://qiita.com/sample 5https://qiita.com/sample/aaaa?a=aa 6https://qiita.com/sample/aaaa?a=aa&b=bb 7https://b.qiita.com/sample/aaaa?a=aa&b=bb

×不合格のurl例

plain

1http://qiitaacom 2javascript:alert( 'test' )

ご掲示のURLは全て「正しいURL」です。
期待する動作を得る為には合格or不合格のURLの文法規則を study_111 さんが確定させる必要があります。

new URL()

URL() コンストラクタを利用すると、比較的簡単に実装できます。
「URLの文法規則」は質問文にないので、想像で補完しました。

※質問に「文法規則」を書かないと、回答者は正しいコードを書けませんので、質問時に注意する事をお勧めします。

JavaScript

1'use strict'; 2const okList = ['http://qiita.com','https://qiita.com','https://sample.qiita.com','https://qiita.com/sample','https://qiita.com/sample/aaaa?a=aa','https://qiita.com/sample/aaaa?a=aa&b=bb','https://b.qiita.com/sample/aaaa?a=aa&b=bb']; 3const ngList = ['http://qiitaacom','javascript:alert( \'test\' )']; 4 5function isCustomValidUrl (urlString) { 6 try { 7 const url = new URL(urlString); 8 return url.hostname.includes('.') && url.protocol !== 'javascript:'; 9 } catch (e) { 10 return false; 11 } 12} 13 14console.assert(JSON.stringify(okList.filter(isCustomValidUrl)) === JSON.stringify(okList)); 15console.assert(JSON.stringify(ngList.filter(isCustomValidUrl)) === '[]');

正規表現

正規表現を用いたURLチェックを実装しているのですが、

正規表現に拘るなら、RFC3986を元に組んだことが有ります。

現在では「URL Standard」が最も新しいと思われますので、そちらを参考に正規表現を組むと良いと思います。

Re: study_111 さん

投稿2020/09/23 07:50

編集2020/09/23 08:04
think49

総合スコア18189

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

study_111

2020/09/23 09:16 編集

ご回答ありがとうございます。 URLに関しては、自分も良く分かっていない部分があります為、正規表現のサンプル「 /https?://[\w/:%#$&?()~.=+-]+/ 」を使用することしたのですが、「http://qiitaacom」こちらを通してしまうことが発覚してしまいました為、新たに条件を加える必要が出てきてしまったといった経緯でした。 OKパターンに関しては、Qiita記事で見つけた引用もあります為、自分でも把握出来ていない部分がある為、出来ましたら正規表現での実装を考えております。 サーバーサイド側では、現在、Djangoによる実装を行なっているのですが、URLのバリデーションは、 「 https://docs.djangoproject.com/ja/3.0/_modules/django/core/validators/ 」の「 URLValidator」によって行なっております。 その為、こちらと同じパターンでのバリデーションをJS側でも実装したいと考えておりました。
think49

2020/09/23 09:36 編集

> URLに関しては、自分も良く分かっていない部分があります為、正規表現のサンプル「 /https?://[\w/:%#$&?()~.=+-]+/ 」を使用することしたのですが、「http://qiitaacom」こちらを通してしまうことが発覚してしまいました為、新たに条件を加える必要が出てきてしまったといった経緯でした。 まず、大前提ですが、「よくわからないもの」を作ることは出来ません。 私は「×不合格のurl例」から - ホスト名に . を一つ以上含まなければならない - javascript: スキームであってはならない という規則性を読み取りましたが、それすらも「よくわからない」のでしたら、「あなたが作りたいように作ってください」と突き放すようなアドバイスしか出来ません。 少なくとも、コードを作るにあたって、そのコードを実行させる目的があるはずですが、それすらも分からないのでしょうか。 だとしたら、納品先orソースコードの管理者に要求仕様を確認するのが第一歩だと思いました。 > サーバーサイド側では、現在、Djangoによる実装を行なっているのですが、URLのバリデーションは、 > 「 https://docs.djangoproject.com/ja/3.0/_modules/django/core/validators/ 」の「 URLValidator」によって行なっております。 サーバサイド側のソースコードが判明しているのであれば、「ソースコードを読み取って、JavaScriptコードに変換する」という誰もが考え付く当たり前の解決方法になります。 何が障害となっているのでしょうか。
think49

2020/09/23 09:38

https://docs.djangoproject.com/en/3.1/ref/validators/#urlvalidator > URL/URI scheme list to validate against. If not provided, the default list is ['http', 'https', 'ftp', 'ftps']. As a reference, the IANA website provides a full list of valid URI schemes. という事ですから、javascript: schemeがNGなのは読み取れますよね。 RFC 3986にはそんな制約はありませんので、これはdjango側の仕様です。
study_111

2020/09/23 10:01 編集

> サーバサイド側のソースコードが判明しているのであれば、「ソースコードを読み取って、JavaScriptコードに変換する」という誰もが考え付く当たり前の解決方法になります。 実は、正規表現に慣れておらず、こちらの部分が少々難しく出来ていない状態なのですよね...
think49

2020/09/23 10:01

「少々難しく」の質問に回答を返す事は出来ないので、具体的に質問して下さい
study_111

2020/09/23 10:06

そうですね...まず、URLValidatorクラスの「 ul = '\u00a1-\uffff' 」ここの部分から何が行われているか、わからないといった状況です...
think49

2020/09/23 10:14

> まず、URLValidatorクラスの「 ul = '\u00a1-\uffff' 」ここの部分から何が行われているか、わからないといった状況です... Pythonは専門外ですが、公式マニュアルを参照したところでは、 https://docs.python.org/ja/3.10/reference/lexical_analysis.html#literals 文字列リテラルで「16-bit の十六進値 00a1 を持つ文字」と「16-bit の十六進値 ffff を持つ文字」を作って、変数に格納していますね。 このレベルでわからないようでしたら、基礎学習が足りてないと思うので、Python入門書、解説サイト、公式マニュアルを駆使して一から学習すべきだと思います。
study_111

2020/09/23 10:40 編集

こちら、Pythonコードを解析して、javascriptコードに変換となりますと、Python,JavaScriptの両方に精通している必要がありますし、少々難易度が高い作業なように思えます...
think49

2020/09/23 10:44 編集

はい。JavaScript,Pythonの両方を理解する必要があります。 難易度は人によるので何とも言えませんが、目的が「djangoのURLValidatorと同じ機能をJavaScriptで実装したい」なら必要経費のように思います。 逆にお聞きしたいのですが、いろいろなこと(Python/正規表現/djangoの仕様)が分かっていない状況でどうやって作ろうとしていたのでしょうか。
study_111

2020/09/23 10:49

今回、ネックとなってしまっているのが、正規表現の部分だと認識していますし、一度DjangoのURLバリデータのコードに関しましては、色々調べるなどし、移植作業を行うか、別の方法で実装するか検討してみたいと思います。
guest

0

そのURLにリクエスト飛ばして、ステータス200を判定すれば精度100%じゃない?

投稿2020/09/23 07:56

phper.k

総合スコア3923

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

正規表現を用いたURLチェック

IE 以外が対象であれば、以下のネイティブ実装を使ったほうがよいかもしれません。


正規表現を用いるケースとしては CODEPEN parseURL() を回答したことがあります
whitelist / blacklist 併用を想定した単純な字句解析です)。

追記)

ご助言頂けましたら

クライアントサーバモデル はご存知と思いますが、再確認してみてください。
クライアント(ブラウザ)側の JavaScript で出来ることは2つに限られます。

  1. Ajaxでサーバー(API)にDNS問い合わせを含めた厳密なURLチェックするように要求し、結果を得る

(リクエスト数 +1で実現可能)
2. DNS問い合わせまでは行わず、URL(文字列)を判別し、予め用意したリストと照合するに留める
(リクエスト数 +0で実現可能)

共に回答は出揃っていますが、「正規表現」が要となるのは、後者の方法でPOST前の簡易チェックに留めるケースです。
「2つある方法のうち、いずれかを選択する」というアプローチを検討してもよいと思います。

投稿2020/09/23 03:06

編集2020/09/23 22:47
AkitoshiManabe

総合スコア5434

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問