آشنایی با مفاهیم API و REST API و آموزش کامل fetch در جاوااسکریپت

در این پست قصد داریم در عین سادگی، بصورت کاملا مختصر و مفید، آموزش کامل fetch و ajax در جاوااسکریپت را بیان کنیم و همینطور بصورت جزئی روی مبحث api ها بررسی عمیقی داشته باشیم.
همانطور که میدانید در ابتدا ایجکس ویا همان ajax در زبان جاوااسکریپت ، وظیفه ارتباط با سرور در نوع داده غیر همزمان را برعهده داشت و امروزه در مرورگرهای آپدیت و به روز ، دستور fetch
به ترتیب به معرفی و انواع آنها میپردازیم و تا حدی در جزئیات آنها ریز میشویم ، اما قبل از این موارد باید آشنایی با API ها پیدا کنیم.
آشنایی با مفاهیم پایه API
API مخفف عبارت Application Programming Interface بهمعنای «رابط برنامهنویسی نرمافزار» است.
در سادهترین تعریف، API مکانیزمی استاندارد برای ارتباط و تبادل اطلاعات بین دو نرمافزار یا سیستم مستقل فراهم میکند، بدون آنکه نیاز به دانستن نحوه پیادهسازی داخلی یکدیگر داشته باشند.
به بیان دیگر، API به توسعهدهندگان این امکان را میدهد که از قابلیتها و خدمات یک نرمافزار دیگر استفاده کنند، بدون آنکه به منطق درونی آن دسترسی مستقیم داشته باشند.
API یکی از ارکان اساسی در معماری نرمافزارهای مدرن است. برخی از مهمترین کاربردهای آن عبارتند از:
- ایجاد ارتباط بین فرانتاند و بکاند در نرمافزارهای تحت وب و موبایل
- استفاده از خدمات نرمافزاری شرکتهای ثالث مانند Google Maps API، Stripe API یا OpenWeather API
- افزایش قابلیت توسعهپذیری و نگهداری نرمافزار با جداسازی لایههای مختلف
- اتصال چندین پلتفرم به یک سرویس واحد (مانند وبسایت، اپلیکیشن موبایل و نرمافزار دسکتاپ)
APIها را میتوان از جنبههای مختلف دستهبندی کرد. در ادامه، رایجترین انواع API را معرفی میکنیم:
نوع API | توضیح |
---|---|
Local API | رابطی برای تعامل بین اجزای داخلی یک نرمافزار (مثلاً در سیستمعاملها) |
Web API | APIهایی که از طریق پروتکل HTTP در بستر اینترنت قابل دسترسی هستند |
Third-party API | APIهایی که توسط شرکتهای دیگر ارائه میشوند و معمولاً برای استفاده عمومی یا تجاری در دسترساند |
Private API | APIهایی که فقط برای استفاده داخلی سازمان طراحی شدهاند |
Public API | APIهایی که برای استفاده عمومی و توسعهدهندگان خارجی در دسترس هستند، گاهی با محدودیت یا نیاز به ثبتنام |
تفاوت API و REST API
REST API یک نوع خاص از Web API است که براساس اصول معماری REST طراحی شدهاست. در جدول زیر، تفاوت میان API بهطور کلی و REST API بهطور خاص را مشاهده میکنید:
ویژگی | API (عمومی) | REST API |
---|---|---|
معماری | آزاد (ممکن است REST، SOAP، GraphQL و…) | مبتنی بر اصول مشخص معماری REST |
نحوه ارتباط | بسته به نوع API متغیر است | مبتنی بر پروتکل HTTP |
فرمت داده | ممکن است JSON، XML یا دیگر فرمتها باشد | عمدتاً JSON (یا XML) |
استانداردسازی | استاندارد خاصی الزامی نیست | پیروی از اصول REST الزامی است |
برای درک بهتر مفهوم API، یک مثال کاربردی ارائه میشود. فرض کنید قصد دارید در یک وبسایت، اطلاعات آبوهوای تهران را نمایش دهید. با استفاده از API سرویس OpenWeatherMap، میتوانید چنین درخواستی ارسال کنید:
GET https://api.openweathermap.org/data/2.5/weather?q=Tehran&appid=YOUR_API_KEY
و پاسخ آن، بهصورت JSON خواهد بود:
{
"main": {
"temp": 295.15
},
"name": "Tehran"
}
آیا میدانید مدرسه پرنیان، دوره آموزش طراحی سایت حرفه ای بصورت حضوری و مجازی برگزار میکند؟کلیک کنید
REST چیست؟
REST مخفف عبارت Representational State Transfer بهمعنای «انتقال وضعیت بهصورت نمایشی» است.
REST یک سبک معماری برای طراحی API است که توسط Roy Fielding در سال ۲۰۰۰ در رساله دکتریاش معرفی شد. REST به توسعهدهندگان کمک میکند تا APIهایی طراحی کنند که ساده، مقیاسپذیر، و سازگار با پروتکل HTTP باشند.
یک API که اصول معماری REST را رعایت کند، یک RESTful API نامیده میشود.
برای اینکه یک API ، رست باشد، باید ۶ اصل زیر را رعایت کند:
اصل | توضیح |
---|---|
1. Client-Server | تفکیک کامل بین کلاینت (مثلاً React یا اپ موبایل) و سرور (مثلاً Node.js یا Django) |
2. Stateless | هر درخواست باید مستقل باشد. هیچ اطلاعاتی از درخواستهای قبلی در سرور نگهداری نمیشود. |
3. Cacheable | پاسخها میتوانند قابل کش شدن باشند تا کارایی افزایش یابد. |
4. Uniform Interface | همه درخواستها باید از یک ساختار و قرارداد مشخص پیروی کنند (مثل استفاده استاندارد از URL و HTTP). |
5. Layered System | API ممکن است از چند لایه (مانند CDN، فایروال، سرور اصلی) عبور کند بدون آنکه کلاینت متوجه شود. |
6. Code on Demand (اختیاری) | سرور میتواند کد (مثلاً جاوااسکریپت) به کلاینت ارسال کند و کلاینت آن را اجرا کند. |
در RESTful API، برای انجام عملیاتهای مختلف روی منابع، از متدهای HTTP استفاده میشود:
متد | عملکرد | مثال کاربردی |
---|---|---|
GET | دریافت اطلاعات | GET /users (همه کاربران) |
POST | ایجاد منبع جدید | POST /users (افزودن کاربر) |
PUT | بروزرسانی کامل منبع | PUT /users/12 (ویرایش کامل) |
PATCH | بروزرسانی جزئی | PATCH /users/12 (ویرایش جزئی) |
DELETE | حذف منبع | DELETE /users/12 (حذف کاربر) |
یک URL در REST باید ساده، خوانا و بازتابدهنده ساختار منابع باشد.
1- باید از اسم جمع برای منابع استفاده کرد:
/products ✅ /product ❌
2- مسیرها نشاندهنده سلسلهمراتب منطقی باشند:
/users/5/orders/3
3- هیچ فعلی در URL نوشته نشود. عملیات از طریق متد مشخص میشود:
/deleteUser ❌ → DELETE /users/5 ✅
RESTful API باید پاسخها را با استفاده از کدهای وضعیت HTTP ارائه دهد تا کلاینت بتواند نتیجه عملیات را تشخیص دهد:
کد | معنی | توضیح |
---|---|---|
200 | OK | درخواست با موفقیت انجام شد |
201 | Created | منبع با موفقیت ایجاد شد (مثلاً در POST) |
204 | No Content | عملیات موفق، اما دادهای برای بازگرداندن نیست |
400 | Bad Request | داده ورودی نامعتبر یا ناقص است |
401 | Unauthorized | نیاز به احراز هویت دارد |
403 | Forbidden | دسترسی غیرمجاز |
404 | Not Found | منبع پیدا نشد |
500 | Internal Server Error | خطای داخلی در سرور |
JSON چیست و چرا مهم است؟
JSON فرمتی متنی برای نمایش ساختار دادهها است که از آبجکتهای جاوااسکریپتی الهام گرفته و از دو نوع داده اصلی تشکیل شده است:
- Object: ساختار کلید-مقدار (مثل دیکشنری در پایتون)
- Array: لیستی از عناصر مرتبشده
مثال از یک JSON معتبر:
{
"id": 1,
"name": "Parsa Ghorbanian",
"skills": ["HTML", "CSS", "React"],
"isInstructor": true
}
تبدیل آبجکت به JSON:
const user = { name: "Parsa", age: 30 };
const json = JSON.stringify(user);
console.log(json); // {"name":"Parsa","age":30}
تبدیل JSON به آبجکت:
const json = '{"name":"Parsa","age":30}';
const obj = JSON.parse(json);
console.log(obj.name); // "Parsa"
خوب. حالا که با مفهوم api ها بصورت کلی آشنا شدیم، وقت آن است که بصورت عملی به سراغ کار با انها برویم. در نظر داشته باشید عموما با سه دستور ajax, fetch و کتابخانه axios این امر محقق میشود.
در زیر به ترتیب شروع به آموزش این مفاهیم با مثال های عملی کرده ایم. پس قدم به قدم خوانده و مثال ها را تمرین کنید.
استفاده از شی XMLHttpRequest
AJAX یک تکنیک در JavaScript است که به شما این امکان را میدهد که درخواستهای HTTP را بهصورت غیرهمزمان ارسال کنید، بدون اینکه صفحه وب مجدداً بارگذاری شود. این ویژگی بهویژه در تعاملات وبسایتهای مدرن (مانند بارگذاری دادهها بدون رفرش صفحه) بسیار مفید است.
با استفاده از شئ XMLHttpRequest در آجاکس میتونیم یک درخواست به سمت سرور ایجاد و ارسال کنیم. مانند مثال زیر:
<div id="Result"></div>
<p style="text-align:center;"> <button onclick="Load()">get</button>
</p>
<script>
function Load() {
const MyRequest = new XMLHttpRequest();
MyRequest.onload = function () {
document.getElementById("Result").innerHTML = this.responseText;
}
MyRequest.open("GET", "parsa.html");
MyRequest.send();
}
</script>
معرفی ajax
Asynchronous JavaScript And XML که سرکلمات همان ajax میباشد یک روش کلی و یا بعبارتی یک تکنولوژی در زبان جاوااسکریپت میباشد و اصلی ترین عملکرد و وظیفه آن ، ارتباط با سرور بدون رفرش شدن صفحه و بصورت asynchronous یا همان ناهمزمان میباشد.
پس کلیت کار بسیار آسان است. درخواستی به سمت سرور ارسال میشود، سرور آن را دریافت و تحلیل میکند. سپس پاسخی به آن ارسال میکند و تمام این موارد در پشت پرده و بدون رفرش صفحه انجام میشود.
ساده ترین و متداول ترین مثال این قسمت، سرچ گوگل است. همانطور که میبینید ، بدون آنکه صفحه رفرش شود، با هر کاراکتری که وارد میکنید ، نتایج تغییر و آپدیت میشود.
بعنوان مثال اول میتوانید یک فرم را با متد های AJAX ارسال نمایید.
<!DOCTYPE html>
<html>
<body data-rsssl=1>
<div class="row">
<input type="text" id="UserName" required placeholder="نام شما">
</div>
<div class="row">
<br>
<button type="button" onclick="MyLoad();">ارسال</button>
</div>
<br>
<p id="Result"></p>
<script>
function MyLoad() {
const xhttp = new XMLHttpRequest();
var MyInput = document.getElementById("UserName").value;
var result = document.getElementById("Result");
if (MyInput == "") {
result.innerHTML = "pooor kon!";
} else {
xhttp.onload = function () {
result.innerHTML = this.responseText;
}
xhttp.open("GET", "reg.php?UserName=" + MyInput + "");
xhttp.send();
}
}
</script>
آیا میدانید مدرسه پرنیان، دوره طراحی سایت حرفه ای بصورت حضوری و مجازی برگزار میکند؟
Asynchronous یا Synchronous
همزمان در جاوااسکریپت یعنی منتظر پاسخ بمان و تا زمانی که پاسخی دریافت نکردی ، هیچ کار دیگری انجام نده. اما نا همزمان به آن معناست که برعکس صحبت قبل عمل میکند و به کارهای دیگه هم رسیدگی خواهد کرد.
MyRequest.open( “Method” , “URL” , true or false);
اگه true بزاریم یعنی ناهمزمان ( Asynchronous ) و اگه false بزاریم یعنی همزمان ( Synchronous ) که بصورت دیفالت ، ناهمزمان هست.
onreadystatechange در آجاکس جاوااسکریپت
با استفاده از ویژگی onreadystatechange میتونیم یک تابع تعریف کنیم تا اگه وضعیت ویژگی readyState تغییر کرد بتونیم وضعیت درخواست ارسال شده بسمت سرور رو کنترل کنیم.
نام ویژگی | توضیح |
---|---|
readyState | کنترل وضعیت درخواست عدد ۰ یعنی درخواست هنوز آماده سازی نشده عدد ۱ یعنی اتصال با سرور برقرار شده عدد ۲ یعنی درخواست دریافت شده عدد ۳ یعنی پردازش روی درخواست انجام شده عدد ۴ یعنی درخواست بطور کامل دریافت و پاسخ آماده شده |
status | ۲۰۰ = OK ۲۰۳ = Non-Authoritative Information ۲۰۴ = No Content ۴۰۰ = Bad Request ۴۰۳ = Forbidden ۴۰۴ = Not Found ۵۰۰ = Internal Server Error ۵۰۲ = Bad Gateway ۵۰۳ = Service Unavailable |
statusText | برگشت وضعیت status بصورت رشته ( مثلا OK یا Not Found و… ) |
مثال کد زیر را ببینید:
<div id="Result"></div>
<p style="text-align:center;">
<button onclick="Load()">get</button>
</p>
<script>
function Load() {
const MyRequest = new XMLHttpRequest();
var Result = document.getElementById("Result");
MyRequest.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
Result.innerHTML = this.responseText;
}
};
MyRequest.open("GET", "parsa.html");
MyRequest.send();
}
</script>
برای ارسال داده های فرم با استفاده از متد POST باید اول با استفاده از setRequestHeader مشخص کنیم که نوع داده های ارسالی چه چیزی هستند ( مثلا داده های فرم ) ، بعدش در متد send باید داده هامون رو وارد کنیم.
function MyLoad(){
const xhttp = new XMLHttpRequest();
var MyInput = document.getElementById("UserName").value;
var result = document.getElementById("Result");
if(MyInput == ""){
result.innerHTML = "pooor kon!";
}else{
xhttp.onload = function(){
result.innerHTML = this.responseText;
}
xhttp.open("POST", "parsa.php");
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send("UserName="+MyInput+"");
}
}
برای قرار دادن لودینگ در حین بارگزاری صفحه میتوانید از کد زیر استفاده کنید:
<div id="Result"></div>
<button onclick="Load()">get</button>
<script>
function Load() {
const MyRequest = new XMLHttpRequest();
var Result = document.getElementById("Result");
MyRequest.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
Result.innerHTML = this.responseText;
} else {
Result.innerHTML = "<div><img src='img/loading.gif' width='70'></div>";
}
};
MyRequest.open("GET", "parsa.html");
MyRequest.send();
}
</script>
مثال : دو سلکت آپشن قرار دهید. یکی برای استان و یکی برای شهر. با کلیک بروی استان ، شهر های مربوطه در سلکت دوم فعال شود.
و اما fetch…
معرفی دستور Fetch
جاوا اسکریپت می تواند درخواست های شبکه را به سرور ارسال کند و اطلاعات جدید را هر زمان که نیاز باشد بارگیری کند.Fetch یک رابط مدرن است که به شما امکان می دهد؛ درخواست های HTTP را از مرورگرهای وب به سرورها ارسال کنید.
اگر با شیء XMLHttpRequest (XHR) کار کرده اید، Fetch API می تواند تمام وظایف را مانند شیء XHR انجام دهد.
باید بدانید ، Fetch با promise کار می کند، در صورتی که XHR با callback.
برای اطلاعات بیشتر در رابطه با promise لطفا این مقاله را مطالعه کنید.
تابع Promise بعد از اجرا شدن، یک پرامیس به ما برمیگردونه. این پرامیس شامل یک سری اطلاعات از نتیجه درخواست هست. نمونه کد زیر:
async function users() {
let response = await fetch('https://randomuser.me/api/?results=10');
console.log(response);
};
users();
و همچنین کد زیر :
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then((response) => {
console.log(response.status);
console.log(response.statusText);
console.log(response.ok);
console.log(response.url);
});
چیزی که توی body قرار میگیرد، شامل پاسخ اصلی هست که از سمت سرور آمده. دراین مرحله باید مشخص کنیم پاسخی که از سرور آمده را به چه فرمتی میخوهیم؟
response.text();
response.json();
response.formData();
response.blob();
response.arrayBuffer();
در مثال زیر خروجی JSON میخواهیم:
async function users() {
let response = await fetch('https://randomuser.me/api/?results=10');
let data = await response.json();
return data;
};
users().then(data => console.log(data));
متد blob
بدنهی پاسخ در قالب یک فایل (blob یا Binary Large Object) به تابع onFulfilled ارسال میشود. در نتیجه از متد blob معمولاً زمانی استفاده میشود که قصد داشته باشیم یک فایل را به صورت کامل دریافت کرده و در صفحهی وب درج کنیم (مانند یک فایل JPEG).
const myImage = document.querySelector('img');
const p = fetch('imgcode.....jpg');
p.then(response => response.blob())
.then(function (myBlob) {
let fileURL = URL.createObjectURL(myBlob);
myImage.src = fileURL;
});
در این قسمت از مقاله آموزش کامل fetch و ajax در جاوااسکریپت ، به حالت های مختلف شی میپردازیم:
- Response.ok : این ویژگی یک Boolean برمی گرداند که نشان می دهد آیا درخواست موفقیت آمیز بوده است یا خیر.
- Response.status : این ویژگی کد وضعیت پاسخ را برمی گرداند (به عنوان مثال عدد ۲۰۰، برای یک درخواست موفق).
- Response.url : این ویژگی URL درخواست را برمی گرداند. معمولاً هنگام ارسال درخواست، این مورد را دارید.
- ()Response.clone : یک کلون از شی Response ایجاد می کند.
- ()Response.text : دادههای موجود در پاسخ را به صورت متن برمیگرداند، که هنگام بازیابی HTML مفید است.
- ()Response.json: دادههای موجود در پاسخ را بهعنوان یک شیء JSON معتبر برمیگرداند.
- ()Response.blob : برای داده هایی که به شکل مرجع فایل هستند؛ (مانند URL تصویر) مفید است.
کد زیر را در نظر بگیرید:
fetch('https://jsonplaceholder.typicode.com/posts')
.then(function (response) {
// if (response.status !== 200)
if (!response.ok) {
console.log('Erroradam bash! : ' + response.status);
return;
}
response.json().then(function (data) {
document.write(data);
console.log(data);
});
})
.catch(function (err) {
document.write('Error: ' + err);
});
در پارامتر دوم تابع fetch میتونیم نوع متد رو مشخص کنیم، data پاس بدیم و هدر ست کنیم.
هر گاه اطلاعاتی را از سرور نیاز داشته باشیم باید یک درخواست به آن بزنیم و پاسخ را از سمت سرور دریافت کنیم. بر این درخواست و پاسخ قوانینی حکم فرماست که به آن پروتکل (Http Protocol) گفته می شود.
هدرهایی که توسط سرور در پاسخ HTTP قرار داده میشوند از طریق خاصیت headers قابل دسترسی هستند. در واقع خاصیت headers یک نمونه از شئ Headers میباشد.
این شئ دارای تعدادی متد است که با استفاده از آنها امکان دسترسی به هدرهای ذخیره شده در این شئ، و همچنین اضافه کردن هدرهای جدید وجود دارد.
جالب است بدانید خود Header به تنهایی یک شی است که میتواند مقادیری را در HTTP ذخیره کند. مانند مثال زیر:
const myHeaders = new Headers()
myHeaders.set('name', 'arsam');
document.write(myHeaders.get('name') + '<hr>')
نمونه ست کردن هدر به کمک شی XMLHttpRequest :
let request = new XMLHttpRequest();
request.open('GET', document.location, false);
request.setRequestHeader('Accept', 'text / plain');
request.setRequestHeader('Content-Type', 'text / plain');
request.setRequestHeader('Content-Language', 'fa-ir');
request.send(null);
console.log(request.getAllResponseHeaders().toLowerCase());
نمونه دیگری از ست کردن هدر در صفحه:
const content = 'Hello World';
const myHeaders = new Headers();
myHeaders.append('Content-Type', 'text/plain');
myHeaders.append('name', 'arsam');
myHeaders.append('Content-Length', content.length.toString());
console.log(myHeaders.has('Content-Type')); // true
console.log(myHeaders.has('Set-Cookie')); // false
console.log(myHeaders.get('Content-Type'));
myHeaders.set('Content-Type', 'text/html');
console.log(myHeaders.get('Content-Type')); // 11
console.log(myHeaders.get('name'));
myHeaders.append('X-Custom-Header', 'AnotherValue');
console.log(myHeaders.get('Content-Length')); // 11
console.log(myHeaders.get('X-Custom-Header')); // ['ProcessThisImmediately', 'AnotherValue']
myHeaders.delete('X-Custom-Header');
console.log(myHeaders.get('X-Custom-Header')); // null
برای ارسال درخواست Fetch با Headers، یک شی با ویژگی متد و هدر ارسال می کنیم:
- get(name) : در صورتی که هدر name وجود داشته باشد مقدار آن را بازمیگرداند. در غیر این صورت مقدار null را بازمیگرداند.
- set(name , value) : در صورتی که هدر name وجود داشته باشد مقدار آن را به value تغییر میدهد. در غیر این صورت هدر name را با مقدار value ایجاد میکند.
- delete(name) : در صورتی که هدر name وجود داشته باشد آن را حذف میکند.
- append(name , value) : در صورتی که هدر name وجود داشته باشد مقدار value را به مقدار قبلی الحاق میکند. در غیر این صورت هدر name را با مقدار value ایجاد میکند.
- has(name) : در صورتی که هدر name وجود داشته باشد مقدار true را بازمیگرداند. در غیر این صورت مقدار false را بازمیگرداند.
مانند کد زیر :
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then((response) => {
console.log(response.headers.get('Content-Type'));
// "application/json; charset=utf-8"
console.log(response.headers.get('Date'));
// null
console.log(response.headers.has('Content-Type'));
// true
console.log(response.headers.has('Date'));
// false });
درخواست های پیشرفته
به عنوان مثال در حالت پیشفرض تمام درخواستها با روش GET ارسال میشوند. اما ممکن است بخواهیم درخواستی را با روش POST ارسال کنیم.
همچنین در حالت پیشفرض تمام هدرهای HTTP توسط مرورگر تنظیم میشوند. اما ممکن است بخواهیم هدرهای دیگری را به درخواست HTTP اضافه کنیم و یا تغییراتی در هدرهای موجود ایجاد کنیم.
const req = new Request('https://example.com' , {
method: 'POST',
mode: 'cors',
redirect: 'follow',
....
});
خاصیت method
روش ارسال درخواست را تعیین میکند. (معمولاً GET یا POST)
خاصیت headers
یک شئ از نوع Headers است که هدرهای ارسال شونده به سرور را تعیین میکند.
خاصیت body
بدنهی درخواست در این خاصیت تعیین میشود. مقدار این خاصیت میتواند یک رشتهی ساده، یک رشتهی JSON، یک شئ FormData و … باشد.
خاصیت cache
حتماً میدانید که مرورگرها دارای بخشی به نام حافظهی کش (Cache) هستند. بسیاری از منابعی که توسط یک مرورگر دریافت میشوند (مانند صفحات وب، فایلهای CSS یا فایلهای PNG) در این حافظه ذخیره میشوند.
مرورگرها در حالت پیشفرض قبل از ارسال یک درخواست HTTP برای دریافت یک منبع، معمولاً حافظهی کش را بررسی میکنند.
در صورتی که منبع مورد نظر از قبل در حافظهی کش ذخیره شده باشد و تاریخ انقضای آن نیز نگذشته باشد. مرورگر از همان نسخهی ذخیره شده استفاده میکند و عملاً هیچ درخواستی به سرور ارسال نمیشود.
خاصیت mode
در حالت پیشفرض امکان ارسال درخواستهای Ajax به هر منبعی وجود دارد. هرچند پس از دریافت پاسخ، فقط در دو حالت میتوان از پاسخ دریافت شده استفاده کرد.
یا باید منبع صفحهی ارسال کننده با منبع درخواست شده یکسان باشد (سیاست SOP). یا اینکه سیاست SOP توسط سرور غیر فعال شده باشد. یعنی سیاست SOP پس از دریافت پاسخ از سرور اعمال میشود و در ارسال درخواست نقشی ندارد.
- basic : یعنی آدرس درخواست شده با آدرس صفحهی درخواست کننده در یک منبع قرار دارد.
- cors : یعنی آدرس درخواست شده با آدرس صفحهی درخواست کننده در یک منبع قرار ندارد. اما به دلیل غیر فعال بودن سیاست SOP، امکان استفاده از پاسخ دریافت شده وجود دارد.
- opaque : یعنی آدرس درخواست شده با آدرس صفحهی درخواست کننده در یک منبع قرار ندارد. و به دلیل فعال بودن سیاست SOP، امکان استفاده از پاسخ دریافت شده وجود ندارد.
- error : یعنی ارسال درخواست با خطا مواجه شده است و هیچ اطلاعات مفیدی دریافت نشده است. در این حالت مقدار خاصیت status برابر با صفر است.
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
body: JSON.stringify({
title: 'foo',
body: 'bar',
userId: 1,
}),
headers: {
'Content-type': 'application/json; charset=UTF-8',
},
})
.then((response) => response.json())
.then((json) => console.log(json));
یا در مثالی دیگر :
const url = 'https://api.oxforddictionaries.com:443/api/v1/entries/en/'
let searchString = 'word'
fetch(url + searchString, {
method: 'get',
headers: {
"Accept": "application/json",
"app_id": "vb805en4",
"app_key": "bmd3a11b2951277c3a04ddbbnaec0216"
}
})
.then(function (response) {
console.log(response.json());
})
مهمترین مثال این بخش ترکیب ارسال هدر و کد های سرور (سمت php) هست که در این فرم، با ارسال هدر میتوانیم در سمت سرور هدر مورد نظر را دریافت کرده و با انجام فعل و انفعال مورد نظر خود، نتیجه را به کاربران نشان میدهیم.
دو صفحه درست کنید.index.html و fetch.php
این کد ها را در صفحه index.html وارد کنید:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body data-rsssl=1>
<h1>Index HTML</h1>
<form action="#" onsubmit="submitHandler()">
<input type="text" name=name>
<button type="submit">Send Request</button>
</form>
<**script>
function submitHandler() {
event.preventDefault();
fetch('fetch.php', {
method: 'post',
headers:{
"x-auth-test": "parsaKeyyyyyyyyyyyyyyyyy",
"name" : "parsa"
}
})
.then(result => result.text())
.then(result => {
document.write(result)
})
}
</**script>
</body>
</html>
کدهای زیر را در صفحه fetch.php وارد کنید:
<?php
function getRequestHeaders() {
$headers = array();
foreach($_SERVER as $key => $value) {
if (substr($key, 0, 5) <> 'HTTP_') {
continue;
}
$header = str_replace(' ', '-', ucwords(str_replace('_', ' ', strtolower(substr($key, 5)))));
$headers[$header] = $value;
}
return $headers;
}
$headers = getRequestHeaders();
foreach ($headers as $header => $value) {
echo "$header: $value <br />\n";
}
یا کد زیر:
<?php
if(!isset($_SERVER['HTTP_X_AUTH_TEST'])) {
echo 'Key is not exist';
return;
}
$headerStringValue = $_SERVER['HTTP_X_AUTH_TEST'];
echo "salaaammmmm $headerStringValue";
?>
با مثال بالا، هدر را در سمت سرور دریافت کرده و بعد از دیتاماینینگ، جواب مورد نظر را در صفحه چاپ میکند.
در مثال دیگری از دوست عزیزمان fetch میتوانیم با تابع AbortController حالت timeout برای درخواست خود ایجاد نماییم.
AbortController
ابزاریه برای کنترل یا لغو یک عملیات async، مثل fetch
.
signal
رو به fetch
میدیم تا بدونه میتونه متوقف بشه.
وقتی controller.abort()
رو صدا بزنی، اون fetch
متوقف میشه.
اگه درخواست قبل از اتمام لغو بشه، catch
اجرا شده و خطایی با نام AbortError
دریافت میکنیم.
const controller = new AbortController(); // ایجاد کنترلر
const signal = controller.signal; // گرفتن سیگنال از کنترلر
// شروع درخواست fetch
fetch("https://jsonplaceholder.typicode.com/posts", { signal })
.then(response => response.json())
.then(data => console.log("دیتا دریافت شد:", data))
.catch(error => {
if (error.name === "AbortError") {
console.log("درخواست متوقف شد!");
} else {
console.error("خطای دیگر:", error);
}
});
// لغو درخواست بعد از 2 ثانیه
setTimeout(() => {
controller.abort(); // متوقف کردن درخواست
}, 2000);
درخواست های پیشرفته و ارسال و دریافت توکن. اگر بطور مثال چنین درخواستی به شما شد:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6...
در واقع هدر (header) یک درخواست HTTP هست که برای احراز هویت (Authentication) به سرور فرستاده میشه.
اجزای این عبارت:
بخش | توضیح |
---|---|
Authorization: | اسم هدر (Header) هست که به سرور میگه: «این درخواست حاوی اطلاعات احراز هویت هست». |
Bearer | یعنی نوع توکن ما از نوع «Bearer Token» هست. این یعنی توکن باید همراه درخواست فرستاده بشه تا اجازه دسترسی داده بشه. |
eyJhbGciOiJIUzI1NiIsInR5cCI6... | این همون توکن JWT یا کلید دسترسی شماست. به زبان ساده: یه کد رمزگذاریشده است که داخلش اطلاعاتی مثل userId , role , exp (زمان انقضا) هست. |
به مثال زیر توجه کنید. با کلیک روی باتن اول توکن دریافت شده و با کلیک روی باتن دوم، درخواست همراه توکن ارسال میشود.
<button onclick="login()">Login</button>
<button onclick="accessProtected()">Access Protected</button>
<script>
let token = '';
function login() {
fetch('http://localhost:3000/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
})
.then(res => res.json())
.then(data => {
token = data.token;
console.log('توکن دریافت شد:', token);
});
}
function accessProtected() {
fetch('http://localhost:3000/protected', {
headers: {
'Authorization': 'Bearer ' + token
}
})
.then(res => res.json())
.then(data => console.log('پاسخ سرور:', data))
.catch(err => console.error('خطا:', err));
}
</script>
بهجز Bearer
چه مقادیر دیگری در هدر Authorization داریم؟
هدر Authorization
فقط محدود به Bearer
نیست. این هدر بسته به نوع احراز هویت، میتواند مقادیر مختلفی داشته باشد. در اینجا رایجترین آنها را معرفی میکنیم:
نوع | مقدار در Authorization | توضیح |
---|---|---|
Basic Authentication | Authorization: Basic <base64encoded> | اطلاعات کاربری (username:password) به صورت Base64 رمزگذاری شده و ارسال میشود. بسیار ساده است اما امنیت کمی دارد مگر اینکه از HTTPS استفاده شود. |
Bearer Token | Authorization: Bearer <token> | توکن (معمولاً JWT) به عنوان کلید احراز هویت استفاده میشود. رایجترین روش در REST APIهاست. |
API Key (سفارشی) | Authorization: Apikey <your_api_key> یا در Query String/Headers | بعضی از APIها از کلیدهای خاص خود استفاده میکنند. استاندارد جهانی ندارد اما رایج است. |
Digest Authentication | Authorization: Digest ... | پیچیدهتر از Basic است. با استفاده از nonce، hash و پارامترهای امنیتی بیشتر. در برخی سیستمهای قدیمیتر استفاده میشود. |
OAuth1.0 | Authorization: OAuth ... | الگویی قدیمیتر از OAuth2 است که شامل چند پارامتر مختلف درون هدر Authorization میشود. |
هدرهای رایج در HTTP Request (درخواست سمت کاربر)
نام هدر | کاربرد | مثال |
---|---|---|
Authorization | ارسال اطلاعات احراز هویت مثل توکن یا اطلاعات کاربری | Authorization: Bearer eyJhbGci... |
Content-Type | مشخص میکند که نوع داده ارسالی چیست | Content-Type: application/json یا application/x-www-form-urlencoded |
Accept | مشخص میکند که کاربر انتظار چه نوع محتوایی دارد | Accept: application/json یا Accept: text/html |
User-Agent | مشخصات مرورگر یا کلاینت ارسالکننده درخواست | User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) |
Referer | آدرس صفحهای که کاربر از آن آمده | Referer: https://example.com/home |
Host | آدرس دامنهای که درخواست به آن ارسال شده | Host: api.example.com |
Cookie | ارسال کوکیهای ذخیرهشده در مرورگر به سرور | Cookie: session_id=abc123; token=xyz456 |
X-Requested-With | نشان میدهد درخواست از طریق Ajax ارسال شده | X-Requested-With: XMLHttpRequest |
Origin | دامنهای که درخواست را ارسال کرده (در CORS مهم است) | Origin: https://myapp.com |
Cache-Control | نحوه کش شدن اطلاعات توسط مرورگر یا پروکسی را تعیین میکند | Cache-Control: no-cache |
Accept-Language | زبانهای قابل قبول برای پاسخ سرور | Accept-Language: fa, en-US;q=0.9 |
احتمالا در هنگام سر و کله زدن با api های پیشرفته و یا در محیط کار، چنین مقادیری را بدون هیچ توضیح اضافه به شما بدهند و شما باید آن را به کد تبدیل کنید:
curl -X 'GET' \
'https://api.one-api.ir/digikala/v1/home/' \
-H 'accept: application/json' \
-H 'one-api-token: 1'
1. curl
این دستور از ابزار curl
استفاده میکند که برای ارسال درخواست HTTP از طریق خط فرمان بهکار میرود. ابزار curl
یک ابزار متنباز، قدرتمند و بسیار کاربردی در تست و دیباگ APIها است.
2. -X 'GET'
این گزینه مشخص میکند که نوع درخواست HTTP، از نوع GET
است.
در
GET
، دادهای به سرور ارسال نمیشود، بلکه صرفاً اطلاعات از سرور دریافت میشود.
3. 'https://api.one-api.ir/digikala/v1/home/'
این آدرس URL همان Endpoint مربوط به API است. در این مثال:
- دامنه اصلی:
api.one-api.ir
- مسیر (Path):
/digikala/v1/home/
- نسخه API:
v1
- عملکرد API: دریافت اطلاعات صفحه اصلی دیجیکالا
4. -H 'accept: application/json'
هدر HTTP به سرور اعلام میکند که پاسخ را در قالب JSON میخواهیم.
Accept
یکی از مهمترین هدرهاست که مشخص میکند نوع داده مورد انتظار از سمت سرور چیست.
5. -H 'one-api-token: 1'
این هدر، توکنی به نام one-api-token
با مقدار 1
به سرور ارسال میکند.
در این API خاص، برای احراز هویت یا دسترسی، لازم است که توکن معتبر به صورت هدر ارسال شود.
هر API ممکن است از هدر خاصی برای شناسایی کاربر یا سطح دسترسی استفاده کند.
یا در مثالی دیگر:
Curl
curl -X 'GET' \
'https://api.one-api.ir/digikala/v1/search/?q=mobile&page=10' \
-H 'accept: application/json' \
-H 'one-api-token: 1'
توضیح این که
URL: جستجو در API دیجیکالا با کوئری mobile
در صفحه ۱۰.
method: “GET”: نوع درخواست، خواندنی است.
Headers:
accept: application/json
: انتظار داریم پاسخ در قالب JSON باشد.one-api-token: 1
: برای احراز هویت یا دسترسی به API.
کد جاوا اسکریپت آن میشود:
fetch("https://api.one-api.ir/digikala/v1/search/?q=mobile&page=10", {
method: "GET",
headers: {
"accept": "application/json",
"one-api-token": "1"
}
})
.then(response => {
if (!response.ok) throw new Error("Request failed");
return response.json();
})
.then(data => {
console.log("Search Result:", data);
})
.catch(error => {
console.error("Error:", error);
});
در انتها میتوانید با دانلود فایل زیر، دو فایل json حجیم و تقریبا واقعی از صفحات فروشگاه آنلاین دیجیکالا را مشاهده کرده و برای تمرین از آن استفاده کنید.
امیدواریم از این مقاله نهایت استفاده را برده باشید و آن را با دوستانتان به اشتراک بگذارید. تیم تولید محتوای مدرسه اینترنتی پرنیان این مقاله را تهیه کرده است.
درباره مدیریت
شما در حال مطالعه یکی از مقالات آموزشی وبلاگ پرنیان بودید. اگر برایتان مفید بود آن را با دوستانتان به اشتراک بگذارید. من پارسا قربانیان و اینجا مدرسه فرانت اند پرنیان، میخواهیم در یک معامله برد برد، با هم به آرزوهایمان برسیم..
نوشته های بیشتر از مدیریتمطالب زیر را حتما مطالعه کنید
19 دیدگاه
به گفتگوی ما بپیوندید و دیدگاه خود را با ما در میان بگذارید.
kheili allli va kamel bod ostad parsa
ممنون
بسیار مقاله مفیدی بود هرچی بگم از API و fetch از جذابیت هاش کم نمیشه D:
بله واقعا جذابه
مرسی از مقاله مفید
واقعا عالیه✔. خسته نباشین💖
ممنون از شما
vaghan maghale khubie makhsosan mesal has ke baes mishe behtr yad begire adam
خواهش میکنم
چقدر خوبه که مثال زدید.مرسی
خواهش میکنم
مقاله کاملا کاربردی و عالی بود . خیلی ممنون از سایت خوبتون
ممنون از نظر شما
واقعا دست مریزاد
از این کاملا تر نیست تو نت
حتی php روهم نوشتی
خواهش میکنم
سلام- خیلی کامله- مرررررررررررسی واقعن
سلام
خوشحالیم که استفاده کردید
خیلی عاااااااااااالی- ممنون استاد از شما
سپاس از شما