ตรวจสอบว่าสตริง JavaScript เป็น URL หรือไม่


284

มีวิธีใน JavaScript เพื่อตรวจสอบว่าสตริงเป็น URL หรือไม่?

regexes ได้รับการยกเว้นเนื่องจาก URL ที่เขียนส่วนใหญ่มีแนวโน้มเช่นstackoverflow; ที่จะบอกว่ามันอาจจะไม่ได้.com, หรือwwwhttp


22
หากไม่มีhttpจะเป็นค่าเริ่มต้นที่ไม่มี URL
nfechner

1
@nfechner ที่จะกล่าวว่าหากไม่ได้ระบุโปรโตคอลและใช้อักขระโคลอน (ควรมีเครื่องหมายทับสองข้างถัดไป) ถ้าเป็นเช่นนั้นไม่ใช่ URL ใช่หรือไม่
jcolebrand

5
ดังที่คุณสามารถอ่านได้ในURL RFCเพียงส่วนเดียวที่จำเป็นในการทำให้สตริงเป็น URL ที่ถูกต้องคือโคลอน URL ที่ถูกต้องมีลักษณะดังนี้:<scheme>:<scheme-specific-part>
nfechner


8
วิธีที่คุณทดสอบว่าบางสิ่งนั้นเป็น URL นั้นขึ้นอยู่กับบริบทอย่างมากและคลุมเครือเกินไปโดยไม่มีการรับรองเพิ่มเติม มันมีความสำคัญกับคุณหรือไม่ว่าเป็นไปตามข้อกำหนด URL RFC หรือไม่ทำงานเมื่อมีการเรียกระบบปฏิบัติการเพื่อเปิด URLแยกวิเคราะห์เป็นองค์ประกอบhrefในสมอทำงานเมื่อโทรwindow.open(url)ชี้ไปที่สิ่งที่มีอยู่จริงทำงานในตำแหน่งเบราว์เซอร์ แถบหรือการรวมกันของข้างต้นหรือไม่ คุณจะได้รับคำตอบที่แตกต่างกันมากขึ้นอยู่กับว่าคุณสนใจเรื่องไหน
Roy Tinker

คำตอบ:


189

คำถามที่เกี่ยวข้องกับคำตอบ:

Javascript regex URL ที่ตรงกัน

หรือ Regexp นี้จากDevshed :

function validURL(str) {
  var pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol
    '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
    '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
    '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
    '(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
    '(\\#[-a-z\\d_]*)?$','i'); // fragment locator
  return !!pattern.test(str);
}

1
ฉันรู้ แต่ฉันกำลังค้นหาในบุ๊กมาร์กของฉันและส่วนใหญ่เขียนเหมือน stackoverflow (โดยไม่ต้องมี. com, ฯลฯ )
Bruno

3
@Bruno: มีโอกาสมากที่พวกเขาจะถูกบันทึกไว้ภายในด้วยชื่อและ URL แยกต่างหากเช่น{ title: "Stackoverflow", uri: "http://stackoverflow.com" } อัปเดต:แน่นอนดูcode.google.com/chrome/extensions/bookmarks.html
Marcel Korpel

10
พยายามใช้ตัวอย่างของคุณ invalid quantifierแต่ฉันได้รับข้อผิดพลาดในวางเพลิงซึ่งบอกว่า ความคิดใด ๆ
Sisir

125
ฟังก์ชันส่งคืน: SyntaxError: Invalid regular expression: /^(https?://)?((([a-zd]([a-zd-]*[a-zd])*).)+[a-z]{2,}|((d{1,3}.){3}d{1,3}))(:d+)?(/[-a-zd%_.~+]*)*(?[;&a-zd%_.~+=-]*)?(#[-a-zd_]*)?$/: Invalid group Google Chrome (รุ่น 30.0.1599.101) (Mac OS X: 10.8.5)
dr.dimitru

10
โปรดทราบว่าถ้าคุณใช้สตริงเป็นพารามิเตอร์สำหรับRegExpคุณต้องหลบหนีคู่ backslashes - อื่นที่คุณได้รับข้อผิดพลาดเช่นกลุ่มที่ไม่ถูกต้อง
Kjell

165
function isURL(str) {
  var pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol
  '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|'+ // domain name
  '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
  '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
  '(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
  '(\\#[-a-z\\d_]*)?$','i'); // fragment locator
  return pattern.test(str);
}

13
ล้มเหลวในการเชื่อมโยงรูปภาพการค้นหาของ Google:http://www.google.com/url?sa=i&rct=j&q=&esrc=s&source=images&cd=&docid=nIv5rk2GyP3hXM&tbnid=isiOkMe3nCtexM:&ved=0CAUQjRw&url=http%3A%2F%2Fanimalcrossing.wikia.com%2Fwiki%2FLion&ei=ygZXU_2fGKbMsQTf4YLgAQ&bvm=bv.65177938,d.aWc&psig=AFQjCNEpBfKnal9kU7Zu4n7RnEt2nerN4g&ust=1398298682009707
davis เรียกเก็บเงิน

7
นี่ใช้ไม่ได้ช้า
Hernán Eche

3
@ HernánEcheดังนั้นสิ่งที่คุณหมายถึงช้า ? start = new Date(); isURL("http://michalstefanow.com"); end = new Date(); diff = end - start; console.log(diff)ฉันใส่กาต้มน้ำเข้าไปในห้องน้ำเรียกแม่ของฉันและสิ่งที่ทำในเวลาไม่นาน ...
Mars Robertson

62
ก็จะส่งกลับสำหรับtrue aaa
alex naumov

1
สิ่งนี้ไม่ควรเป็นคำตอบที่ถูกต้อง มันล้มเหลวในหลาย ๆ กรณีทดสอบและที่สำคัญกว่านั้นคือมันทำให้หน้าของคุณแฮงค์แม้กระทั่งสายอักขระสั้น ๆ : isURL('12345678901234567890123')เพิ่มตัวละครเพิ่มขึ้นและยิ่งแย่ลงไปอีก
aamarks

142

คุณสามารถลองใช้คอนURLสตรัคเตอร์ : ถ้ามันไม่โยนสตริงนั้นเป็น URL ที่ถูกต้อง:

function isValidUrl(string) {
  try {
    new URL(string);
  } catch (_) {
    return false;  
  }

  return true;
}

คำว่า 'URL' ถูกกำหนดในRFC 3886 (เป็น URI); จะต้องเริ่มต้นด้วยชื่อแบบแผนและชื่อแบบแผนไม่ จำกัด ที่ http / https

ตัวอย่างที่น่าสังเกต:

  • www.google.com ไม่ใช่ URL ที่ถูกต้อง (รูปแบบที่ขาดหายไป)
  • javascript:void(0) เป็น URL ที่ถูกต้องแม้ว่าจะไม่ใช่ HTTP ก็ตาม
  • http://..เป็น URL ที่ถูกต้องกับโฮสต์เป็น..; การแก้ไขจะขึ้นอยู่กับ DNS ของคุณหรือไม่
  • https://google..com เป็น URL ที่ถูกต้องเช่นเดียวกับด้านบน

หากคุณต้องการตรวจสอบว่าสตริงเป็น URL HTTP ที่ถูกต้องหรือไม่:

function isValidHttpUrl(string) {
  let url;

  try {
    url = new URL(string);
  } catch (_) {
    return false;  
  }

  return url.protocol === "http:" || url.protocol === "https:";
}

13
@ ไม่ต้องใช่มันไม่ใช่ เช่นคุณไม่สามารถใช้เป็นแอตทริบิวต์สำหรับhref <a>URL ที่ถูกต้องจะต้องเริ่มต้นด้วยชื่อโครงการhttps://เช่น
Pavlo

3
ใหม่ URL ('javascript: alert (23)')
blade091

6
@Pavlo สิ่งนี้จะส่งกลับจริงisValidUrl("javascript:void(0)")
Praveena

