Fastify
Dekoratörler
Dekoratör API'si, temel Fastify nesnelerinin, örneğin sunucu örneği ve HTTP istek yaşam döngüsü sırasında kullanılan her türlü istek ve yanıt nesnelerinin özelleştirilmesine olanak tanır. Dekoratör API'si, temel nesnelere her türden özelliği eklemek için kullanılabilir; örneğin, fonksiyonlar, düz nesneler veya yerel türler.
Bu API senkron bir yapıya sahiptir. Asenkron olarak bir dekorasyon tanımlamaya çalışmak, dekorasyon tamamlanmadan Fastify örneğinin başlatılmasına neden olabilir. Bu sorunu önlemek ve asenkron bir dekorasyonu kaydetmek için, register
API'si ile birlikte fastify-plugin
kullanılmalıdır. Daha fazla bilgi için Eklentiler
belgesine bakın.
:::
tip
Dikkat edilmesi gereken bir ipucu: Asenkron dekorasyon tanımlarken fastify-plugin
kullanmayı unutmayın.
:::
Bu API ile temel nesneleri dekore etmek, temel JavaScript motorunun sunucu, istek ve yanıt nesnelerinin işlenmesini optimize etmesine olanak tanır. Bu, tüm nesne örneklerinin şeklinin, bunlar oluşturulmadan ve kullanılmadan önce tanımlanarak gerçekleştirilir. Örneğin, aşağıdaki kullanım önerilmez çünkü nesnelerin biçimini yaşam döngüleri sırasında değiştirecektir:
// Kötü örnek! Okumaya devam edin.
// İstek işleyici çağrılmadan önce gelen isteğe bir kullanıcı özelliği ekleyin.
fastify.addHook('preHandler', function (req, reply, done) {
req.user = 'Bob Dylan'
done()
})
// Eklenen kullanıcı özelliğini istek işleyicisinde kullanın.
fastify.get('/', function (req, reply) {
reply.send(`Merhaba, ${req.user}`)
})
Yukarıdaki örnek, istek nesnesi zaten oluşturulduktan sonra onu değiştirdiğinden, JavaScript motoru istek nesnesine erişimi deoptimize etmek zorunda kalır. Dekoratör API'sini kullanarak bu deoptimizasyonun önüne geçebiliriz:
// İsteği 'user' özelliği ile dekore et
fastify.decorateRequest('user', '')
// Özelliğimizi güncelleyelim
fastify.addHook('preHandler', (req, reply, done) => {
req.user = 'Bob Dylan'
done()
})
// Ve sonunda buna erişelim
fastify.get('/', (req, reply) => {
reply.send(`Merhaba, ${req.user}!`)
})
Dekore edilmiş bir alanın başlangıç şeklinin, gelecekte dinamik olarak ayarlanacak değere mümkün olduğunca yakın olması önemlidir. Eğer hedef değer bir dize ise dekoratörü ''
ile, bir nesne veya fonksiyon olacaksa null
ile başlatın.
::: warning Dekoratör API'si, yalnızca değer türleri ile çalışır; referans türleri Fastify başlangıcında hata verecektir. :::
Daha fazla bilgi için decorateRequest
belgesine bakın.
Bu konuyla ilgili daha fazla bilgi için JavaScript motoru temelleri: Şekiller ve Satır İçi Önbellekler sayfasını inceleyin.
Kullanım
decorate(name, value, [dependencies])
Bu yöntem, Fastify sunucu
örneğini özelleştirmek için kullanılır.
Örneğin, sunucu örneğine yeni bir metot eklemek için:
fastify.decorate('utility', function () {
// Çok faydalı bir şey
})
Yukarıda belirtildiği gibi, işlev olmayan değerler sunucu örneğine aşağıdaki gibi eklenebilir:
fastify.decorate('conf', {
db: 'some.db',
port: 3000
})
Dekore edilmiş özelliklere erişmek için dekorasyon API'sine sağlanan ismi kullanın:
fastify.utility()
console.log(fastify.conf.db)
Dekore edilmiş Fastify sunucusu
, route
işleyicilerinde this
üzerine bağlıdır:
fastify.decorate('db', new DbConnection())
fastify.get('/', async function (request, reply) {
// return kullanarak
return { hello: await this.db.query('world') }
// veya
// reply.send() kullanarak
reply.send({ hello: await this.db.query('world') })
await reply
})
dependencies
parametresi, tanımlanan dekoratörün bağımlı olduğu dekoratörlerin isteğe bağlı bir listesidir. Bu liste, diğer dekoratörlerin adlarının bir dizesinin listesidir. Aşağıdaki örnekte, "utility" dekoratörü "greet" ve "hi" dekoratörlerine bağımlıdır:
async function greetDecorator (fastify, opts) {
fastify.decorate('greet', () => {
return 'selam mesajı'
})
}
async function hiDecorator (fastify, opts) {
fastify.decorate('hi', () => {
return 'merhaba mesajı'
})
}
async function utilityDecorator (fastify, opts) {
fastify.decorate('utility', () => {
return `${fastify.greet()} | ${fastify.hi()}`
})
}
fastify.register(fastifyPlugin(greetDecorator, { name: 'greet' }))
fastify.register(fastifyPlugin(hiDecorator, { name: 'hi' }))
fastify.register(fastifyPlugin(utilityDecorator, { dependencies: ['greet', 'hi'] }))
fastify.get('/', function (req, reply) {
// Cevap: {"hello":"selam mesajı | merhaba mesajı"}
reply.send({ hello: fastify.utility() })
})
fastify.listen({ port: 3000 }, (err, address) => {
if (err) throw err
})
Not: Bir ok fonksiyonu kullanmak, this
'in FastifyInstance
'e bağlanmasını bozacaktır.
Eğer bir bağımlılık karşılanmazsa, decorate
metodu bir istisna fırlatır. Bağımlılık kontrolü sunucu örneği başlatılmadan önce gerçekleştirilir. Dolayısıyla, çalışma zamanında gerçekleşemez.
decorateReply(name, value, [dependencies])
İsmi önerdiği gibi, bu API temel Reply
nesnesine yeni metotlar/özellikler eklemek için kullanılır:
fastify.decorateReply('utility', function () {
// Çok faydalı bir şey
})
Not: Bir ok fonksiyonu kullanmak, this
'in Fastify Reply
örneğine bağlanmasını bozacaktır.
Not: decorateReply
kullanmak, bir referans türü ile kullanıldığında hata fırlatacaktır:
// Bunu yapmayın
fastify.decorateReply('foo', { bar: 'fizz'})
Bu örnekte, nesnenin referansı tüm isteklerle paylaşılacak ve herhangi bir değişiklik tüm istekleri etkileyecek, bu da potansiyel olarak güvenlik açıklarına veya bellek sızıntılarına neden olabilecektir, bu yüzden Fastify bunu engeller.
İstekler arasında doğru kapsülleme sağlamak için, her gelen istek için yeni bir değer yapılandırın 'onRequest'
kancası` içinde. Örnek:
const fp = require('fastify-plugin')
async function myPlugin (app) {
app.decorateRequest('foo')
app.addHook('onRequest', async (req, reply) => {
req.foo = { bar: 42 }
})
}
module.exports = fp(myPlugin)
dependencies
parametresi hakkında bilgi için decorate
belgesine bakın.
decorateRequest(name, value, [dependencies])
Yukarıda decorateReply
ile olduğu gibi, bu API, temel Request
nesnesine yeni metotlar/özellikler eklemek için kullanılır:
fastify.decorateRequest('utility', function () {
// çok faydalı bir şey
})
Not: Bir ok fonksiyonu kullanmak, this
'in Fastify Request
örneğine bağlanmasını bozacaktır.
Not: decorateRequest
kullanmak, bir referans türü ile kullanıldığında hata fırlatacaktır:
// Bunu yapmayın
fastify.decorateRequest('foo', { bar: 'fizz'})
Bu örnekte, nesnenin referansı tüm isteklerle paylaşılacak ve herhangi bir değişiklik tüm istekleri etkileyecek, bu da potansiyel olarak güvenlik açıklarına veya bellek sızıntılarına neden olabilecektir, bu yüzden Fastify bunu engeller.
İstekler arasında doğru kapsülleme sağlamak için, her gelen istek için yeni bir değer yapılandırın 'onRequest'
kancası`.
Örnek:
const fp = require('fastify-plugin')
async function myPlugin (app) {
app.decorateRequest('foo')
app.addHook('onRequest', async (req, reply) => {
req.foo = { bar: 42 }
})
}
module.exports = fp(myPlugin)
Kanca çözümü, onRequest
kancasında daha fazla mantık ekleyebileceğiniz için daha esnektir ve daha karmaşık başlatmalara olanak tanır.
Başka bir yaklaşım, getter/setter desenini kullanmaktır, ancak bu, 2 dekoratör gerektirir:
fastify.decorateRequest('my_decorator_holder') // tutucu tanımla
fastify.decorateRequest('user', {
getter () {
this.my_decorator_holder ??= {} // tutucuyu başlat
return this.my_decorator_holder
}
})
fastify.get('/', async function (req, reply) {
req.user.access = 'granted'
// diğer kod
})
Bu, user
özelliğinin her istek için her zaman benzersiz olmasını garanti eder.
dependencies
parametresi hakkında bilgi için decorate
belgesine bakın.
hasDecorator(name)
Bir sunucu örneği dekorasyonunun varlığını kontrol etmek için kullanılır:
fastify.hasDecorator('utility')
hasRequestDecorator
Bir İstek dekorasyonunun varlığını kontrol etmek için kullanılır:
fastify.hasRequestDecorator('utility')
hasReplyDecorator
Bir Yanıt dekorasyonunun varlığını kontrol etmek için kullanılır:
fastify.hasReplyDecorator('utility')
Dekoratörler ve Kapsülleme
Aynı kapsüllenmiş bağlamda aynı isimle bir dekoratör tanımlamak, bir istisna fırlatır.
Örneğin, aşağıdaki kod hata verecektir:
const server = require('fastify')()
server.decorateReply('view', function (template, args) {
// Harika bir görünüm oluşturma motoru
})
server.get('/', (req, reply) => {
reply.view('/index.html', { hello: 'world' })
})
// Kod tabanımızın başka bir yerinde, başka bir
// görünüm dekoratörü tanımlıyoruz. Bu hata verir.
server.decorateReply('view', function (template, args) {
// Diğer bir oluşturma motoru
})
server.listen({ port: 3000 })
Ama bu hata vermez:
const server = require('fastify')()
server.decorateReply('view', function (template, args) {
// Harika bir görünüm oluşturma motoru.
})
server.register(async function (server, opts) {
// Mevcut kapsüllenmiş eklentiye bir görünüm dekoratörü ekliyoruz.
// Bu hata vermez; çünkü burada görünüm yeni bir tanım olurken,
// kapsül dışında eski olan budur.
server.decorateReply('view', function (template, args) {
// Diğer bir oluşturma motoru
})
server.get('/', (req, reply) => {
reply.view('/index.page', { hello: 'world' })
})
}, { prefix: '/bar' })
server.listen({ port: 3000 })
Alıcılar ve Ayarlayıcılar
Dekoratörler, özel "getter/ayarlayıcı" nesnelerini tanır. Bu nesnelerin getter
ve setter
adında fonksiyonları vardır (ancak setter
fonksiyonu isteğe bağlıdır). Bu, dekoratörler aracılığıyla özellikler tanımlamaya olanak tanır, örneğin:
fastify.decorate('foo', {
getter () {
return 'bir alıcı'
}
})
Bu, Fastify örneğinde foo
özelliğini tanımlayacaktır:
console.log(fastify.foo) // 'bir alıcı'