يقدم الصنف URL المدمج واجهةً ملائمةً لإنشاء عناوين الموارد وروابط URL وتفسيرها، لا تحتاج الطلبات عبر الشبكة إلى هذا الكائن بالتحديد، فالقيم النصية التي يمكن أن تعبّر عن العناوين كافية، وبالتالي لن نحتاج إليه تقنيًا، لكننا سنجد أن استخدامه مفيد في مناسبات عدة.
إنشاء رابط URL
إليك الصيغة البرمجية التي تُنشئ كائن URL
جديدًا:
new URL(url, [base])
-
url
: عنوان URL الكامل، أو جزء منه عند إسناد قيمة إلىbase
. -
base
: أساس اختياري للعنوان، فإذا أسندت قيمة لهذا الوسيط وكانت قيمة الوسيط الآخرurl
هي مسار فقط، فسيُولّد الكائن URL منسوبًا إلى القاعدةbase
.
إليك مثالًا:
let url = new URL('https://javascript.info/profile/admin');
لاحظ أن كائني URL
التاليين متطابقين تمامًا:
let url1 = new URL('https://javascript.info/profile/admin'); let url2 = new URL('/profile/admin', 'https://javascript.info'); alert(url1); // https://javascript.info/profile/admin alert(url2); // https://javascript.info/profile/admin
يمكن بالطبع إنشاء كائن URL
جديد مبني على مسار نسبي أساسه كائن URL
موجود مسبقًا:
let url = new URL('https://javascript.info/profile/admin'); let newUrl = new URL('tester', url); alert(newUrl); // https://javascript.info/profile/tester
نستطيع الوصول إلى مكوّنات الكائن URL
مباشرةً، وبالتالي سيقدم طريقةً أنيقةً لتفسير العناوين:
let url = new URL('https://javascript.info/url'); alert(url.protocol); // https: alert(url.host); // javascript.info alert(url.pathname); // /url
إليك لائحةً بمكوّنات URL
:
-
href
: ويعيد العنوان كاملًا، تمامًا كما يفعل التابع()url.toString
. -
protocol
: جزء من العنوان ينتهي بالنقطتين ":". -
search
: سلسلة نصية من المعاملات يبدأ بإشارة الاستفهام "؟". -
hash
: ويبدأ بالعلامة "#". -
كما يمكنك أن تجد الخاصيتين
user
وpassword
عند استخدام استيثاق HTTP، مثلhttp://login:password@site.com
، لكنه نادر الاستخدام.
اقتباسيمكن تمرير كائنات
URL
مثل وسيط إلى طلب عبر الشبكة، بدلًا من تمرير قيمة نصية. يمكن استخدام هذا الكائن معfetch
أوXMLHttpRequest
أو في أي مكان يوجد فيه عنوانURL
على شكل قيمة نصية، إذ تُجري معظم الطلبات عملية تحويل إلى نص، وبالتالي سيتحول الكائنURL
إلى نص يحمل عنوان URL كاملًا.
معامل البحث "?"
لنفترض أننا سننشئ عنوان url له معاملات بحث محددة، مثل https://google.com/search?query=JavaScript
، كما يمكننا وضع المعاملات عند إنشاء كائن URL
:
new URL('https://google.com/search?query=JavaScript')
ويجب ترميز المعاملات إذا احتوت على فراغات أو أحرف ليست لاتينيةً وما شابه (ستجد المزيد عن ذلك في الفقرات التالية)، لذلك توجد خاصية تتولى ذلك هي url.searchParams
، وهي كائن من النوع URLSearchParams، وتؤمن مجموعةً من التوابع التي تتعامل مع معاملات البحث:
-
(append(name, value
: يضيف المعامل المحدد بالاسمname
. -
(delete(name
: يحذف المعامل المحدد بالاسمname
. -
(get(name
: يحضر المعامل المحدد بالاسمname
. -
(getAll(name
: يحضر كل المعاملات التي لها نفس الاسمname
، وهو أمر ممكن، مثل?user=John&user=Pete
. -
(has(name
: التحقق من وجود معامل بالاسمname
. -
(set(name, value
: لضبط معامل أو تغييره. -
()sort
: فرز المعاملات بالاسم، وتُستخدّم نادرًا، وهي قابلة للمرور عليها Iterable بصورة مشابهة للترابط Map.
let url = new URL('https://google.com/search'); url.searchParams.set('q', 'test me!'); //! يضيف معاملًا ضمنه فراغ وإشارة alert(url); // https://google.com/search?q=test+me%21 url.searchParams.set('tbs', 'qdr:y'); // ":" يضيف معاملًا يحوي العلامة // تُرمز المعاملات تلقائيًا alert(url); // https://google.com/search?q=test+me%21&tbs=qdr%3Ay //(المرور على المعاملات (فك ترميز for(let [name, value] of url.searchParams) { alert(`${name}=${value}`); // q=test me!, then tbs=qdr:y }
الترميز Encoding
يحدد المعيار RFC3986 المحارف المسموحة في العناوين، والمحارف التي لا يُسمح باستخدامها. وينبغي ترميز المحارف التي لا يسمح بها، مثل الأحرف غير اللاتينية والفراغات، باستبدالها بمقابلاتها في ترميز UTF-8 مسبوقًا بالمحرف "%"، كأن نكتب 20%. ويمكن ترميز الفراغ بالمحرف "+" لأسباب تاريخية -وهذه حالة استثنائية-، لكن الجيد بالأمر هو أنّ الكائن URL
ينجز كل ذلك تلقائيًا، وكل ما علينا فعله هو تزويده بالمعاملات دون ترميز، وسيحول العنوان إلى نص:
// using some cyrillic characters for this example let url = new URL('https://ru.wikipedia.org/wiki/Тест'); url.searchParams.set('key', 'ъ'); alert(url); //https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D1%81%D1%82?key=%D1%8A
لاحظ أن القيمتين Тест
في مسار العنوان وъ
في المعامل قد رُمِّزا، سيغدو العنوان أطول لأن كل محرف سيُمثّل ببايتين في UTF-8، وبالتالي ستكون هناك كتلتان من الشكل ..%
لكل محرف.
ترميز القيم النصية
استخدم المبرمجون -في السابق وقبل ظهور الكائن URL
- القيم النصية لتمثيل العناوين، لكن استخدام الكائن URL
حاليًا أكثر ملاءمةً، ومع ذلك لا يزال استخدام القيم النصية شائعًا، فهو يجعل العنوان أقصر في الكثير من الأحيان، ولا بدّ عند استخدام القيم النصية من ترميز أو فك ترميز المحارف الخاصة يدويًا، باستخدام دوال مدمجة هي:
- encodeURI: يُرمِّز العنوان بالكامل.
- decodeURI: يفك ترميز النص المرمَّز.
- encodeURIComponent: يرمّز مكوّنًا من مكونات العنوان، مثل معاملات البحث أو المسار.
- decodeURIComponent: يفك ترميز الجزء المُرمَز.
لكن السؤال الطبيعي سيكون: "ما هو الفرق بين encodeURIComponent
وencodeURI
؟ ومتى سنستخدم كلًا منهما؟"
من السهل استيعاب الفكرة عند النظر إلى الصورة السابقة التي تفصل العنوان التالي إلى مكوناته:
https://site.com:8080/path/page?p1=v1&p2=v2#hash
إذ يُسمح باستخدام المحارف التالية :
و?
و=
و&
و#
في عنوان URL، ومن جهة أخرى إذا نظرنا إلى أي مكوّن من مكوّنات العنوان بمفرده، مثل: المعاملات، فلا بدّ من ترميز هذه المحارف حتى لا تخِلّ بتنسيق العنوان.
وهنا سنرى استخدام الدالتين السابقتين:
-
encodeURI
: تُرمز المحارف المرفوضة كليًا في العناوين فقط. -
encodeURIComponent
: ترمز نفس المحارف التي ترمزها الدالة السابقة بالإضافة إلى المحارف التالية:#
و$
و&
و+
و,
و/
و:
و;
و=
و?
و@
.
لذلك يمكن استخدام الدالة encodeURI
لترميز العنوان كاملًا:
// using cyrillic characters in url path let url = encodeURI('http://site.com/привет'); alert(url); // http://site.com/%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82
بينما ستستخدم الدالة encodeURIComponent
في ترميز معاملات العنوان:
let music = encodeURIComponent('Rock&Roll'); let url = `https://google.com/search?q=${music}`; alert(url); // https://google.com/search?q=Rock%26Roll
لاحظ الفرق عند استخدام encodeURI
:
let music = encodeURI('Rock&Roll'); let url = `https://google.com/search?q=${music}`; alert(url); // https://google.com/search?q=Rock&Roll
حيث لا تُرمّز الدالة encodeURI
المحرف &
لأنه محرف مقبول في عنوان URL الكامل، لكن لا بدّ من ترميزه عندما يكون ضمن معامل البحث، وإلا ستكون نتيجة q=Rock&Roll
هي q=Rock
، بالإضافة إلى معامل غامض يمثله Roll
، وهي ليست كما قصدنا.
لذا لا بدّ من استخدام encodeURIComponent
فقط عند تشفير كل معامل من معاملات البحث، لكي نضعه بشكله الصحيح في نص العنوان، وتبقى طريقة ترميز الاسم والعنوان معًا هي الأكثر أمانًا؛ إلا عندما نثق تمامًا بعدم احتواء أي منهما على محارف ممنوعة الاستخدام.
اقتباساختلافات التشفير بالنسبة إلى العناوين URL بُني الصنفان URL وURLSearchParams على التوصيفات الأخيرة للعناوين URI ضمن المعيار RFC3986، بينما بُنيت الدوال
*encode
على النسخة RFC2396 المنتهية المفعول. ستجد بعض الاختلافات بينهما مثل عناوين IPv6 التي ستُرمَّز بشكل مختلف:
// valid url with IPv6 address let url = 'http://[2607:f8b0:4005:802::1007]/'; alert(encodeURI(url)); // http://%5B2607:f8b0:4005:802::1007%5D/ alert(new URL(url)); // http://[2607:f8b0:4005:802::1007]/
اقتباسوكما نرى ستستبدل الدالة
encodeURI
محتوى الأقواس المربعة[...]
غير الصحيحة كونها عنوان IPv6، فلم تكن هذه العناوين موجودةً في زمن المعيار (أغسطس "آب" 1998)، وهذه الحالات نادرة، لذلك ستعمل الدوال*encode
جيدًا في معظم الأوقات.
ترجمة -وبتصرف- للفصل URL Objects من سلسلة The Modern JavaScript Tutorial.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.