3
ฉันชอบสิ่งนี้สำหรับสอนสิ่งใหม่เกี่ยวกับ js! ไม่มีเชิงลบที่ผิดที่ฉันสามารถหาได้ มันมีผลบวกบางอย่างที่ผิดพลาด: http://..หรือhttp:///a
aamarks

2
URL เริ่มทำงานจาก Edge ดังนั้นทุกอย่างด้านล่างอาจไม่ทำงานอย่างที่คุณคาดไว้ ตรวจสอบให้แน่ใจว่าคุณตรวจสอบความเข้ากันได้ก่อน
Tony T.

97

แทนที่จะใช้การแสดงออกปกติฉันขอแนะนำให้ใช้องค์ประกอบจุดยึด

เมื่อคุณตั้งค่าhrefคุณสมบัติของanchorคุณสมบัติอื่น ๆ จะถูกตั้งค่า

var parser = document.createElement('a');
parser.href = "http://example.com:3000/pathname/?search=test#hash";

parser.protocol; // => "http:"
parser.hostname; // => "example.com"
parser.port;     // => "3000"
parser.pathname; // => "/pathname/"
parser.search;   // => "?search=test"
parser.hash;     // => "#hash"
parser.host;     // => "example.com:3000"

แหล่ง

อย่างไรก็ตามหากค่าhrefถูกผูกไว้กับไม่ใช่ URL ที่ถูกต้องค่าของคุณสมบัติเสริมเหล่านั้นจะเป็นสตริงว่าง

แก้ไข:ตามที่ระบุไว้ในความคิดเห็น: หากมีการใช้ URL ที่ไม่ถูกต้องคุณสมบัติของ URL ปัจจุบันอาจถูกทดแทน

ดังนั้นตราบใดที่คุณไม่ได้ผ่าน URL ของหน้าปัจจุบันคุณสามารถทำสิ่งต่อไปนี้:

function isValidURL(str) {
   var a  = document.createElement('a');
   a.href = str;
   return (a.host && a.host != window.location.host);
}

3
นี่ไม่ใช่กรณี (ใน Chrome 48 เป็นอย่างน้อย) หาก url ที่ส่งไปยังa.hrefไม่ถูกต้องให้parser.hostส่งคืนชื่อโฮสต์ของหน้าเว็บที่คุณเปิดอยู่ไม่ใช่ชื่อที่คาดfalseไว้
Sam Beckham

2
Gah! แปลกแฮะ, แปลกนะ, มันแปลก ๆ นะ. ฉันสาบานว่าฉันจะทดสอบสิ่งนี้! ฉันคิดว่ามันยุติธรรมที่จะบอกว่าสิ่งนี้จะไม่ถูกนำมาใช้จริงในหน้าปัจจุบันดังนั้นเงื่อนไขสามารถเปลี่ยนแปลงได้ ฉันจะแก้ไขโพสต์
ลุค

มันไม่ได้เป็นกรณีการใช้งานทั่วไปมาก แต่เทคนิคนี้ใช้ไม่ได้กับบริบทของหน้าต่างเบราว์เซอร์ Firefox (สำคัญสำหรับการพัฒนา addon)
chrmod

@ SamBeckham นี่เป็นข้อกังวลอย่างแน่นอนเมื่อใช้วิธีนี้ แต่ฉันแค่อยากจะชี้ให้เห็นว่านี่ไม่ใช่พฤติกรรมพิเศษ หากคุณมีลิงก์ในหน้าเพจของคุณที่ไม่ถูกต้องเช่น<a href="invalidurl">นั้นจะไปที่โดเมนของคุณ มันได้รับการเพิ่มในตอนท้ายของ URL ปัจจุบัน ดังนั้น Chrome จึงทำสิ่งที่ถูกต้องโดยให้ชื่อโฮสต์ปัจจุบันจากองค์ประกอบ "parser"
yts

4
function isValidURL(str): ดีกว่าการใช้ regex! ขอบคุณ!
Rodrigo

47

ฉันใช้ฟังก์ชันด้านล่างเพื่อตรวจสอบความถูกต้องของ URL ด้วยหรือไม่http/https:

function isValidURL(string) {
  var res = string.match(/(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g);
  return (res !== null)
};

var testCase1 = "http://en.wikipedia.org/wiki/Procter_&_Gamble";
console.log(isValidURL(testCase1)); // return true

var testCase2 = "http://www.google.com/url?sa=i&rct=j&q=&esrc=s&source=images&cd=&docid=nIv5rk2GyP3hXM&tbnid=isiOkMe3nCtexM:&ved=0CAUQjRw&url=http%3A%2F%2Fanimalcrossing.wikia.com%2Fwiki%2FLion&ei=ygZXU_2fGKbMsQTf4YLgAQ&bvm=bv.65177938,d.aWc&psig=AFQjCNEpBfKnal9kU7Zu4n7RnEt2nerN4g&ust=1398298682009707";
console.log(isValidURL(testCase2)); // return true

var testCase3 = "https://sdfasd";
console.log(isValidURL(testCase3)); // return false

var testCase4 = "dfdsfdsfdfdsfsdfs";
console.log(isValidURL(testCase4)); // return false

var testCase5 = "magnet:?xt=urn:btih:123";
console.log(isValidURL(testCase5)); // return false

var testCase6 = "https://stackoverflow.com/";
console.log(isValidURL(testCase6)); // return true

var testCase7 = "https://w";
console.log(isValidURL(testCase7)); // return false

var testCase8 = "https://sdfasdp.ppppppppppp";
console.log(isValidURL(testCase8)); // return false


2
ดูเหมือนจะเป็นทางออกที่ดี! คุณสามารถเพิ่มการทดสอบบางรายการที่แสดงว่าทำงานได้ในบางกรณี (ดูตัวอย่างความคิดเห็นเหล่านี้)
Basj

@Basj เพิ่มกรณีทดสอบ โปรดตรวจสอบ
Vikasdeep Singh

ไม่เลวเลยล้มเหลวในการส่ง http: //⌘.wsหรือ142.42.1.1และอนุญาตให้ http: //.www.foo.bar./ แต่มันไม่ติดเช่น regex อื่น ๆ รวมถึงคำตอบที่ได้รับคะแนนสูงสุด
aamarks

@aamarks ฉันตรวจสอบคำตอบของคุณแล้ว คำตอบของคุณคือการล้มเหลวhttps://sdfasdp.pppppppppppเช่นกลับtrueแต่ผลตอบแทนของfalseฉันที่ฉันคิดว่า
Vikasdeep Singh

4
มันกลับมาจริงหรือsadf@gmail.com... ฉันเดาว่าไม่ควร
Zohab Ali

35

ในการตรวจสอบ URL โดยใช้จาวาสคริปต์แสดงอยู่ด้านล่าง

function ValidURL(str) {
  var regex = /(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/;
  if(!regex .test(str)) {
    alert("Please enter valid URL.");
    return false;
  } else {
    return true;
  }
}

3
หลายส่วนของ regex สามารถลดลงอย่างมากมาย: a) (http|https)ถึง(?:https?); b) :{0,1}ถึง:?; c) [0-9]ถึง\d
Dmitry Parzhitsky


23

ปรับปรุงคำตอบที่ยอมรับ ...

  • ตรวจสอบ ftp / ftps เป็นโปรโตคอล
  • มีการหลบหนีสองเท่าสำหรับแบ็กสแลช (\\)
  • ตรวจสอบให้แน่ใจว่าโดเมนมีจุดและส่วนขยาย (.com .io .xyz)
  • อนุญาตให้ใช้โคลอนแบบเต็ม (:) ในเส้นทางเช่นhttp://thingiverse.com/download:1894343
  • อนุญาตให้แอมเปอร์แซนด์ (&) อยู่ในเส้นทางเช่นhttp://en.wikipedia.org/wiki/Procter_&_Gamble
  • อนุญาตสัญลักษณ์ @ ในเส้นทางเช่นhttps://medium.com/@techytimo

    isURL(str) {
      var pattern = new RegExp('^((ft|htt)ps?:\\/\\/)?'+ // protocol
      '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name and extension
      '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
      '(\\:\\d+)?'+ // port
      '(\\/[-a-z\\d%@_.~+&:]*)*'+ // path
      '(\\?[;&a-z\\d%@_.,~+&:=-]*)?'+ // query string
      '(\\#[-a-z\\d_]*)?$','i'); // fragment locator
      return pattern.test(str);
    }

