
نسخة Fork من وحدة send module للتعامل مع CVE-2017-20165
Send هي مكتبة لدفق الملفات من نظام الملفات كاستجابة HTTP تدعم الاستجابات الجزئية (النطاقات)، والتفاوض المشروط بـ GET (If-Match، If-Unmodified-Since، If-None-Match، If-Modified-Since)، وتغطية اختبار عالية، وأحداث دقيقة يمكن الاستفادة منها لاتخاذ الإجراءات المناسبة في تطبيقك أو إطار العمل الخاص بك.
هذه وحدة Node.js متاحة عبر npm registry. يتم التثبيت باستخدام الأمر npm install:
$ npm install @fastify/send
يجب استخدام @types/mime@3 إذا كنت ترغب في استخدام TypeScript؛
@types/mime@4 أزال أنواع mime.
$ npm install -D @types/mime@3
const send = require('@fastify/send')
توفر statusCode، headers، و stream للمسار المحدد لإرسالها إلى res. req هو طلب HTTP الخاص بـ Node.js و path هو مسار مرمّز بعناوين URL للإرسال (مرمّز، وليس مسار نظام الملفات الفعلي).
تفعيل أو تعطيل قبول الطلبات ذات النطاق، القيمة الافتراضية هي true.
تعطيل هذا الخيار لن يرسل Accept-Ranges وسيتجاهل محتوى رأس الطلب Range.
تفعيل أو تعطيل تعيين رأس الاستجابة Cache-Control، القيمة الافتراضية هي true.
تعطيل هذا الخيار سيتجاهل خيارات immutable و maxAge.
بشكل افتراضي، تستخدم هذه المكتبة وحدة mime لتعيين Content-Type للاستجابة بناءً على امتداد الملف المطلوب.
لتعطيل هذه الوظيفة، قم بتعيين contentType إلى false.
سيحتاج رأس Content-Type إلى التعيين يدويًا إذا تم تعطيله.
تحديد كيفية معالجة "ملفات النقطة" عند مواجهتها. ملف النقطة هو ملف أو دليل يبدأ بنقطة ("."). لاحظ أن هذا الفحص يتم على المسار نفسه دون التحقق من وجود المسار على القرص. إذا تم تحديد root، يتم فحص ملفات النقطة الموجودة فوق الجذر فقط (أي أن الجذر نفسه يمكن أن يكون داخل ملف نقطة عند تعيينه على "deny").
'allow' لا توجد معاملة خاصة لملفات النقطة.'deny' إرسال 403 لأي طلب لملف نقطة.'ignore' التظاهر بأن ملف النقطة غير موجود وإرجاع 404.القيمة الافتراضية مشابهة لـ 'ignore'، مع استثناء أن هذه القيمة الافتراضية لن تتجاهل الملفات داخل دليل يبدأ بنقطة، وذلك للتوافق مع الإصدارات السابقة.
إزاحة البايت التي ينتهي عندها الدفق، القيمة الافتراضية هي طول الملف ناقص 1. النهاية شاملة في الدفق، مما يعني أن end: 3 ستضم البايت الرابع في الدفق.
تفعيل أو تعطيل توليد etag، القيمة الافتراضية هي true.
إذا لم يكن الملف المحدد موجودًا، حاول إضافة أحد الامتدادات المحددة، بالترتيب المحدد. افتراضيًا، هذا معطّل (مضبوط على false). قيمة مثال ستخدم ملفات HTML بدون امتداد: ['html', 'htm']. يتم تخطي هذا إذا كان الملف المطلوب يحتوي بالفعل على امتداد.
تفعيل أو تعطيل التوجيه immutable في رأس الاستجابة Cache-Control، القيمة الافتراضية هي false. إذا تم تعيينها إلى true، يجب أيضًا تحديد خيار maxAge لتمكين التخزين المؤقت. سيمنع التوجيه immutable العملاء المدعومين من إجراء طلبات شرطية خلال فترة خيار maxAge للتحقق مما إذا كان الملف قد تغير.
بشكل افتراضي، يدعم send ملفات "index.html"، لتعطيل ذلك قم بتعيين false أو لتوفير فهرس جديد قم بتمرير سلسلة نصية أو مصفوفة بالترتيب المفضل.
تفعيل أو تعطيل رأس Last-Modified، القيمة الافتراضية هي true. يستخدم قيمة التعديل الأخيرة لنظام الملفات.
توفير حد أقصى للعمر بالمللي ثانية للتخزين المؤقت HTTP، القيمة الافتراضية هي 0. يمكن أن يكون هذا أيضًا سلسلة نصية مقبولة بواسطة وحدة ms.
تحديد الحد الأقصى لحجم محتوى الاستجابة، القيمة الافتراضية هي حجم الملف بالكامل. سيتم استخدام هذا عندما يكون acceptRanges صحيحًا.
خدمة الملفات نسبيًا إلى path.
إزاحة البايت التي يبدأ عندها الدفق، القيمة الافتراضية هي 0. البداية شاملة، مما يعني أن start: 2 ستضم البايت الثالث في الدفق.
عند توفيره، يعيّن هذا الخيار الحد الأقصى لعدد البايتات التي سيحتفظ بها المخزن المؤقت الداخلي قبل إيقاف القراءات من المورد الأساسي. إذا حذفت هذا الخيار (أو مررت undefined)، فإن Node.js يعود إلى الإعداد الافتراضي المدمج للتيارات الثنائية القابلة للقراءة.
التصدير mime هو المثيل العام لوحدة mime npm.
يستخدم هذا لتكوين أنواع MIME المرتبطة بامتدادات الملفات بالإضافة إلى خيارات أخرى لكيفية حل نوع MIME لملف (مثل النوع الافتراضي لاستخدامه لامتداد ملف غير معروف).
لا يقوم بـ التخزين المؤقت الداخلي، يجب عليك استخدام وكيل عكسي للتخزين المؤقت مثل Varnish لهذا، أو تلك الأشياء الفاخرة التي تسمى CDNs. إذا كان تطبيقك صغيرًا بما يكفي لاستفادته من التخزين المؤقت في الذاكرة على عقدة واحدة، فهو صغير بما يكفي لعدم الحاجة إلى التخزين المؤقت على الإطلاق ;).
لتفعيل إخراج debug()، قم بتصدير NODE_DEBUG:
$ NODE_DEBUG=send node app
$ npm install
$ npm test
هذا المثال البسيط سيرسل ملفًا معينًا لجميع الطلبات.
const http = require('node:http')
const send = require('send')
const server = http.createServer(async function onRequest (req, res) {
const { statusCode, headers, stream } = await send(req, '/path/to/index.html')
res.writeHead(statusCode, headers)
stream.pipe(res)
})
server.listen(3000)
هذا المثال البسيط سيخدم جميع الملفات في دليل معين كمستوى أعلى. على سبيل المثال، طلب GET /foo.txt سيرسل /www/public/foo.txt.
const http = require('node:http')
const parseUrl = require('parseurl')
const send = require('@fastify/send')
const server = http.createServer(async function onRequest (req, res) {
const { statusCode, headers, stream } = await send(req, parseUrl(req).pathname, { root: '/www/public' })
res.writeHead(statusCode, headers)
stream.pipe(res)
})
server.listen(3000)
const http = require('node:http')
const parseUrl = require('parseurl')
const send = require('@fastify/send')
// تعيين الأنواع غير المعروفة افتراضيًا إلى text/plain
send.mime.default_type = 'text/plain'
// إضافة نوع مخصص
send.mime.define({
'application/x-my-type': ['x-mt', 'x-mtt']
})
const server = http.createServer(function onRequest (req, res) {
const { statusCode, headers, stream } = await send(req, parseUrl(req).pathname, { root: '/www/public' })
res.writeHead(statusCode, headers)
stream.pipe(res)
})
server.listen(3000)
هذا مثال على خدمة هيكل من الدلائل مع وظيفة مخصصة لعرض قائمة بالدليل.
const http = require('node:http')
const fs = require('node:fs')
const parseUrl = require('parseurl')
const send = require('@fastify/send')
// نقل الملفات العشوائية من داخل /www/example.com/public/*
// مع معالج مخصص لعرض قائمة الدليل
const server = http.createServer(async function onRequest (req, res) {
const { statusCode, headers, stream, type, metadata } = await send(req, parseUrl(req).pathname, { index: false, root: '/www/public' })
if(type === 'directory') {
// الحصول على قائمة الدليل
const list = await readdir(metadata.path)
// عرض فهرس للدليل
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' })
res.end(list.join('\n') + '\n')
} else {
res.writeHead(statusCode, headers)
stream.pipe(res)
}
})
server.listen(3000)
const http = require('node:http')
const parseUrl = require('parseurl')
const send = require('@fastify/send')
const server = http.createServer(async function onRequest (req, res) {
// نقل الملفات العشوائية من داخل
// /www/example.com/public/*
const { statusCode, headers, stream, type, metadata } = await send(req, parseUrl(req).pathname, { root: '/www/public' })
switch (type) {
case 'directory': {
// منطق معالجة الدليل المخصص لديك:
res.writeHead(301, {
'Location': metadata.requestPath + '/'
})
res.end('جاري إعادة التوجيه إلى ' + metadata.requestPath + '/')
break
}
case 'error': {
// منطق معالجة الأخطاء المخصص لديك:
res.writeHead(metadata.error.status ?? 500, {})
res.end(metadata.error.message)
break
}
default: {
// الرؤوس المخصصة لديك
// خدمة جميع الملفات للتحميل
res.setHeader('Content-Disposition', 'attachment')
res.writeHead(statusCode, headers)
stream.pipe(res)
}
}
})
server.listen(3000)
مرخص بموجب MIT.