Ana içeriğe geç

Ara Katmanlar

Bir ara katman fonksiyonu, her gelen bağlantı için yürütülen bir fonksiyondur.

Ara katman fonksiyonları, şunlar için faydalı olabilir:

  • günlükleme
  • kimlik doğrulama / yetkilendirme
  • oran sınırlama

Not: Bu fonksiyon, bağlantı birden fazla HTTP isteğinden oluşsa bile, her bağlantı başına yalnızca bir kez yürütülecektir.

bilgi

Eğer Express ara katmanlarını arıyorsanız, lütfen bu bölüme göz atın.

Bir ara katman kaydetme

Bir ara katman fonksiyonu, Socket örneğine ve bir sonraki kayıtlı ara katman fonksiyonuna erişime sahiptir.

io.use((socket, next) => {
if (isValid(socket.request)) {
next();
} else {
next(new Error("geçersiz"));
}
});

Birden fazla ara katman fonksiyonu kaydedebilirsiniz ve bunlar sıralı olarak yürütülecektir:

io.use((socket, next) => {
next();
});

io.use((socket, next) => {
next(new Error("geçemeyeceksin"));
});

io.use((socket, next) => {
// yürütülmez, çünkü önceki ara katman bir hata döndürmüştür
next();
});

Her durumda next() çağrısını yaptığınızdan emin olun. Aksi takdirde, bağlantı, belirtilen bir zaman aşımından sonra kapatılana kadar beklemede kalacaktır.

Önemli not: Ara katman yürütüldüğünde Socket örneği aslında bağlı değildir, bu da bağlantı başarısız olursa disconnect olayının yayımlanmayacağı anlamına gelir.

Örnek: İstemci bağlantıyı manuel olarak kapatırsa:

// sunucu tarafı
io.use((socket, next) => {
setTimeout(() => {
// istemci bağlantısı kesildikten sonra next çağrılır
next();
}, 1000);

socket.on("disconnect", () => {
// tetiklenmez
});
});

io.on("connection", (socket) => {
// tetiklenmez
});

// istemci tarafı
const socket = io();
setTimeout(() => {
socket.disconnect();
}, 500);

Kimlik bilgilerini gönderme

İstemci, auth seçeneği ile kimlik bilgilerini gönderebilir:

// düz nesne
const socket = io({
auth: {
token: "abc"
}
});

// veya bir fonksiyonla
const socket = io({
auth: (cb) => {
cb({
token: "abc"
});
}
});

Bu kimlik bilgilerine, sunucu tarafında handshake nesnesinde erişilebilir:

io.use((socket, next) => {
const token = socket.handshake.auth.token;
// ...
});

Ara katman hatasını yönetme

Eğer next metodu bir Hata nesnesi ile çağrılırsa, bağlantı reddedilir ve istemci connect_error olayı alır.

// istemci tarafı
socket.on("connect_error", (err) => {
console.log(err.message); // hataya bağlı mesajı yazdırır
});

Hata nesnesine ek ayrıntılar ekleyebilirsiniz:

// sunucu tarafı
io.use((socket, next) => {
const err = new Error("yetkisiz");
err.data = { content: "Lütfen daha sonra tekrar deneyin" }; // ek ayrıntılar
next(err);
});

// istemci tarafı
socket.on("connect_error", (err) => {
console.log(err instanceof Error); // true
console.log(err.message); // yetkisiz
console.log(err.data); // { content: "Lütfen daha sonra tekrar deneyin" }
});

Express ara katmanlarıyla uyumluluk

Socket.IO ara katmanları, genellikle bir HTTP istek/yanıt döngüsüne bağlı olmadıkları için, Express ara katmanları ile gerçekten uyumlu değildir.

Bununla birlikte, 4.6.0 sürümünden itibaren, Express ara katmanları artık alt motor tarafından desteklenmektedir:

io.engine.use((req, res, next) => {
// bir şey yap

next();
});

Bu ara katmanlar, gelen her HTTP isteği için çağrılır, yükseltme istekleri de dahil.

express-session ile bir örnek:

import session from "express-session";

io.engine.use(session({
secret: "klavye kedi",
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}));

helmet ile bir örnek:

import helmet from "helmet";

io.engine.use(helmet());

Eğer ara katman yalnızca el sıkışma isteğine (her HTTP isteği için değil) uygulanması gerekiyorsa, sid sorgu parametresinin varlığını kontrol edebilirsiniz.

passport-jwt ile bir örnek:

io.engine.use((req, res, next) => {
const isHandshake = req._query.sid === undefined;
if (isHandshake) {
passport.authenticate("jwt", { session: false })(req, res, next);
} else {
next();
}
});