5
ไม่ควรเป็นคำตอบที่ยอมรับไม่ได้ เช่นเดียวกับคนอื่น ๆ มันค้างอยู่ที่สตริงอักขระ 33 ตัวเท่านั้น: isURL ('123456789012345678901234567890123') และล้มเหลวในการทดสอบกรณีขอบจำนวนมาก: foo.com/blah_blah_(wikipedia)_(again) // ผลตอบแทนที่ไม่ถูกต้อง
aamarks

2
นั่นเป็นเพราะ localhost: 8080 ไม่ใช่ URL ที่ถูกต้อง
เชน

1
ตัวอย่างการทำงาน: runkit.com/shanekenyon87/5bc0e57263c77b0012db05dc
Shane

ควรเป็น ftps: // localhost: 8080 =)
vp_arth

ดูเหมือนจะใช้งานไม่ได้: แฮงค์กับอินพุตที่ยาว (เช่น @aanmarks พูด)
cecemel

13

นี่คือวิธีอื่น

var elm;
function isValidURL(u){
  if(!elm){
    elm = document.createElement('input');
    elm.setAttribute('type', 'url');
  }
  elm.value = u;
  return elm.validity.valid;
}

console.log(isValidURL('http://www.google.com/'));
console.log(isValidURL('//google.com'));
console.log(isValidURL('google.com'));
console.log(isValidURL('localhost:8000'));


รหัสการศึกษา! กลไกที่นี่อาจเหมือนกับnew URL(string)รหัสใน Pavlo การทดสอบทั้งคู่มีผลลัพธ์ที่เหมือนกันกับเคสขอบทั้งหมดที่ฉันทดสอบ ฉันชอบรหัสของเขาเพราะมันง่ายกว่าและไม่เกี่ยวข้องกับการสร้างองค์ประกอบ แต่คุณจะเร็วขึ้นสองสามครั้ง (อาจเป็นเพราะมันไม่ได้สร้าง el หลังจากใช้ครั้งแรก)
aamarks

1
ขอบคุณ! ฉันใช้คำแนะนำของคุณ อย่างไรก็ตามโปรดทราบ: เบราว์เซอร์ที่เก่ากว่าและ / หรืออุปกรณ์มือถือ WebView อาจไม่ได้ใช้องค์ประกอบ <input type = url> ดังนั้นค่าอินพุตจะได้รับการปฏิบัติเช่นเดียวกับข้อความปกติ (ไม่มีการตรวจสอบ URL) REF: developer.mozilla.org/en-US/docs/Web/HTML/Element/input/url
Panini Luncher

10

(ฉันไม่มีพนักงานให้ความเห็นเกี่ยวกับValidURLตัวอย่างดังนั้นโพสต์นี้เป็นคำตอบ)

ในขณะที่การใช้งานของ URL สัมพัทธ์โปรโตคอลไม่ได้รับการสนับสนุน ( URL ที่พิธีสารญาติ ) พวกเขาจะได้รับการจ้างงานในบางครั้ง เพื่อตรวจสอบ URL ดังกล่าวด้วยการแสดงออกปกติส่วนโปรโตคอลอาจเป็นตัวเลือกเช่น:

function isValidURL(str) {
    var pattern = new RegExp('^((https?:)?\\/\\/)?'+ // protocol
        '(?:\\S+(?::\\S*)?@)?' + // authentication
        '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
        '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
        '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
        '(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
        '(\\#[-a-z\\d_]*)?$','i'); // fragment locater
    if (!pattern.test(str)) {
        return false;
    } else {
        return true;
    }
}

ดังที่คนอื่น ๆ ระบุไว้การแสดงออกปกติดูเหมือนจะไม่ใช่วิธีที่เหมาะสมที่สุดสำหรับการตรวจสอบความถูกต้องของ URL


ฉันคิดว่าในตอนแรกมันค่อนข้างดี แต่มันล้มเหลวในการทดสอบจำนวนมากที่mathiasbynens.be/demo/url-regexจากนั้นมันก็หยุดทำงานisValidURL("https://d1f4470da51b49289906b3d6cbd65074@app.getsentry.com/13176")
aamarks

ใช่อย่างที่ฉันพูดฉันแค่แสดงความคิดเห็นในส่วนของโปรโตคอล @ฉันจะเพิ่มข้อรับรองความถูกต้องในการจัดการ มันไม่ได้แขวนในของฉันเบราว์เซอร์
ko la

ขออภัยฉันต้องผ่านหลายสิ่งเหล่านี้เพื่อประเมินพวกเขาและพลาดว่าคุณแสดงความคิดเห็นกับคำตอบที่ระบุ ฉันคิดว่าการแก้ไขของคุณช่วยให้ฉันเริ่มต้นสิ่งเหล่านี้ได้เมื่อฉันเข้าชมหน้านี้เป็นครั้งแรก ไม่ได้แขวนตอนนี้
aamarks

9

คุณสามารถใช้API เนทีฟของURL :

  const isUrl = string => {
      try { return Boolean(new URL(string)); }
      catch(e){ return false; }
  }

3
ดูเหมือนว่าจะคล้ายกับคำตอบที่ @pavlo มีเพียงชื่อตัวแปรที่เปลี่ยนไปเท่านั้น)
Munim Munna

2
ควรจะมีวิธีการเนทีฟแบบง่าย ๆ เพื่อตรวจสอบสิ่งนี้ในตอนนี้ - คำตอบนี้ดูมีแนวโน้มมาก แต่จะให้ผลตอบแทนเร็วกว่าที่ @Basj กล่าวถึงข้างต้น
zero_cool

8

ดังที่ได้กล่าวไว้แล้วว่า regex ที่สมบูรณ์นั้นเข้าใจยาก แต่ก็ดูเหมือนจะเป็นวิธีที่เหมาะสม (ทางเลือกคือการทดสอบฝั่งเซิร์ฟเวอร์หรือURLการทดลองAPI ใหม่ ) แต่คำตอบที่ระดับสูงมักจะกลับเท็จสำหรับ URL ที่พบบ่อย แต่ยิ่งเลวร้ายลงจะหยุด app / isURL('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')หน้าของคุณสำหรับนาทีแม้ในขณะที่เรียบง่ายเป็นสตริง มีการชี้ให้เห็นในความคิดเห็นบางส่วน แต่ส่วนใหญ่อาจยังไม่ได้ใส่ค่าที่ไม่ดีเพื่อดู การแขวนเช่นนั้นทำให้โค้ดนั้นใช้ไม่ได้ในแอปพลิเคชันที่ร้ายแรง ((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|' ...ฉันคิดว่ามันจะเกิดจากกรณีซ้ำชุดตายในรหัสเช่น นำ 'i' ออกมาและมันก็ไม่หยุด แต่แน่นอนว่าจะไม่ทำงานตามที่ต้องการ แต่ถึงแม้จะมีการตั้งค่ากรณีเพิกเฉยการทดสอบเหล่านั้นก็ปฏิเสธค่ายูนิโค้ดสูงที่ได้รับอนุญาต

สิ่งที่ดีที่สุดที่กล่าวมาแล้วคือ:

function isURL(str) {
  return /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/.test(str); 
}

ที่มาจาก Github segmentio / IS-URL สิ่งที่ดีเกี่ยวกับที่เก็บรหัสคือคุณสามารถดูการทดสอบและปัญหาใด ๆ และสตริงการทดสอบที่เรียกใช้ผ่านมัน มีสาขาที่อนุญาตให้ใช้โปรโตคอลที่หายไปเช่นgoogle.comแม้ว่าคุณอาจจะทำข้อสันนิษฐานมากเกินไป พื้นที่เก็บข้อมูลได้รับการปรับปรุงและฉันไม่ได้วางแผนที่จะติดตามมิเรอร์ที่นี่ มันถูกแบ่งออกเป็นการทดสอบที่แยกต่างหากเพื่อหลีกเลี่ยงการ RegEx redosซึ่งสามารถใช้ประโยชน์เพื่อการโจมตี DoS (ผมไม่คิดว่าคุณต้องกังวลเกี่ยวกับ js ฝั่งไคลเอ็นต์ แต่คุณไม่ต้องกังวลเกี่ยวกับที่แขวนอยู่หน้าเว็บของคุณมานานแล้วว่าของคุณ ผู้เยี่ยมชมออกจากไซต์ของคุณ)

มีอีกหนึ่งที่เก็บข้อมูลที่ฉันเคยเห็นว่าอาจดีกว่าสำหรับ isURL ที่dperini / regex-weburl.jsแต่มันซับซ้อนมาก มีรายการทดสอบ URL ที่ถูกต้องและไม่ถูกต้องมากขึ้น วิอย่างง่ายข้างบนยังคงผ่านการบวกทั้งหมดและล้มเหลวในการบล็อกเชิงลบคี่เช่นhttp://a.b--c.de/เช่นเดียวกับไอพีพิเศษ

ไม่ว่าคุณจะเลือกแบบไหนให้เรียกใช้ผ่านฟังก์ชั่นนี้ซึ่งฉันได้ดัดแปลงจากการทดสอบบน dperini / regex-weburl.js ในขณะที่ใช้เครื่องมือพัฒนาเครื่องมือสำหรับนักพัฒนาของเบราว์เซอร์

function testIsURL() {
//should match
console.assert(isURL("http://foo.com/blah_blah"));
console.assert(isURL("http://foo.com/blah_blah/"));
console.assert(isURL("http://foo.com/blah_blah_(wikipedia)"));
console.assert(isURL("http://foo.com/blah_blah_(wikipedia)_(again)"));
console.assert(isURL("http://www.example.com/wpstyle/?p=364"));
console.assert(isURL("https://www.example.com/foo/?bar=baz&inga=42&quux"));
console.assert(isURL("http://✪df.ws/123"));
console.assert(isURL("http://userid:password@example.com:8080"));
console.assert(isURL("http://userid:password@example.com:8080/"));
console.assert(isURL("http://userid@example.com"));
console.assert(isURL("http://userid@example.com/"));
console.assert(isURL("http://userid@example.com:8080"));
console.assert(isURL("http://userid@example.com:8080/"));
console.assert(isURL("http://userid:password@example.com"));
console.assert(isURL("http://userid:password@example.com/"));
console.assert(isURL("http://142.42.1.1/"));
console.assert(isURL("http://142.42.1.1:8080/"));
console.assert(isURL("http://➡.ws/䨹"));
console.assert(isURL("http://⌘.ws"));
console.assert(isURL("http://⌘.ws/"));
console.assert(isURL("http://foo.com/blah_(wikipedia)#cite-1"));
console.assert(isURL("http://foo.com/blah_(wikipedia)_blah#cite-1"));
console.assert(isURL("http://foo.com/unicode_(✪)_in_parens"));
console.assert(isURL("http://foo.com/(something)?after=parens"));
console.assert(isURL("http://☺.damowmow.com/"));
console.assert(isURL("http://code.google.com/events/#&product=browser"));
console.assert(isURL("http://j.mp"));
console.assert(isURL("ftp://foo.bar/baz"));
console.assert(isURL("http://foo.bar/?q=Test%20URL-encoded%20stuff"));
console.assert(isURL("http://مثال.إختبار"));
console.assert(isURL("http://例子.测试"));
console.assert(isURL("http://उदाहरण.परीक्षा"));
console.assert(isURL("http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com"));
console.assert(isURL("http://1337.net"));
console.assert(isURL("http://a.b-c.de"));
console.assert(isURL("http://223.255.255.254"));
console.assert(isURL("postgres://u:p@example.com:5702/db"));
console.assert(isURL("https://d1f4470da51b49289906b3d6cbd65074@app.getsentry.com/13176"));

//SHOULD NOT MATCH:
console.assert(!isURL("http://"));
console.assert(!isURL("http://."));
console.assert(!isURL("http://.."));
console.assert(!isURL("http://../"));
console.assert(!isURL("http://?"));
console.assert(!isURL("http://??"));
console.assert(!isURL("http://??/"));
console.assert(!isURL("http://#"));
console.assert(!isURL("http://##"));
console.assert(!isURL("http://##/"));
console.assert(!isURL("http://foo.bar?q=Spaces should be encoded"));
console.assert(!isURL("//"));
console.assert(!isURL("//a"));
console.assert(!isURL("///a"));
console.assert(!isURL("///"));
console.assert(!isURL("http:///a"));
console.assert(!isURL("foo.com"));
console.assert(!isURL("rdar://1234"));
console.assert(!isURL("h://test"));
console.assert(!isURL("http:// shouldfail.com"));
console.assert(!isURL(":// should fail"));
console.assert(!isURL("http://foo.bar/foo(bar)baz quux"));
console.assert(!isURL("ftps://foo.bar/"));
console.assert(!isURL("http://-error-.invalid/"));
console.assert(!isURL("http://a.b--c.de/"));
console.assert(!isURL("http://-a.b.co"));
console.assert(!isURL("http://a.b-.co"));
console.assert(!isURL("http://0.0.0.0"));
console.assert(!isURL("http://10.1.1.0"));
console.assert(!isURL("http://10.1.1.255"));
console.assert(!isURL("http://224.1.1.1"));
console.assert(!isURL("http://1.1.1.1.1"));
console.assert(!isURL("http://123.123.123"));
console.assert(!isURL("http://3628126748"));
console.assert(!isURL("http://.www.foo.bar/"));
console.assert(!isURL("http://www.foo.bar./"));
console.assert(!isURL("http://.www.foo.bar./"));
console.assert(!isURL("http://10.1.1.1"));}

จากนั้นทดสอบสตริงของ 'a's

ดูการเปรียบเทียบ isURL regexโดย Mathias Bynens สำหรับข้อมูลเพิ่มเติมก่อนที่คุณจะโพสต์ regex ที่ดีมาก


ฉันตรวจสอบคำตอบของคุณ คำตอบของคุณล้มเหลวในการใช้sdfasdp.pppppppppppนั่นคือการคืนค่าจริง แต่คาดว่าเป็นเท็จ
Vikasdeep Singh

1
ฉันคิดว่านั่นเป็น URL ที่ถูกต้องซึ่งมีโครงสร้าง ไม่ใช่ผู้เชี่ยวชาญเกี่ยวกับมาตรฐาน แต่ฉันไม่คิดว่าจะมีข้อ จำกัด เกี่ยวกับความยาวของส่วน. com (ฉันรู้ว่า. ออนไลน์เป็นเรื่องถูกต้อง)
aamarks

1
ฉันเพิ่งรู้วิธีการเขียน regex สองสามเดือนที่ผ่านมา ปัญหารุนแรง regex ทั้งสองที่ฉันยกมาสามารถทำได้isURL('a'.repeat(100))หลายล้านครั้ง / วินาที (ยิ่งซับซ้อนยิ่งขึ้นจาก dperini เร็วขึ้นจริง) คำตอบที่อยู่ในระดับสูงของแบบฟอร์ม ([a-zA-Z] +) * อาจใช้เวลาหลายชั่วโมงกว่าจะเสร็จสมบูรณ์ในครั้งเดียว ค้นหา RegEx redos สำหรับข้อมูลเพิ่มเติม
aamarks

6

ฉันไม่สามารถแสดงความคิดเห็นในโพสต์ที่ใกล้เคียงที่สุด# 5717133แต่ด้านล่างเป็นวิธีที่ฉันคิดวิธีที่จะทำให้ @ tom-gullen regex ทำงาน

/^(https?:\/\/)?((([a-z\d]([a-z\d-]*[a-z\d])*)\.)+[a-z]{2,}|((\d{1,3}\.){3}\d{1,3}))(\:\d+)?(\/[-a-z\d%_.~+]*)*(\?[;&a-z\d%_.~+=-]*)?(\#[-a-z\d_]*)?$/i

2
สิ่งนี้ใช้ได้สำหรับฉัน แต่ฉันต้องการแบ็กสแลชแบ็กสแลช var pattern = new RegExp('(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$', 'i');
Fernando Chavez Herrera

ตรวจสอบw3resource.com/javascript-exercises/…สำหรับกรณีทดสอบเพิ่มเติม
Kewal Shah

5

ใช้validator.js

ES6

import isURL from 'validator/lib/isURL'

isURL(string)

ไม่มี ES6

var validator = require('validator');

validator.isURL(string)

นอกจากนี้คุณยังสามารถปรับพฤติกรรมของฟังก์ชั่นนี้ได้อย่างละเอียดโดยส่งoptionsวัตถุเสริมเป็นอาร์กิวเมนต์ที่สองของisURL

นี่คือoptionsวัตถุเริ่มต้น:

let options = {
    protocols: [
        'http',
        'https',
        'ftp'
    ],
    require_tld: true,
    require_protocol: false,
    require_host: true,
    require_valid_protocol: true,
    allow_underscores: false,
    host_whitelist: false,
    host_blacklist: false,
    allow_trailing_dot: false,
    allow_protocol_relative_urls: false,
    disallow_auth: false
}

isURL(string, options)

host_whitelistและhost_blacklistสามารถเป็นอาร์เรย์ของโฮสต์ได้ พวกเขายังสนับสนุนการแสดงออกปกติ

let options = {
    host_blacklist: ['foo.com', 'bar.com'],
}

isURL('http://foobar.com', options) // => true
isURL('http://foo.bar.com/', options) // => true
isURL('http://qux.com', options) // => true

isURL('http://bar.com/', options) // => false
isURL('http://foo.com/', options) // => false


options = {
    host_blacklist: ['bar.com', 'foo.com', /\.foo\.com$/],
}

isURL('http://foobar.com', options) // => true
isURL('http://foo.bar.com/', options) // => true
isURL('http://qux.com', options) // => true

isURL('http://bar.com/', options) // => false
isURL('http://foo.com/', options) // => false
isURL('http://images.foo.com/', options) // => false
isURL('http://cdn.foo.com/', options) // => false
isURL('http://a.b.c.foo.com/', options) // => false

1
ดี! ไลบรารี่ขนาดเล็ก (น้อยกว่า 40k ลดขนาด), ไลบรารี่ยอดนิยม (ดาวน์โหลดมากกว่า 3 สัปดาห์ต่อสัปดาห์ที่ npm) ช่วยให้คุณมีความยืดหยุ่นในการระบุความถูกต้องของ URL สำหรับกรณีการใช้งานเฉพาะของคุณและมีเครื่องมือตรวจสอบอื่น ๆ นี่คือคำตอบที่ดีที่สุด IMHO
Javid Jamae

4

ฟังก์ชันหนึ่งที่ฉันใช้เพื่อตรวจสอบความถูกต้องของ "สตริง" คือ:

var matcher = /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/;

function isUrl(string){
  return matcher.test(string);
}

ฟังก์ชันนี้จะคืนค่าบูลีนว่าเป็นสตริงหรือไม่

ตัวอย่าง:

isUrl("https://google.com");     // true
isUrl("http://google.com");      // true
isUrl("http://google.de");       // true
isUrl("//google.de");            // true
isUrl("google.de");              // false
isUrl("http://google.com");      // true
isUrl("http://localhost");       // true
isUrl("https://sdfasd");         // false

4

นี่เป็นเรื่องยากที่จะทำกับ regex แท้เพราะ URL มี 'ความไม่สะดวก "มากมาย

  1. ตัวอย่างเช่นชื่อโดเมนมีข้อ จำกัด ที่ซับซ้อนในยัติภังค์:

    มันได้รับอนุญาตให้มียัติภังค์ต่อเนื่องหลายตัวอยู่ตรงกลาง

    ข แต่อักขระตัวแรกและอักขระตัวสุดท้ายของชื่อโดเมนจะต้องไม่ใช่เครื่องหมายขีดคั่น

    ค. อักขระที่ 3 และ 4 ไม่สามารถเป็นทั้งเครื่องหมายขีดคั่น

  2. หมายเลขพอร์ตในทำนองเดียวกันสามารถอยู่ในช่วง 1-65535 เท่านั้น นี่เป็นการตรวจสอบที่ง่ายถ้าคุณแยกส่วนพอร์ตและแปลงเป็นintแต่ค่อนข้างยากที่จะตรวจสอบด้วยนิพจน์ทั่วไป

  3. นอกจากนี้ยังไม่มีวิธีง่ายๆในการตรวจสอบส่วนขยายโดเมนที่ถูกต้อง บางประเทศมีโดเมนระดับที่สอง (เช่น 'co.uk') หรือส่วนขยายอาจเป็นคำที่ยาวเช่น '.International' และ TLD ใหม่จะถูกเพิ่มอย่างสม่ำเสมอ สิ่งต่าง ๆ ประเภทนี้สามารถตรวจสอบได้กับรายการที่มีการกำหนดรหัสตายตัวเท่านั้น (ดูhttps://en.wikipedia.org/wiki/Top-level_domain )

  4. จากนั้นก็มี URL ของแม่เหล็ก, ที่อยู่ ftp และอื่น ๆ ทั้งหมดนี้มีข้อกำหนดที่แตกต่างกัน

อย่างไรก็ตามนี่คือฟังก์ชั่นที่จัดการทุกอย่างได้ค่อนข้างดียกเว้น:

  • กรณีที่ 1. ค
  • ยอมรับหมายเลขพอร์ตใด ๆ 1-5 หลัก
  • ยอมรับส่วนขยายใด ๆ 2-13 ตัวอักษร
  • ไม่ยอมรับ ftp, แม่เหล็ก ฯลฯ ...

function isValidURL(input) {
    pattern = '^(https?:\\/\\/)?' + // protocol
        '((([a-zA-Z\\d]([a-zA-Z\\d-]{0,61}[a-zA-Z\\d])*\\.)+' + // sub-domain + domain name
        '[a-zA-Z]{2,13})' + // extension
        '|((\\d{1,3}\\.){3}\\d{1,3})' + // OR ip (v4) address
        '|localhost)' + // OR localhost
        '(\\:\\d{1,5})?' + // port
        '(\\/[a-zA-Z\\&\\d%_.~+-:@]*)*' + // path
        '(\\?[a-zA-Z\\&\\d%_.,~+-:@=;&]*)?' + // query string
        '(\\#[-a-zA-Z&\\d_]*)?$'; // fragment locator
    regex = new RegExp(pattern);
    return regex.test(input);
}

let tests = [];
tests.push(['', false]);
tests.push(['http://en.wikipedia.org/wiki/Procter_&_Gamble', true]);
tests.push(['https://sdfasd', false]);
tests.push(['http://www.google.com/url?sa=i&rct=j&q=&esrc=s&source=images&cd=&docid=nIv5rk2GyP3hXM&tbnid=isiOkMe3nCtexM:&ved=0CAUQjRw&url=http%3A%2F%2Fanimalcrossing.wikia.com%2Fwiki%2FLion&ei=ygZXU_2fGKbMsQTf4YLgAQ&bvm=bv.65177938,d.aWc&psig=AFQjCNEpBfKnal9kU7Zu4n7RnEt2nerN4g&ust=1398298682009707', true]);
tests.push(['https://stackoverflow.com/', true]);
tests.push(['https://w', false]);
tests.push(['aaa', false]);
tests.push(['aaaa', false]);
tests.push(['oh.my', true]);
tests.push(['dfdsfdsfdfdsfsdfs', false]);
tests.push(['google.co.uk', true]);
tests.push(['test-domain.MUSEUM', true]);
tests.push(['-hyphen-start.gov.tr', false]);
tests.push(['hyphen-end-.com', false]);
tests.push(['https://sdfasdp.international', true]);
tests.push(['https://sdfasdp.pppppppp', false]);
tests.push(['https://sdfasdp.ppppppppppppppppppp', false]);
tests.push(['https://sdfasd', false]);
tests.push(['https://sub1.1234.sub3.sub4.sub5.co.uk/?', true]);
tests.push(['http://www.google-com.123', false]);
tests.push(['http://my--testdomain.com', false]);
tests.push(['http://my2nd--testdomain.com', true]);
tests.push(['http://thingiverse.com/download:1894343', true]);
tests.push(['https://medium.com/@techytimo', true]);
tests.push(['http://localhost', true]);
tests.push(['localhost', true]);
tests.push(['localhost:8080', true]);
tests.push(['localhost:65536', true]);
tests.push(['localhost:80000', false]);
tests.push(['magnet:?xt=urn:btih:123', true]);

for (let i = 0; i < tests.length; i++) {
    console.log('Test #' + i + (isValidURL(tests[i][0]) == tests[i][1] ? ' passed' : ' failed') + ' on ["' + tests[i][0] + '", ' + tests[i][1] + ']');
}


1

ฉันคิดว่าการใช้ Native API APIนั้นดีกว่ารูปแบบ regex ที่ซับซ้อนตามที่ @pavlo แนะนำ มันมีข้อบกพร่องบางอย่างซึ่งเราสามารถแก้ไขได้ด้วยรหัสพิเศษบางอย่าง วิธีนี้ล้มเหลวสำหรับ URL ที่ถูกต้องต่อไปนี้

//cdn.google.com/script.js

เราสามารถเพิ่มโปรโตคอลที่หายไปล่วงหน้าเพื่อหลีกเลี่ยง นอกจากนี้ยังตรวจไม่พบ URL ที่ไม่ถูกต้องดังต่อไปนี้

http://w
http://..

เหตุใดจึงต้องตรวจสอบ URL ทั้งหมด เราสามารถตรวจสอบโดเมนได้ ผมยืม regex เพื่อตรวจสอบโดเมนจากที่นี่

function isValidUrl(string) {
    if (string && string.length > 1 && string.slice(0, 2) == '//') {
        string = 'http:' + string; //dummy protocol so that URL works
    }
    try {
        var url = new URL(string);
        return url.hostname && url.hostname.match(/^([a-z0-9])(([a-z0-9-]{1,61})?[a-z0-9]{1})?(\.[a-z0-9](([a-z0-9-]{1,61})?[a-z0-9]{1})?)?(\.[a-zA-Z]{2,4})+$/) ? true : false;
    } catch (_) {
        return false;
    }
}

hostnameแอตทริบิวต์เป็นสตริงที่ว่างเปล่าสำหรับjavascript:void(0)เพื่อการทำงานที่มากเกินไปและคุณยังสามารถเพิ่มที่อยู่ IP ตรวจสอบมากเกินไป ฉันต้องการยึดติดกับ API ดั้งเดิมที่สุดและหวังว่าจะเริ่มให้การสนับสนุนทุกอย่างในอนาคตอันใกล้


ที่น่าสนใจ แต่อาจยังต้องทำงานกับ regex เพราะตอนนี้มันเปิดตัวเชิงลบเท็จซึ่งnew URLไม่ได้มีในการทดสอบที่ฉันได้ทำ นี่คือการโทร: http://142.42.1.1 //falseและการบล็อกสตริงยูนิโค้ดสูง
aamarks

1

คำถามจะถามวิธีการตรวจสอบความถูกต้องสำหรับ URL เช่นstackoverflowโดยไม่มีโปรโตคอลหรือจุดใด ๆ ในชื่อโฮสต์ ดังนั้นจึงไม่เป็นเรื่องของการตรวจสอบความถูกต้องของ URL sintax แต่การตรวจสอบว่ามันเป็น URL ที่ถูกต้องโดยการเรียกมันจริง

ฉันพยายามหลายวิธีในการรู้ว่า url จริงนั้นมีอยู่และสามารถเรียกใช้ได้จากภายในเบราว์เซอร์ แต่ไม่พบวิธีทดสอบกับ javascript ในส่วนหัวการตอบสนองของการโทร:

  • การเพิ่มองค์ประกอบสมอเป็นเรื่องปกติสำหรับการยิงclick()วิธี
  • การโทร ajax ไปยัง url ที่ท้าทายด้วย'GET'นั้นใช้ได้ แต่มีข้อ จำกัด มากมายเนื่องจากCORSนโยบายและไม่ใช่กรณีของการใช้ajaxเพราะ url อาจอยู่นอกโดเมนเซิร์ฟเวอร์ของฉัน
  • การใช้fetch APIมีวิธีแก้ปัญหาคล้ายกับ ajax
  • ปัญหาอื่น ๆ คือฉันมีเซิร์ฟเวอร์ของฉันภายใต้httpsโปรโตคอลและส่งข้อยกเว้นเมื่อเรียก url ที่ไม่ปลอดภัย

ดังนั้นทางออกที่ดีที่สุดที่ฉันสามารถคิดจะได้รับเครื่องมือบางอย่างที่จะดำเนินการCURLโดยใช้ javascript curl -I <url>พยายามบางอย่างเช่น น่าเสียดายที่ฉันไม่พบสิ่งใดและในสิ่งที่เป็นไปไม่ได้ ฉันจะขอบคุณความคิดเห็นใด ๆ เกี่ยวกับเรื่องนี้

แต่ในที่สุดฉันก็มีเซิร์ฟเวอร์ที่ทำงานอยู่PHPและเมื่อฉันใช้ Ajax สำหรับคำขอเกือบทั้งหมดของฉันฉันได้เขียนฟังก์ชั่นทางฝั่งเซิร์ฟเวอร์เพื่อดำเนินการตามคำขอ curl ที่นั่นและกลับไปที่เบราว์เซอร์

เกี่ยวกับ url คำเดี่ยวในคำถาม 'stackoverflow' มันจะนำฉันไปสู่https://daniserver.com.ar/stackoverflowที่ daniserver.com.ar เป็นโดเมนของฉันเอง


OP น่าจะบ่งบอกถึงเจตนาของเขาได้มากกว่านี้ ปัญหาแตกต่างกันไปตามความต้องการของคุณอย่างแน่นอนและไม่ว่าจะเป็นสิ่งสำคัญที่จะแยกบวกเท็จหรือรวมเชิงลบเท็จ ตามที่ระบุปัญหาดูเหมือนว่าจะไม่มีคำตอบสำหรับฉัน คุณสามารถรับfooและสมมติว่าเป็น http หรือ https หรือ. com หรือ. es หรือส่วนต่อท้ายใด ๆ นับไม่ถ้วนได้หรือไม่? คุณทิ้งอ่างล้างจานไว้เรื่อย ๆ จนกว่าคุณจะได้รับจริงหรือไม่?
aamarks

1

นี่เป็นหนึ่งในปัญหาที่ยากที่สุดใน CS;)

นี่เป็นอีกวิธีที่ไม่สมบูรณ์ที่ทำงานได้ดีพอสำหรับฉันและดีกว่าโซลูชันอื่น ๆ ที่ฉันเคยเห็นที่นี่ ฉันใช้อินพุต [type = url] สำหรับสิ่งนี้เพื่อรองรับ IE11 มิฉะนั้นจะง่ายกว่าการใช้ window.URL เพื่อทำการตรวจสอบแทน:

const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
function isValidIpv4(ip) {
  if (!ipv4Regex.test(ip)) return false;
  return !ip.split('.').find(n => n > 255);
}

const domainRegex = /(?:[a-z0-9-]{1,63}\.){1,125}[a-z]{2,63}$/i;
function isValidDomain(domain) {
  return isValidIpv4(domain) || domainRegex.test(domain);
}

let input;
function validateUrl(url) {
  if (! /^https?:\/\//.test(url)) url = `http://${url}`; // assuming Babel is used
  // to support IE11 we'll resort to input[type=url] instead of window.URL:
  // try { return isValidDomain(new URL(url).host) && url; } catch(e) { return false; }
  if (!input) { input = document.createElement('input'); input.type = 'url'; }
  input.value = url;
  if (! input.validity.valid) return false;
  const domain = url.split(/^https?:\/\//)[1].split('/')[0].split('@').pop();
  return isValidDomain(domain) && url;
}

console.log(validateUrl('google'), // false
  validateUrl('user:pw@mydomain.com'),
  validateUrl('https://google.com'),
  validateUrl('100.100.100.100/abc'),
  validateUrl('100.100.100.256/abc')); // false

เพื่อที่จะยอมรับอินพุตที่ไม่สมบูรณ์เช่น "www.mydomain.com" มันจะทำให้ถูกต้องโดยสมมติว่าโปรโตคอลคือ "http" ในกรณีเหล่านั้นและส่งคืน URL ที่ถูกต้องหากที่อยู่นั้นถูกต้อง มันจะส่งกลับเท็จเมื่อไม่ถูกต้อง

นอกจากนี้ยังรองรับโดเมน IPv4 แต่ไม่รองรับ IPv6


1

ในกรณีของฉันความต้องการเฉพาะของฉันคือการป้อนข้อมูลผู้ใช้จะไม่ถูกตีความว่าเป็นลิงค์ญาติเมื่อวางไว้ใน href ของแท็กและคำตอบที่นี่เป็นบิต OTT สำหรับที่หรือ URL ที่ได้รับอนุญาตไม่ตรงกับความต้องการของฉันดังนั้น คือสิ่งที่ฉันจะไปด้วย:

^https?://.+$

สิ่งเดียวกันสามารถทำได้ค่อนข้างง่ายโดยไม่ต้อง regex


1

การทำงานกับฉันนี้

function isURL(str) {
  var regex = /(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/;
  var pattern = new RegExp(regex); 
return pattern.test(str);
}

1
คำตอบนี้ได้รับเมื่อ 4 ปีที่แล้วโดย kavitha Reddy
aamarks

ฉันทำให้มันง่ายขึ้นและเป็นนามธรรมมากขึ้น
HeshamSalama

1

หากคุณสามารถเปลี่ยนประเภทอินพุตฉันคิดว่าวิธีนี้จะง่ายกว่านี้มาก:

คุณสามารถใช้งานง่ายtype="url"ในการป้อนข้อมูลของคุณและตรวจสอบด้วยcheckValidity()ใน js

เช่น:

your.html

<input id="foo" type="url">

your.js

// The selector is JQuery, but the function is plain JS
$("#foo").on("keyup", function() {
    if (this.checkValidity()) {
        // The url is valid
    } else {
        // The url is invalid
    }
});

1

วิธีนี้ไม่ใช่วิธีที่มีประสิทธิภาพมากที่สุด แต่สามารถอ่านได้และง่ายต่อการจัดรูปแบบตามที่คุณต้องการ และง่ายต่อการเพิ่ม regex / ความซับซ้อนจากที่นี่ ดังนั้นนี่คือวิธีการปฏิบัติอย่างมาก

const validFirstBits = ["ftp://", "http://", "https://", "www."];
const invalidPatterns = [" ", "//.", ".."];

export function isUrl(word) {
// less than www.1.dk
if (!word || word.length < 8) return false;

// Let's check and see, if our candidate starts with some of our valid first bits
const firstBitIsValid = validFirstBits.some(bit => word.indexOf(bit) === 0);
if (!firstBitIsValid) return false;

const hasInvalidPatterns = invalidPatterns.some(
    pattern => word.indexOf(pattern) !== -1,
);

if (hasInvalidPatterns) return false;

const dotSplit = word.split(".");
if (dotSplit.length > 1) {
    const lastBit = dotSplit.pop(); // string or undefined
    if (!lastBit) return false;
    const length = lastBit.length;
    const lastBitIsValid =
        length > 1 || (length === 1 && !isNaN(parseInt(lastBit)));
    return !!lastBitIsValid;
}

    return false;
}

ทดสอบ:

import { isUrl } from "./foo";

describe("Foo", () => {
    test("should validate correct urls correctly", function() {
        const validUrls = [
            "http://example.com",
            "http://example.com/blah",
            "http://127.0.0.1",
            "http://127.0.0.1/wow",
            "https://example.com",
            "https://example.com/blah",
            "https://127.0.0.1:1234",
            "ftp://example.com",
            "ftp://example.com/blah",
            "ftp://127.0.0.1",
            "www.example.com",
            "www.example.com/blah",
        ];

        validUrls.forEach(url => {
            expect(isUrl(url) && url).toEqual(url);
        });
    });

    test("should validate invalid urls correctly", function() {
        const inValidUrls = [
            "http:// foo.com",
            "http:/foo.com",
            "http://.foo.com",
            "http://foo..com",
            "http://.com",
            "http://foo",
            "http://foo.c",
        ];

        inValidUrls.forEach(url => {
            expect(!isUrl(url) && url).toEqual(url);
        });
    });
});

1

Mathias Bynens ได้รวบรวมรายการregexes URL ที่รู้จักกันดีกับ URL ทดสอบ มีเหตุผลเล็กน้อยที่จะเขียนนิพจน์ทั่วไปใหม่ เพียงเลือกอันที่มีอยู่แล้วที่เหมาะกับคุณที่สุด

แต่ตารางเปรียบเทียบสำหรับ regexes เหล่านั้นยังแสดงให้เห็นว่าเป็นไปไม่ได้ที่จะทำการตรวจสอบความถูกต้องของ URL ด้วยนิพจน์ทั่วไปเดียว regexes ทั้งหมดในรายการ Bynens 'สร้างผลบวกปลอมและเชิงลบเท็จ

ฉันขอแนะนำให้คุณใช้ตัวแยกวิเคราะห์ URL ที่มีอยู่ (ตัวอย่างเช่นnew URL('http://www.example.com/')ใน JavaScript) จากนั้นใช้การตรวจสอบที่คุณต้องการดำเนินการกับรูปแบบการแยกวิเคราะห์และการทำให้ URL เป็นมาตรฐาน ส่วนประกอบของมัน การใช้URLส่วนต่อประสานJavaScript มีประโยชน์เพิ่มเติมที่จะยอมรับเฉพาะ URL ที่ได้รับการยอมรับจากเบราว์เซอร์เท่านั้น

คุณควรจำไว้ว่า URL ที่ไม่ถูกต้องทางเทคนิคอาจยังใช้งานได้ ตัวอย่างเช่นhttp://w_w_w.example.com/, http://www..example.com/, http://123.example.com/ทุกคนมีส่วนชื่อโฮสต์ที่ไม่ถูกต้อง แต่เบราว์เซอร์ฉันรู้ว่าทุกคนจะพยายามที่จะเปิดได้โดยไม่ต้องร้องเรียนและเมื่อคุณระบุที่อยู่ IP สำหรับชื่อที่ไม่ถูกต้องผู้ที่อยู่ใน/etc/hosts/ URL ที่ดังกล่าวแม้จะทำงาน แต่เฉพาะบนคอมพิวเตอร์ของคุณ

ดังนั้นคำถามคือไม่มากว่า URL นั้นถูกต้อง แต่เป็น URL ที่ทำงานได้และควรได้รับอนุญาตในบริบทเฉพาะ

หากคุณต้องการตรวจสอบความถูกต้องของ URL มีรายละเอียดมากมายและตัวพิมพ์ขอบที่มองข้ามได้ง่าย:

  • URL อาจมีข้อมูลรับรองเช่นเดียวกับใน http://user:password@www.example.com/ที่อาจมีข้อมูลประจำตัวเช่นเดียวกับใน
  • หมายเลขพอร์ตจะต้องอยู่ในช่วง 0-65535 แต่คุณอาจต้องการยกเว้น wildcard พอร์ต 0
  • หมายเลขพอร์ตอาจมีเลขศูนย์นำหน้าเช่นเดียวกับในhttp://www.example.com:000080/ http://www.example.com:000080/
  • ที่อยู่ IPv4 นั้นไม่ได้ จำกัด อยู่แค่จำนวนเต็ม 4 ทศนิยมในช่วง 0-255 คุณสามารถใช้จำนวนเต็มหนึ่งถึงสี่และพวกเขาสามารถเป็นทศนิยมฐานแปดหรือฐานสิบหก URL https: //010.010.000010.010/ , https: //0x8.0x8.0x0008.0x8/ , https: //8.8.2056/ , https: //8.526344/ , https: // 134744072 /ทั้งหมดถูกต้องและ เพียงแค่วิธีที่สร้างสรรค์ในการเขียนhttps://8.8.8.8/
  • การอนุญาตที่อยู่ลูปแบ็ค ( http://127.0.0.1/ ), ที่อยู่ IP ส่วนตัว ( http://192.168.1.1 ), ที่อยู่ link-local ( http://169.254.100.200 ) และอื่น ๆ อาจมีผลกระทบต่อความปลอดภัยหรือ ความเป็นส่วนตัว ตัวอย่างเช่นหากคุณอนุญาตให้พวกเขาเป็นที่อยู่ของรูปประจำตัวของผู้ใช้ในฟอรัมคุณจะทำให้เบราว์เซอร์ของผู้ใช้ส่งคำขอเครือข่ายที่ไม่พึงประสงค์ในเครือข่ายท้องถิ่นของพวกเขาและในอินเทอร์เน็ต เกิดขึ้นในบ้านของคุณ
  • ด้วยเหตุผลเดียวกันคุณอาจต้องการยกเลิกการเชื่อมโยงไปยังชื่อโฮสต์ที่ไม่ผ่านการรับรองโดยสมบูรณ์ในคำอื่น ๆ ชื่อโฮสต์ที่ไม่มีจุด
  • แต่ชื่อโฮสต์อาจมีจุดต่อท้าย (เหมือนในhttp://www.stackoverflow.com.) เสมอ
  • ส่วนชื่อโฮสต์ของลิงค์อาจมีวงเล็บมุมสำหรับที่อยู่ IPv6 ในhttp: // [:: 1]1]
  • ที่อยู่ IPv6 ยังมีช่วงสำหรับเครือข่ายส่วนตัวหรือที่อยู่การเชื่อมโยงท้องถิ่น ฯลฯ
  • หากคุณบล็อกที่อยู่ IPv4 บางที่โปรดจำไว้ว่าเช่นhttps://127.0.0.1และhttps: // [:: ffff: 127.0.0.1]ชี้ไปที่ทรัพยากรเดียวกัน (หากอุปกรณ์ลูปแบ็คของเครื่องของคุณพร้อมใช้งาน IPv6 )
  • ตอนนี้ส่วนชื่อโฮสต์ของ URL อาจมี Unicode ดังนั้นช่วงอักขระ[-0-9a-zA-z]จึงไม่เพียงพออีกต่อไป
  • การลงทะเบียนจำนวนมากสำหรับโดเมนระดับบนสุดจะกำหนดข้อ จำกัด เฉพาะตัวอย่างเช่นชุดอักขระ Unicode ที่อนุญาต หรือพวกเขาแบ่ง namespace ของพวกเขา (เช่นco.ukและอื่น ๆ อีกมากมาย)
  • โดเมนระดับบนสุดจะต้องไม่มีตัวเลขทศนิยมและไม่อนุญาตให้ใช้เครื่องหมายขีดกลางยกเว้นในส่วนนำหน้า IDN A-label "xn--"
  • โดเมนระดับบนสุดของ Unicode (และการเข้ารหัส punycode ด้วย "xn--") จะต้องมีตัวอักษรเพียงตัวเดียว แต่ใครที่ต้องการตรวจสอบใน regex?

ข้อ จำกัด และกฎใดที่ใช้เป็นคำถามของข้อกำหนดและรสนิยมของโครงการ

ฉันเพิ่งเขียนตัวตรวจสอบความถูกต้องของ URL สำหรับเว็บแอปที่เหมาะสำหรับ URL ที่ผู้ใช้ระบุในฟอรัมเครือข่ายสังคมหรือสิ่งที่คล้ายกัน รู้สึกอิสระที่จะใช้มันเป็นฐานสำหรับหนึ่งของคุณ:

ฉันได้เขียนโพสต์บล็อกThe Gory Details ของการตรวจสอบ URLด้วยข้อมูลเชิงลึกเพิ่มเติม


1

ฉันเปลี่ยนฟังก์ชั่นเพื่อจับคู่ + ทำการเปลี่ยนแปลงที่นี่ด้วยเครื่องหมายทับและการทำงาน: (http: // และ https) ทั้งคู่

function isValidUrl(userInput) {
    var res = userInput.match(/(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g);
    if(res == null)
       return false;
    else
       return true;
}

0

นี่เป็นเพียงการตรวจสอบที่ง่ายมากเพื่อให้แน่ใจว่ามีโปรโตคอลที่ถูกต้องและส่วนขยายโดเมนต้องมีอักขระอย่างน้อยสองตัว

is_valid_url = ( $url ) => {

    let $url_object = null;

    try {
        $url_object = new URL( $url );
    } catch ( $error ) {
        return false;
    }

    const $protocol = $url_object.protocol;
    const $protocol_position = $url.lastIndexOf( $protocol );
    const $domain_extension_position = $url.lastIndexOf( '.' );

    return (
        $protocol_position === 0 &&
        [ 'http:', 'https:' ].indexOf( $protocol ) !== - 1 &&
        $domain_extension_position > 2 && $url.length - $domain_extension_position > 2
    );

};

0

หากคุณต้องการการสนับสนุนให้https://localhost:3000ใช้ regex ของ [Devshed] รุ่นที่ปรับเปลี่ยนแล้ว

    function isURL(url) {
        if(!url) return false;
        var pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol
            '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
            '((\\d{1,3}\\.){3}\\d{1,3}))|' + // OR ip (v4) address
            'localhost' + // OR localhost
            '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
            '(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
            '(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator
        return pattern.test(url);
    }

0

มีการทดสอบสองสามอย่างโดยใช้ตัวสร้าง URL ซึ่งไม่ได้วิเคราะห์ว่าอินพุตเป็นสตริงหรือวัตถุ URL หรือไม่

// Testing whether something is a URL
function isURL(url) {
    return toString.call(url) === "[object URL]";
}

// Testing whether the input is both a string and valid url:
function isUrl(url) {
    try {
        return toString.call(url) === "[object String]" && !!(new URL(url));
    } catch (_) {
        return false;  
    }
}

0

2563 ปรับปรุง หากต้องการขยายทั้ง answerd ที่ยอดเยี่ยมจาก @iamnewton และ @Fernando Chavez Herrera ฉันเริ่มเห็น@การใช้งานในเส้นทางของ URL

ดังนั้น regex ที่อัปเดตคือ:

RegExp('(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+@]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$', 'i');

หากคุณต้องการอนุญาตในสตริงการสืบค้นและแฮชให้ใช้:

RegExp('(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+@]*)*(\\?[;&a-z\\d%_.~+=-@]*)?(\\#[-a-z\\d_@]*)?$', 'i');

ที่ถูกกล่าวว่าฉันไม่แน่ใจว่ามีกฎ whitepaper ไม่อนุญาต@ในสตริงแบบสอบถามหรือแฮช


0

มีคำตอบมากมายอยู่แล้ว แต่นี่เป็นอีกการสนับสนุน: ถ่ายโดยตรงจากการURLตรวจสอบความถูกต้องของ polyfill ใช้inputองค์ประกอบที่มีtype="url"เพื่อใช้ประโยชน์จากการตรวจสอบความถูกต้องภายในของเบราว์เซอร์:

var inputElement = doc.createElement('input');
inputElement.type = 'url';
inputElement.value = url;

if (!inputElement.checkValidity()) {
    throw new TypeError('Invalid URL');
}

แหล่ง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.