طريقة HTTP QUERY هي طريقة طلب جديدة، مُعرَّفة في RFC 10008 (يونيو 2026)، تُرسل استعلامًا في جسم الطلب وتكون آمنة وidempotent في آنٍ واحد. فكّر فيها كأنها GET مع جسم: تحصل على مساحة POST للفلاتر المعقّدة وضمانات GET للتخزين المؤقت وإعادة المحاولة التلقائية.
إذا سبق لك أن حشرت فلترًا بحجم 3 كيلوبايت في عنوان URL، أو أرسلت بحثًا للقراءة فقط عبر POST ورأيت نظام التخزين المؤقت ومنطق إعادة المحاولة يتجاهلانه، فإن QUERY هي الحل. يغطي هذا الدليل ما يقوله المواصفة، وكيف تقارن QUERY مع GET وPOST، وما يدعمها اليوم، وكيفية اختبار نقطة نهاية QUERY باستخدام وكيل البرمجة الخاص بك.
ما هي طريقة HTTP QUERY؟
QUERY هي طريقة HTTP تطلب من المورد الهدف تشغيل الاستعلام الموصوف في محتوى الطلب وإرجاع النتيجة. يحدّد جسم الطلب وContent-Type الخاص به الاستعلام. الطريقة آمنة (لا يتوقع العميل أي تغيير في الحالة) وidempotent (تكرارها له نفس التأثير)، لذا يمكن للعملاء والوسطاء وذاكرات التخزين المؤقت إعادة المحاولة والتخزين المؤقت لها مثل GET.
المواصفة هي RFC 10008، «طريقة HTTP QUERY»، وهي معيار مقترح نُشر في يونيو 2026 بواسطة Julian Reschke (greenbytes) وJames M. Snell (Cloudflare) وMike Bishop (Akamai). أضافتها IANA إلى سجل طرق HTTP بوصف «آمنة: نعم، idempotent: نعم»، بجوار طريقة SEARCH من حقبة WebDAV التي كادت أن تصبح هي نفسها.
يبدو طلب QUERY هكذا:
QUERY /contacts HTTP/1.1
Host: example.org
Content-Type: application/x-www-form-urlencoded
Accept: application/json
select=surname,givenname,email&limit=10&match=%22email=*@example.*%22
يرد الخادم بـ200 OK والنتيجة في الجسم.
لماذا لم يكن GET وPOST كافيين
كان لديك خيارَان لقراءة معقدة قبل QUERY، وكلاهما به ثغرات.
GET يضع كل شيء في عنوان URL. تسرد RFC 10008 أربع مشاكل في ذلك:
- حدود الحجم غير معروفة مسبقًا، لأن الطلب يعبر أنظمة عديدة. RFC 9110 توصي فقط بأن يدعم المرسلون والمستقبلون 8,000 أوكتت على الأقل.
- ترميز البيانات المهيكلة في URI صالح مضيعة للموارد.
- يُسجَّل في السجلات ويُضاف إلى المفضلة في URIs أكثر بكثير من أجسام الطلبات، وهو ما يمثل مشكلة خصوصية للفلاتر الحساسة.
- كل مجموعة من مدخلات الاستعلام تصبح موردًا مستقلًا بذاته.
GET مع جسم ليس الحل أيضًا. تقول RFC 9110 إن المحتوى في طلب GET ليس له دلالات محددة. بعض الخوادم تقرأه، وبعضها يتجاهله، وبعض الوسطاء يرفضون الطلب. لا يمكنك الاعتماد عليه عبر المسار.
POST يعمل، لكنه يكذب بشأن النية. بحث POST يعمل بشكل جيد، لكن لا شيء يخبر العميل أو ذاكرة التخزين المؤقت أو الوسيط أو مكتبة إعادة المحاولة بأن العملية للقراءة فقط. لذا تتجاهله ذاكرات التخزين المؤقت ولا يعيد العملاء المحاولة بعد انقطاع الاتصال. إذا اضطررت لإضافة مفتاح idempotency على قراءة خالصة فقط لجعل إعادة المحاولة آمنة، فقد شعرت بهذا.
تحافظ QUERY على جسم POST وتضيف ضمانات GET.
QUERY مقابل GET مقابل POST
إليك المقارنة، بناءً على الجدول 1 من RFC 10008:
| الخاصية | GET | QUERY | POST |
|---|---|---|---|
| آمنة | نعم | نعم | قد لا تكون |
| Idempotent | نعم | نعم | قد لا تكون |
| جسم الطلب | لا دلالات محددة | متوقع، يحدّد الاستعلام | متوقع |
| URI للاستعلام نفسه | نعم، بحكم التعريف | اختياري، عبر Location |
لا |
| URI للنتيجة | اختياري، عبر Content-Location |
اختياري، عبر Content-Location |
اختياري، عبر Content-Location |
| قابلة للتخزين المؤقت | نعم | نعم، الجسم جزء من مفتاح ذاكرة التخزين المؤقت | فقط لطلبات GET أو HEAD لاحقة |
| CORS preflight من المتصفحات | ليس للطلبات البسيطة | دائمًا | ليس للطلبات البسيطة |
النسخة القصيرة: استخدم GET عندما يتسع الاستعلام بشكل مريح في عنوان URL، وQUERY عندما لا يتسع، وPOST فقط عندما يغيّر الطلب الحالة. لمراجعة الطرق الكلاسيكية، راجع أدلتنا حول طرق HTTP وGET مقابل POST.
ما تحدده RFC 10008
Content-Type إلزامي
يجب على الخوادم أن تُفشل طلب QUERY الذي يكون فيه Content-Type مفقودًا أو غير متوافق مع الجسم. توصي RFC برموز الحالة التالية:
- 400 Bad Request: لا يوجد نوع وسائط، أو نوع لا يطابق المحتوى. لا يستطيع الخوادم تخمين الجسم وتجاوزه.
- 415 Unsupported Media Type: المورد لا يدعم تنسيق الاستعلام هذا.
- 422 Unprocessable Content: التنسيق سليم لكن الاستعلام لا يمكن تشغيله، كما هو الحال في SQL الذي يشير إلى جدول غير موجود.
- 406 Not Acceptable: طلب العميل نوع استجابة لا يستطيع المورد إنتاجه.
Location وContent-Location
يمكن للخادم إرجاع رأسين اختياريين يحولان QUERY إلى شيء يمكنك GET لاحقًا:
Content-Locationيشير إلى النتيجة المخزنة لهذا التشغيل المحدد. قد تكون مؤقتة.Locationيشير إلى الاستعلام المخزن نفسه. طلب GET عليه يعيد تشغيل الاستعلام ببيانات حديثة، دون إعادة إرسال الجسم.
تقترح RFC أن يتحول العملاء إلى GET على URI الخاص بـLocation للطلبات المتكررة، لأن التخزين المؤقت لـGET أبسط. إذا أعدت أيًا من الرأسين لاستعلام يحتوي على بيانات حساسة، فينبغي ألا يحتوي URI على الأجزاء الحساسة من الجسم الأصلي.
التخزين المؤقت
استجابات QUERY قابلة للتخزين المؤقت. يجب أن يتضمن مفتاح ذاكرة التخزين المؤقت محتوى الطلب والبيانات الوصفية المرتبطة به مثل نوع الوسائط. يجوز لذاكرات التخزين المؤقت تطبيع الجسم أولًا، على سبيل المثال بإزالة ترميز المحتوى أو تطبيع JSON لنوع +json، للحصول على المزيد من الإصابات. تحذر المواصفة من أن التطبيع السيئ يمكن أن يُرجع استجابة خاطئة، لذا توقع أن تكون CDNs حذرة هنا.
عمليات إعادة التوجيه
يعني 301 أو 302 أو 307 أو 308 «أرسل نفس QUERY إلى URI الجديد». على عكس POST، يجب ألا يُعاد كتابة QUERY إلى GET عند 301 أو 302. يعني 303 See Other «اجلب النتيجة باستخدام GET على هذا URI».
رأس Accept-Query
Accept-Query هو رأس استجابة جديد يعلن دعم QUERY وتنسيقات الاستعلام التي يقبلها المورد. إنه قائمة حقل مهيكل، لذا حلّله كذلك:
Accept-Query: "application/jsonpath", application/sql;charset="UTF-8"
يمكن للعملاء أيضًا اكتشاف الدعم باستخدام OPTIONS وقراءة رأس Allow، أو ببساطة إرسال QUERY ومعالجة 405 Method Not Allowed.
ما الأدوات التي تدعم QUERY اليوم؟
الدعم غير متساوٍ، لذا اختبر حزمتك الخاصة. إليك ما أكدناه في 28 أكتوبر 2026:
| الأداة | النتيجة |
|---|---|
خادم http في Node.js 24 |
http.METHODS يتضمن QUERY؛ استقبل خادم بسيط الطريقة والجسم |
fetch في Node.js 24 |
أرسل QUERY بجسم JSON |
| curl 8.7 | curl -X QUERY مع -d أرسل الطريقة والجسم |
http.client في Python 3.14 |
أرسل QUERY بجسم |
| OpenAPI 3.2 | كائن Path Item يحتوي على حقل query لعمليات QUERY |
| Apidog CLI 2.2.12 | مخطط endpoint-create يقبل "method": "query" |
إليك استدعاء curl الذي استخدمناه ضد خادم Node محلي:
curl -i -X QUERY http://localhost:3000/products \
-H "Content-Type: application/json" \
-d '{"q":"running shoe","limit":2}'
معيار Fetch يحظر فقط وجود جسم في GET وHEAD، لذا يمكن للمتصفحات إرسال QUERY بجسم. لكن QUERY ليست ضمن قائمة الطرق المسموح بها تلقائيًا في CORS، لذا كل طلب QUERY عبر الأصل يُشغّل preflight. يجب أن يُدرج خادمك QUERY في Access-Control-Allow-Methods.
الفجوات في منتصف الشبكة: الوسطاء العكسيون وبوابات API وجدران الحماية WAFs وشبكات توصيل المحتوى CDNs التي تسمح بقائمة محددة من الطرق أو لا تربط ذاكرتها المؤقتة بالجسم. تحقق من كل قفزة قبل الإطلاق. يشير نشرة APIs You Won’t Hate إلى أن العديد من أطر الويب تتعامل مع QUERY مباشرة أو عبر توجيه الطرق المخصصة.
كيف تتبنى QUERY دون كسر العملاء
لا يجب أن تزيل نقاط نهاية بحث POST دفعة واحدة.
- أضف QUERY بجوار مسار POST. وجّه كليهما إلى نفس المعالج. يستخدم العملاء الجدد QUERY؛ ويستمر القدامى في العمل.
- أعلن عنه. أعد
Accept-Queryعلى المورد وأدرجQUERYفيAllowعلى استجاباتOPTIONSو405. - فرض Content-Type. أعد 400 أو 415 كما توصي RFC، و422 للاستعلامات التي تُحلَّل لكن لا يمكن تشغيلها.
- التراجع عند 405 أو 501. يجب على العملاء إعادة إرسال نفس الجسم كـPOST عندما يرفض وسيط طلب QUERY.
- أصلح CORS. أضف
QUERYإلىAccess-Control-Allow-Methodsلعملاء المتصفح. - قرر بشأن التخزين المؤقت. مكّن التخزين المؤقت المشترك فقط عندما تربط ذاكرتك المؤقتة بالجسم. خلاف ذلك أعد URI
Locationودع العملاء يطلبونه بـGET. - وثّق ذلك. في OpenAPI 3.2، عرّف العملية تحت
query:على عنصر المسار:
openapi: 3.2.0
paths:
/products:
query:
summary: Search products
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ProductQuery'
responses:
'200':
description: Matching products
يمكن للفلاتر القصيرة والبسيطة أن تبقى كـسلاسل استعلام على GET. تقول RFC 10008 نفسها إنه إذا كان استعلامك بهذا القِصر، فربما GET هو الخيار الأفضل.
دع وكيل البرمجة الخاص بك يختبر نقطة نهاية QUERY باستخدام Apidog CLI
الطريقة الجديدة تعني التحقق من المسار السعيد، وكل رمز خطأ، ومسار التراجع. سلّم ذلك إلى Claude Code أو Codex أو Cursor ودعه يقود Apidog CLI.
ثبّت CLI، سجّل الدخول، وأضف مهارة Apidog إلى وكيلك:
npm install -g apidog-cli@latest
apidog login --with-token <YOUR_TOKEN>
npx -y skills add https://apidog.com # pick your agent when prompted
ثم أعطِ وكيلك طلبًا واحدًا:
In Apidog project <projectId>, add a QUERY /products endpoint that takes a
JSON body {q, limit}. Create test cases that assert 200 with an array for a
valid body, 415 for Content-Type text/plain, and 400 with no Content-Type.
Run them against the staging environment and summarize any failures.
يقرأ الوكيل كل مخطط، ويتحقق من صحة حمولته وبعدها فقط يكتب:
apidog cli-schema get endpoint-create
apidog cli-schema validate endpoint-create --file endpoint.json
apidog endpoint create --project <projectId> --file endpoint.json
apidog cli-schema get test-case-create
apidog cli-schema validate test-case-create --file case.json
apidog test-case create --project <projectId> --file case.json
apidog run --test-case <caseId> --project <projectId> -e <envId> -r cli,json
ملف endpoint.json الذي يكتبه يضبط "method": "query"، وهو ما يدرجه مخطط endpoint-create في CLI بجانب get وpost وطرق WebDAV. أضف --upload-report لرؤية التشغيل في تطبيق Apidog. نفس أمر apidog run مع -r junit يندرج في CI؛ راجع كيفية تشغيل اختبارات API في CI باستخدام apidog run وكيفية استخدام Apidog CLI في Claude Code. تغطي خطة Apidog المجانية حتى 4 مستخدمين.
الأسئلة الشائعة
هل طريقة HTTP QUERY معيار رسمي؟ نعم. RFC 10008 هي RFC من مسار المعايير، معيار مقترح نُشر في يونيو 2026، وتدرجها IANA في سجل طرق HTTP كآمنة وidempotent.
هل QUERY مجرد GET بجسم؟ قريب، لكنها محددة بشكل أفضل. تمنح RFC 9110 جسم GET بلا دلالات، لذا يمكن للوسطاء تجاهله أو رفضه. تجعل QUERY الجسم هو الاستعلام، وتتطلب Content-Type، وتضم الجسم في مفتاح ذاكرة التخزين المؤقت.
متى يجب أن أستخدم QUERY بدلًا من POST؟ استخدم QUERY لأي بحث أو فلتر للقراءة فقط يكون كبيرًا أو حساسًا جدًا لعنوان URL. احتفظ بـPOST للطلبات التي تنشئ أو تغيّر شيئًا.
هل يمكن للمتصفحات إرسال طلبات QUERY؟ نعم، عبر fetch بطريقة مخصصة. تتطلب طلبات QUERY عبر الأصل دائمًا CORS preflight، لذا يجب أن يسمح خادمك بالطريقة.
هل يتم تخزين استجابات QUERY مؤقتًا؟ يمكن أن تكون كذلك. يجب أن تتضمن ذاكرات التخزين المؤقت جسم الطلب وبياناته الوصفية في مفتاح ذاكرة التخزين المؤقت. العديد من CDNs والوسطاء لا يفعلون ذلك بعد، لذا تحقق من شبكتك أو أعد URI Location يمكن للعملاء طلبه بـGET.
هل يدعم OpenAPI طريقة QUERY؟ يضيف OpenAPI 3.2 حقل query إلى كائن Path Item لعمليات QUERY، بحيث يمكنك توثيقها دون إضافات.
