أمثلة ترميز عناوين URL في JavaScript – متى وكيف تستخدم encodeURIComponent() و encodeURI()
قد يختلط الأمر على العديد من مطوري الويب عند التعامل مع دالتي encodeURI() و encodeURIComponent() في JavaScript، فمن أسمائهما قد يبدو أنهما تؤديان نفس الغرض. هذا الالتباس شائع، وقد تتساءل متى تستخدم أيهما.
في هذا المقال، سنقوم بتبسيط الفروقات الجوهرية بين هاتين الدالتين وسنزيل الغموض المحيط بهما، مع تقديم أمثلة عملية لتوضيح كيفية ومتى يجب استخدام كل واحدة منهما بفعالية لضمان بناء عناوين URL صحيحة وآمنة.
ما هو URI وما الفرق بينه وبين URL؟
لفهم دالات الترميز، من الضروري أولاً استيعاب المفاهيم الأساسية لـ URI و URL:
URI(Uniform Resource Identifier): هو معرف الموارد الموحد. يمثل أي شيء يحدد موردًا بشكل فريد، مثل رقم تعريفي (ID)، اسم، أو رقمISBN.URL(Uniform Resource Locator): هو محدد الموارد الموحد. يحدد موردًا معينًا وكيف يمكن الوصول إليه (مثل البروتوكولHTTPأوHTTPS).
ببساطة، كل URL هو URI، ولكن ليس كل URI هو URL. يمكن اعتبار URI مفهومًا أوسع يشمل URL كنوع خاص منه يحدد طريقة الوصول.
لماذا نحتاج إلى الترميز (Encoding)؟
تتمتع عناوين URL بمتطلبات صارمة فيما يتعلق بالأحرف التي يمكن أن تحتويها. لا يمكن لعناوين URL أن تحتوي إلا على أحرف معينة من مجموعة أحرف ASCII القياسية المكونة من 128 حرفًا. يجب ترميز الأحرف المحجوزة أو الخاصة التي لا تنتمي إلى هذه المجموعة لتجنب المشاكل.
هذا يعني أننا بحاجة إلى ترميز هذه الأحرف عند تمريرها في عنوان URL. على سبيل المثال، الأحرف الخاصة مثل & (علامة العطف)، المسافة (space)، أو ! (علامة التعجب) إذا تم إدخالها مباشرة في عنوان URL دون ترميز، فقد تتسبب في مواقف غير متوقعة أو تؤدي إلى كسر بنية العنوان.
حالات الاستخدام الشائعة للترميز:
- عند إرسال قيم من نموذج (
form) قد تحتوي على سلاسل نصية تحتاج إلى تمريرها كجزء من عنوانURL. - عند الحاجة إلى قبول معلمات سلسلة الاستعلام (
query string parameters) لإجراء طلباتGET، حيث قد تحتوي هذه المعلمات على أحرف خاصة.
الفرق الجوهري بين encodeURI() و encodeURIComponent()
تُستخدم كل من دالتي encodeURI() و encodeURIComponent() لترميز معرفات الموارد الموحدة (URIs) عن طريق استبدال أحرف معينة بتسلسلات هروب (escape sequences) تمثل ترميز UTF-8 للحرف.
يكمن الاختلاف الرئيسي في الغرض من استخدامهما:
encodeURIComponent(): يجب استخدامها لترميز مكونURI(URI Component) – أي سلسلة نصية يُفترض أن تكون جزءًا من عنوانURL، مثل قيمة معلمة استعلام (query parameter) أو جزء من مسار. هذه الدالة تقوم بترميز عدد أكبر من الأحرف، بما في ذلك الأحرف التي لها معنى خاص في بنيةURLمثل/و&و=.encodeURI(): يجب استخدامها لترميزURIكامل أوURLموجود بالفعل. هذه الدالة أقل عدوانية في الترميز، حيث أنها لا تقوم بترميز الأحرف التي تعتبر صالحة في بنيةURL(مثل/و?و&و=و:) لأنها تفترض أنك تقوم بتمريرURLمكتمل وبنيته صحيحة.
الأحرف التي لا يتم ترميزها بواسطة كل دالة:
من المهم معرفة الأحرف التي تحتفظ بها كل دالة دون ترميز:
encodeURI()لن تقوم بترميز:~ ! @ # $ & * ( ) = : / , ; ? + '. كما أنها لا ترمّز الأحرف الأبجدية الرقمية (A-Z a-z 0-9) والأحرف- _ ..encodeURIComponent()لن تقوم بترميز:~ ! * ( ) '. كما أنها لا ترمّز الأحرف الأبجدية الرقمية (A-Z a-z 0-9) والأحرف- _ ..
لاحظ أن encodeURIComponent() تقوم بترميز أحرف مثل # و $ و & و = و : و / و , و ; و ? و + والتي لا تقوم encodeURI() بترميزها. هذا هو الفرق الجوهري الذي يحدد متى تستخدم كل دالة.
أمثلة عملية على الترميز في JavaScript
مثال 1: ترميز عنوان URL كامل ومكون URL
يوضح هذا المثال كيف تتعامل كل دالة مع عنوان URL كامل ومكون من عنوان URL:
const url = 'https://www.twitter.com';
console.log(encodeURI(url));
// الناتج: https://www.twitter.com (لم يتم ترميز أي شيء لأن URL صحيح وبنيته سليمة)
console.log(encodeURIComponent(url));
// الناتج: https%3A%2F%2Fwww.twitter.com (تم ترميز الأحرف الخاصة مثل : و / لأنها تعتبر جزءًا من سلسلة نصية)
const paramComponent = '?q=search';
console.log(encodeURIComponent(paramComponent));
// الناتج: %3Fq%3Dsearch (تم ترميز ? و = لأنهما أحرف خاصة في مكون URL)
console.log(url + encodeURIComponent(paramComponent));
// الناتج: https://www.twitter.com%3Fq%3Dsearch (عند إضافة مكون مُرمّز إلى URL)
كما نرى، encodeURI() لا تغير URL صالحًا، بينما encodeURIComponent() تقوم بترميز الأحرف التي لها دلالة خاصة في سياق مكون URL.
مثال 2: التعامل مع المسافات في عنوان URL
عندما يحتوي جزء من مسار URL على مسافات، يجب ترميزها:
console.log(encodeURI("http://www.mysite.com/a file with spaces.html"));
// الناتج: http://www.mysite.com/a%20file%20with%20spaces.html
هنا، قامت encodeURI() بترجمة المسافات إلى %20، وهو الترميز الصحيح للمسافة في عناوين URL.
مثال 3: بناء عنوان URL من معلمات سلسلة الاستعلام
يعد ترميز معلمات الاستعلام أمرًا بالغ الأهمية لضمان قراءتها بشكل صحيح:
let param = encodeURIComponent('mango');
let url = "http://mysite.com/?search=" + param + "&length=99";
console.log(url);
// الناتج: http://mysite.com/?search=mango&length=99
في هذا المثال، تم ترميز قيمة المعلمة 'mango' بواسطة encodeURIComponent()، على الرغم من أنها لا تحتوي على أحرف خاصة هنا، إلا أنها أفضل ممارسة لضمان السلامة.
مثال 4: معلمات الاستعلام التي تحتوي على أحرف محجوزة
عندما تحتوي قيمة المعلمة على أحرف محجوزة مثل &، يصبح استخدام encodeURIComponent() ضروريًا:
let params = encodeURIComponent('mango & pineapple');
let url = "http://mysite.com/?search=" + params;
console.log(url);
// الناتج: http://mysite.com/?search=mango%20%26%20pineapple
هنا، تم ترميز المسافة إلى %20 وعلامة العطف & إلى %26، مما يضمن أن المتصفح أو الخادم سيفسر السلسلة كقيمة واحدة للمعلمة search بدلاً من تقسيمها إلى معلمات متعددة.
الخلاصة
الخلاصة بسيطة ومباشرة:
- إذا كان لديك عنوان
URLكامل وتريد ترميزه (مع الحفاظ على بنيته الأساسية)، استخدمencodeURI(). - إذا كان لديك جزء من
URL(مثل معلمة استعلام أو جزء من مسار) وتريد ترميزه ليكون آمنًا ضمنURLأكبر، استخدمencodeURIComponent().
فهم هذه الفروقات الدقيقة أمر حيوي لتجنب الأخطاء الشائعة في تطوير الويب ولضمان أن تطبيقاتك تتعامل مع عناوين URL بشكل صحيح وآمن.
الخلاصة التقنية
يُعد الترميز الصحيح لعناوين URL ومكوناتها حجر الزاوية في بناء تطبيقات ويب قوية وآمنة. إن التمييز بين encodeURI() و encodeURIComponent() ليس مجرد تفصيل تقني، بل هو ضرورة عملية تمنع الثغرات الأمنية المحتملة وتضمن سلامة البيانات. استخدام encodeURIComponent() لمعلمات الاستعلام أو الأجزاء الديناميكية من URL يضمن أن الأحرف الخاصة، التي قد تفسرها المتصفحات أو الخوادم بشكل خاطئ، يتم التعامل معها كبيانات خام بدلاً من مكونات هيكلية. بينما تخدم encodeURI() غرضًا مختلفًا، وهو التأكد من أن URL كامل يظل صالحًا وقابلًا للتوجيه دون إفساد بنيته الأساسية. إتقان هذه الدالات يعكس فهمًا عميقًا لبروتوكولات الويب ويساهم بشكل مباشر في تجربة مستخدم سلسة وخالية من الأخطاء.