URL পার্সিং কী?
URL পার্সিং হলো একটি Uniform Resource Locator-কে তার পৃথক উপাদানে বিভক্ত করার প্রক্রিয়া: প্রোটোকল (scheme), হোস্টনেম, পোর্ট, পাথনেম, কোয়েরি প্যারামিটার এবং ফ্র্যাগমেন্ট আইডেন্টিফায়ার। প্রতিটি URL, RFC 3986 এবং WHATWG URL Standard দ্বারা নির্ধারিত একটি কাঠামো অনুসরণ করে। একটি URL পার্সার কাঁচা স্ট্রিং পড়ে, বিভাজক অক্ষরগুলোর (://, :, /, ?, #, &, =) সাহায্যে প্রতিটি অংশ চিহ্নিত করে এবং সেগুলো আলাদা, অ্যাক্সেসযোগ্য ফিল্ড হিসেবে ফেরত দেয়।
আপনি যখনই কোনো ঠিকানা টাইপ করেন বা কোনো লিংকে ক্লিক করেন, ব্রাউজার URL পার্সিং করে। JavaScript-এর URL কনস্ট্রাক্টর, Python-এর urllib.parse মডিউল এবং Go-এর net/url প্যাকেজ — সবই একই কাঠামোগত নিয়ম অনুসরণ করে পার্সার তৈরি করেছে। URL পার্সিং হলো URL এনকোডিং-এর বিপরীত ক্রিয়া: নিরাপদ পরিবহনের জন্য অক্ষর রূপান্তর করার পরিবর্তে, আপনি একটি সম্পূর্ণ URL-কে তার গঠনকারী অংশে বিভক্ত করেন।
https://api.example.com:8080/v1/users?page=2&limit=10#section-এর মতো একটি সাধারণ URL-এ ছয়টি স্বতন্ত্র উপাদান রয়েছে। বিভাজক অক্ষরগুলো — ://, :, /, ?, &, =, এবং # — পার্সিং অস্পষ্টতামুক্ত রাখে: প্রতিটি চিহ্ন একটি সীমানা নির্দেশ করে এবং পার্সারকে কোনো অস্পষ্টতা ছাড়াই ফিল্ড বের করতে সাহায্য করে।
অনলাইন URL পার্সার কেন ব্যবহার করবেন?
ম্যানুয়ালি URL ভাগ করা ত্রুটিপ্রবণ — বিশেষত যখন স্ট্রিংয়ে এনকোড করা অক্ষর, একাধিক কোয়েরি প্যারামিটার বা অ-মানক পোর্ট থাকে। এই টুলটি ব্রাউজার যে WHATWG-সামঞ্জস্যপূর্ণ অ্যালগরিদম ব্যবহার করে সেটি দিয়ে URL পার্স করে এবং প্রতিটি উপাদান একটি স্বচ্ছ, কপিযোগ্য টেবিলে প্রদর্শন করে।
URL পার্সারের ব্যবহারের ক্ষেত্র
URL উপাদানের রেফারেন্স
নিচের টেবিলে দেখানো হয়েছে JavaScript URL কনস্ট্রাক্টর একটি URL পার্স করার সময় যে প্রপার্টিগুলো ফেরত দেয়। একই উপাদানগুলো Python-এর urlparse ফলাফল, Go-এর url.URL স্ট্রাক্ট এবং PHP-এর parse_url আউটপুটেও বিদ্যমান, যদিও ভাষা অনুযায়ী প্রপার্টির নাম ভিন্ন।
| প্রপার্টি | উদাহরণ | বিবরণ |
|---|---|---|
| protocol | https: | Scheme including the trailing colon |
| hostname | api.example.com | Domain name or IP address |
| port | 8080 | Port number (empty string if default) |
| pathname | /v1/users | Path starting with / |
| search | ?page=2&limit=10 | Query string including the leading ? |
| hash | #section | Fragment identifier including the leading # |
| origin | https://api.example.com:8080 | protocol + hostname + port |
| host | api.example.com:8080 | hostname + port |
| username | admin | Credentials before @ (rarely used in practice) |
| password | secret | Credentials before @ (avoid in production URLs) |
| href | (full URL) | The complete, serialized URL string |
WHATWG URL Standard বনাম RFC 3986
দুটি স্পেসিফিকেশন URL পার্স করার পদ্ধতি নির্ধারণ করে। তারা মৌলিক কাঠামোতে একমত, কিন্তু প্রান্তিক ক্ষেত্রে আলাদা আচরণ করে — এবং সেই পার্থক্যই সাধারণত তখন দায়ী যখন আপনার ব্রাউজার সার্ভারের চেয়ে ভিন্নভাবে একটি URL পরিচালনা করে।
ব্যবহারিকভাবে, বেশিরভাগ পার্থক্য দেখা যায় যখন আন্তর্জাতিক ডোমেইন নাম (IDN), অনুপস্থিত scheme বা অস্বাভাবিক অক্ষর সহ URL পার্স করা হয়। WHATWG পার্সার স্বয়ংক্রিয়ভাবে IDN হোস্টনেমকে Punycode-এ রূপান্তর করে, যেখানে কঠোর RFC 3986 পার্সার সেগুলো প্রত্যাখ্যান করতে পারে। আপনি যদি এই টুলে একটি URL পেস্ট করেন এবং আপনার সার্ভার-সাইড কোডের চেয়ে ভিন্ন ফলাফল দেখেন, তাহলে WHATWG বনাম RFC পার্থক্যই সম্ভবত কারণ।
কোড উদাহরণ
প্রতিটি প্রধান ভাষায় একটি অন্তর্নির্মিত URL পার্সার রয়েছে। নিচের উদাহরণগুলো একই URL পার্স করে এবং তার উপাদান বের করে। ভাষা অনুযায়ী নামকরণের ছোট পার্থক্য লক্ষ্য করুন: Python protocol-এর পরিবর্তে scheme ব্যবহার করে, এবং Go search-এর পরিবর্তে RawQuery উন্মুক্ত করে।
const url = new URL('https://api.example.com:8080/v1/users?page=2&limit=10#section')
url.protocol // → "https:"
url.hostname // → "api.example.com"
url.port // → "8080"
url.pathname // → "/v1/users"
url.search // → "?page=2&limit=10"
url.hash // → "#section"
// Iterate over query parameters
for (const [key, value] of url.searchParams) {
console.log(`${key} = ${value}`)
}
// → "page = 2"
// → "limit = 10"
// Modify and re-serialize
url.searchParams.set('page', '3')
url.toString()
// → "https://api.example.com:8080/v1/users?page=3&limit=10#section"from urllib.parse import urlparse, parse_qs
result = urlparse('https://api.example.com:8080/v1/users?page=2&limit=10#section')
result.scheme # → 'https'
result.hostname # → 'api.example.com'
result.port # → 8080
result.path # → '/v1/users'
result.query # → 'page=2&limit=10'
result.fragment # → 'section'
# Parse query string into a dict
params = parse_qs(result.query)
params['page'] # → ['2']
params['limit'] # → ['10']
# Reconstruct with modifications
from urllib.parse import urlencode, urlunparse
new_query = urlencode({'page': '3', 'limit': '10'})
urlunparse(result._replace(query=new_query))
# → 'https://api.example.com:8080/v1/users?page=3&limit=10#section'package main
import (
"fmt"
"net/url"
)
func main() {
u, err := url.Parse("https://api.example.com:8080/v1/users?page=2&limit=10#section")
if err != nil {
panic(err)
}
fmt.Println(u.Scheme) // → "https"
fmt.Println(u.Hostname()) // → "api.example.com"
fmt.Println(u.Port()) // → "8080"
fmt.Println(u.Path) // → "/v1/users"
fmt.Println(u.RawQuery) // → "page=2&limit=10"
fmt.Println(u.Fragment) // → "section"
// Query params as map
q := u.Query()
fmt.Println(q.Get("page")) // → "2"
fmt.Println(q.Get("limit")) // → "10"
}<?php $url = 'https://api.example.com:8080/v1/users?page=2&limit=10#section'; $parts = parse_url($url); $parts['scheme']; // → "https" $parts['host']; // → "api.example.com" $parts['port']; // → 8080 $parts['path']; // → "/v1/users" $parts['query']; // → "page=2&limit=10" $parts['fragment']; // → "section" // Parse query string into an array parse_str($parts['query'], $params); $params['page']; // → "2" $params['limit']; // → "10"