آدرسهای URL بخش مهمی از هر اپلیکیشن وب هستند. اگر اپلیکیشن ما درخواستهایی به یک API ارسال میکند، ایجاد آدرسهای صحیح برای این درخواستها اهمیت زیادی دارد. رابط کاربری API URL
در جاوااسکریپت، که در تمامی مرورگرهای مدرن پشتیبانی میشود، راهی برای تجزیه و دستکاری آدرسهای URL فراهم میکند و دسترسی آسان به بخشهای مختلف یک آدرس URL را ممکن میسازد.
آدرس URL زیر را در نظر میگیریم:
https://example.com/api/search?query=foo&sort=asc#results
این آدرس URL شامل بخشهای زیر است:
https
example.com
/api/search
?query=foo&sort=asc
#results
با استفاده از جاوااسکریپت مدرن، میتوانیم آدرسهای URL را تجزیه کرده و این بخشهای مختلف را به راحتی استخراج کنیم.
در مرورگرهای قدیمی، قبل از اینکه API URL
معرفی شود، یکی از روشهای معمول برای تجزیه آدرسهای URL استفاده از المنت <a>
بود. این المنت قابلیتهایی برای تجزیه ابتدایی URL ارائه میداد. به عنوان مثال، میتوانستیم query string را از یک URL استخراج کنیم:
function getQueryString(url) { const link = document.createElement('a'); link.href = url; return url.search; }
این روش، با وجود سادگی، محدودیتهایی داشت:
href
داده میشد، خطایی رخ نمیداد.روش دیگر، استفاده از Regular Expressionها برای تجزیه بخشهای مختلف URL بود، اما این کار بسیار پیچیده و مستعد خطا بود.
استفاده از API URL
برای تجزیه URLها بسیار ساده است. تنها کافی است آدرس URL مورد نظر را به URL
constructor ارسال کنیم. اگر رشته URL معتبر باشد، یک آبجکت URL
به ما return میشود که شامل ویژگیهایی برای دسترسی به بخشهای مختلف URL است.
const url = new URL('https://example.com/api/search?query=foobar'); console.log(url.host); // example.com console.log(url.pathname); // /api/search console.log(url.search); // ?query=foobar
میتوانیم query string یک URL
را به دو روش استخراج کنیم:
search
: این ویژگی، یک رشته است که شامل کل query string میشود (همراه با کاراکتر ?
).searchParams
: این ویژگی، یک آبجکت از نوع URLSearchParams
است.اگر بخواهیم مقدار یک پارامتر خاص در query string را بدانیم، میتوانیم از متد get
استفاده کنیم تا مقدار آن پارامتر را با نامش دریافت نماییم.
const url = new URL('https://example.com/api/search?query=foobar&maxResults=10'); console.log(url.searchParams.get('query'); // foobar console.log(url.searchParams.get('maxResults'); // 10
اگر چندین پارامتر با نام یکسان وجود داشته باشد، میتوانیم از متد getAll
استفاده کنیم تا آرایهای شامل تمامی مقادیر آن نام را دریافت نماییم:
const url = new URL('https://example.com/api/search?tag=tag1&tag=tag2&tag=tag3'); console.log(url.searchParams.getAll('tag')); // ['tag1', 'tag2', 'tag3']
ساختن query string به صورت دستی میتواند مشکل باشد، مخصوصاً اگر پارامترها شامل کاراکترهای خاصی باشند که نیاز به کدگذاری دارند. بهعنوان مثال، اگر یک پارامتر نیاز داشته باشد که شامل کاراکتر &
باشد، باید آن را به عنوان %۲۶
کدگذاری کنیم. برای مدیریت این موارد، باید از تابع encodeURIComponent
استفاده نماییم:
let queryString = 'foo=bar'; queryString += '&baz=qux'; queryString += '&tag=' + encodeURIComponent('one&two'); console.log(queryString); // foo=bar&baz=qux&tag=one%26two
اما میتوانیم با استفاده از آبجکت URLSearchParams
به صورت ایمنتر query string را بسازیم:
const params = new URLSearchParams(); params.append('foo', 'bar'); params.append('baz', 'qux'); params.append('tag', 'one&two'); console.log(params.toString()); // foo=bar&baz=qux&tag=one%26two
استفاده از URLSearchParams
مزایایی دارد که عبارتند از:
&
برای جداسازی پارامترها باشیم.بدون استفاده از آبجکت URLSearchParams
، پیمایش پارامترهای یک query string کمی پیچیده میشود. در این حالت، باید چندین بار رشته را تقسیم کنیم؛ یک بار برای جدا کردن پارامترها به عنوان جفتهای key/value و بار دیگر برای تفکیک key از value در هر پارامتر:
function listQueryParams(queryString) { queryString.split('&').forEach(param => { const [key, value] = param.split('='); console.log(`${key}: ${value}`); }); }
اگر پارامترها شامل کاراکترهای کدگذاری شده باشند، باید آنها را نیز decode کنیم:
function listQueryParams(queryString) { queryString.split('&').forEach(param => { const [key, value] = param.split('='); console.log(`${key}: ${decodeURIComponent(value)}`); }); }
اما با استفاده از متد entries
آبجکت URLSearchParams
میتوانیم به سادگی روی جفتهای key/value پیمایش کنیم:
function listQueryParams(queryString) { const params = new URLSearchParams(queryString); params.entries().forEach(([key, value]) => console.log(`${key}: ${value}`)); }
برای ساخت یک URL کامل با یک آدرس پایه و چندین پارامتر جستجو، میتوانیم از ترکیب URL و URLSearchParams استفاده کنیم. مثال زیر یک روش کامل را نشان میدهد:
const url = new URL('https://example.com/api/search'); url.searchParams.append('query', 'test'); url.searchParams.append('tag', 'tag1'); url.searchParams.append('tag', 'tag2'); // https://example.com/api/search?query=test&tag=tag1&tag=tag2 console.log(url.toString());
ممکن است بخواهیم از یک regular expression برای اعتبارسنجی یک URL استفاده کنیم، اما نوشتن یک regular expression که بتواند همه URLهای معتبر را به درستی شناسایی کند، کار بسیار دشواری است.
به جای آن، میتوانیم از API URL
استفاده کنیم. اگر یک URL نامعتبر به URL
Constructor داده شود، خطا تولید میکند. این ویژگی برای بررسی معتبر بودن URLها مفید است:
function isValidURL(url) { try { new URL(url); return true; } catch (error) { return false; } }
مرورگرهای جدیدتر این کار را سادهتر کردهاند. متد استاتیک URL.canParse
اضافه شده است که با یک خط کد، اعتبارسنجی مشابهی را انجام میدهد. درست مانند تابع isValidURL
که در بالا دیدیم، این متد در جاوااسکریپت یک رشته URL دریافت میکند و بسته به معتبر بودن آن، مقدار true
یا false
برمیگرداند.
API URL
یک مکانیزم قدرتمند برای تبدیل URLهای نسبی به کامل ارائه میدهد. بهطور معمول، اگر URLای که به URL
constructor داده میشود، کامل و معتبر نباشد، خطا ایجاد میکند. اما اگر یک آرگومان دوم به آن بدهیم، این آرگومان به عنوان یک URL پایه عمل میکند تا URL نسبی را بر اساس آن بسازد.
در این روش، یعنی روش دو آرگومانی، آرگومان اول نیازی به معتبر یا کامل بودن ندارد، اما آرگومان دوم باید یک URL معتبر و کامل باشد. به عنوان مثال:
new URL('/about', 'https://example.com').href;
URL
constructor، آدرس پایه https://example.com
را میگیرد و مسیر نسبی /about
را به آن اضافه میکند. در نتیجه، خروجی https://example.com/about
خواهد بود.
یک مثال دیگر:
new URL('profile', 'https://example.com/users').href;
ممکن است انتظار داشته باشیم که نتیجه https://example.com/users/profile
باشد، اما در واقع خروجی https://example.com/profile
خواهد بود. این رفتار دقیقاً مانند یک لینک نسبی عمل میکند؛ یعنی بخش parent مسیر را که ریشه example.com
است، در نظر میگیرد و سپس profile
را به آن اضافه میکند.
یک مثال دیگر از استفاده URL نسبی را بررسی میکنیم. میتوانیم از ..
استفاده کنیم تا یک سطح به عقب در ساختار مسیر برویم:
new URL('../profile', 'https://example.com/users/123').href;
در این مثال URL در نهایت به https://example.com/profile
تبدیل میشود. باید این موضوع را به خاطر داشته باشیم که آدرسهای URL نسبی از بخش parent مسیر شروع میشوند. در اینجا، ..
باعث میشود که یک سطح بالاتر در مسیر حرکت کنیم.
اگر هنگام استفاده از URL
constructor یک آدرس نسبی را وارد کنیم اما یک آدرس نامعتبر یا ناقص به عنوان URL پایه مشخص نماییم، با خطا مواجه میشویم. همچنین، اگر بدون مشخص کردن یک URL پایه کامل از یک آدرس نسبی استفاده کنیم، باز هم خطا دریافت خواهیم کرد.
new URL('../profile', '/about'); // error! new URL('../profile'); // error
احتمالا با آبجکت window.location
در جاوااسکریپت آشنا هستیم، که نماینده URL صفحه فعلی میباشد. این آبجکت دارای ویژگیهایی مانند href
و pathname
است، بنابراین ممکن است فکر کنیم که یک آبجکت URL
است. اما در واقع این یک آبجکت Location
است که برخی ویژگیهای مشترک با URL
دارد، اما برخی ویژگیها مانند searchParams
را ندارد.
با اینکه این آبجکت یک URL
کامل نیست، اما میتوانیم از آن برای ساخت آبجکتهای جدید URL
استفاده کنیم. به عنوان مثال، میتوانیم window.location
را به URL
constructor بدهیم تا یک URL
کامل با ویژگیهایی مثل searchParams
بر اساس URL فعلی بسازیم، یا حتی از آن به عنوان URL پایه برای ساخت URLهای نسبی استفاده کنیم:
new URL('/profile', window.location).href;
استفاده از URL
باعث میشود تا بتوانیم به سادگی path را از یک URL استخراج کنیم. به عنوان مثال، در URL https://example.com/api/users/123/profile
مقدار pathname برابر با /api/users/123/profile
است. اما اگر بخواهیم فقط ID کاربر (۱۲۳
) را از این URL استخراج کنیم، چه کاری باید انجام بدهیم؟
همانطور که قبلاً به آن اشاره کردیم، ایجاد regular expressionها برای اعتبارسنجی و استخراج بخشهای خاص از یک URL میتواند دشوار باشد.
API جدیدی به نام URLPattern
در جاوااسکریپت وجود دارد که میتواند برای تطبیق و استخراج بخشهایی از URL، بر اساس الگوهای مشخص مورد استفاده قرار بگیرد. این قابلیت به ویژه در برنامههایی مثل routing سمت کلاینت در اپلیکیشنهای تکصفحهای (SPA) بسیار مفید است.
با استفاده از URL مربوط به پروفایل کاربر به عنوان مثال، میخواهیم یک URLPattern
ایجاد کنیم تا ID کاربر را استخراج نماییم. میتوانیم از کاراکتر :
در ابتدای یک placeholder نامگذاری شده استفاده کنیم، که بعداً برای تطبیق آن بخش از URL به کار میرود:
const pattern = new URLPattern('https://example.com/api/users/:userId/profile'); const matcher = pattern.exec('https://example.com/api/users/123/profile'); console.log(matcher.pathname.groups.userId); // 123
هنگامی که متد exec
را روی یک URLPattern
فراخوانی میکنیم، به یک URL معتبر نیاز دارد. این متد یک آبجکت matcher برمیگرداند که شامل ویژگیهایی برای هر بخش از URL (مانند protocol
، host
، pathname
و غیره) است.
هر یک از این ویژگیها دارای یک ویژگی groups
هستند که نام placeholderها (مانند :userId
) را به مقادیر آنها در URL نگاشت میکند.
اگر فقط بخواهیم یک بخش خاص از URL، مانند نام مسیر را تطبیق دهیم، میتوانیم از کاراکترهای wildcard (مانند *
) در الگوی URL استفاده کنیم. همچنین، به جای استفاده از یک رشته URL، میتوانیم یک آبجکت حاوی بخشهایی از URL که میخواهیم تطبیق دهیم، ارسال نماییم:
new URLPattern('https://*/api/users/:userId/profile'); new URLPattern({ pathname: '/api/users/:userId/profile' });
API URLPattern
هنوز در تمام مرورگرها قابل استفاده نیست. در زمان نوشتن این مطلب، مرورگرهای Firefox و Safari از آن پشتیبانی نمیکنند. برای مشاهده آخرین وضعیت پشتیبانی مرورگرها میتوانیم به وبسایت CanIUse.com مراجعه کنیم.
API URL
یک ابزار چندمنظوره برای ساخت، اعتبارسنجی و مدیریت URLها در جاوااسکریپت است. استفاده از این API نسبت به روشهای دستی یا regular expressionها ایمنتر و کمخطاتر است. همچنین با استفاده از آبجکت URLSearchParams
میتوانیم بدون نگرانی درباره اتصال رشتهها یا کدگذاری کاراکترهای خاص، به راحتی یک query string بسازیم.
دیدگاهها: