# Контроллер

Внимание!

В классе контроллера Вы не можете получить доступ к его полям и методам напрямую, так как this связан с контекстом контроллера (описан на этой странице). Для доступа к собственным полям используйте this.controller.

Не будет работать:

module.exports = class Test {
    constructor () {
        this.defaultName = 'stranger';
    }

    _getGreeting (name) {
        return `Hello, ${name || this.defaultName}!`;
    }

    hello () {
        return this._getString(this.query.name);
    }
}

Будет работать:

module.exports = class Test {
    _getGreeting (name) {
        return `Hello, ${name || this.controller.defaultName}!`;
    }

    hello () {
        return this.controller._getString(this.query.name);
    }
}

# Отправка данных

Для отправки данных пользователю из HTTP-обработчика Вы можете использовать метод контекста контроллера this.send, вернуть значение (не пустой return) или выбросить исключение HttpError

Пример:

module.exports = class Test {
    // Ниже представлены полностью аналогичные реализации отправки данных
    async getSmth () {
        return await db.Smth.find({ ... }).lean();
    }

    async getSmth () {
        this.send(await db.Smth.find({ ... }).lean());
    }

    getSmth () {
        db.Smth.find({ ... }).lean().exec((err, list) => {
            if (err) this.send(err.toString(), 500);
            else this.send(list);
        });
    }
}

# Хуки

# onLoad

Вызывается до вызова любого обработчика в данном контроллере с передачей контекста (значения в this). Может прервать обработку запроса, например, если пользователь не имеет нужный уровень доступа.

Так же возможно добавление дополнительных данных в контекст обработчика, таких как информация об авторизации.

Примеры:

module.exports = class Bill {
    async onLoad () {
        const header = this.header('Authorization');
        if (!header || !header.startsWith('Bearer')) {
            return this.send('Incorrect auth type', 400);
        }

        const customer = await db.Customer
            .findOne({ apiToken: header.slice(7) })
            .select('_id')
            .lean();

        if (!customer) {
            return this.send('Incorrect auth token', 403);
        }

        this.auth = { customer: customer._id };
    }

    async list () {
        return await db.Bill.find({ customer: this.auth.customer }).lean();
    }
}
module.exports = class Admin {
    async onLoad () {
        if (this.session.access != 'admin') {
            // Соединение будет закрыто без ответа
            this.drop();
        }
    }
}

# Свойства

# this.address

Содержит информацию об IP-адресе пользователя.

{
    // Тип адреса. Значения: ipv4, ipv6
    type: String,
    // IP-адрес в формате, указанном в `type`
    value: String
}

# this.controller

Объект содержащий все поля и методы текущего контроллера. При вызове любого обработчика из этого объекта передаётся контекст (значение this) в этот обработчик.

# this.data

Содержит данные, полученные из тела POST запроса.

Поддерживает такие типы, как application/json, multipart/form-data и application/x-www-form-urlencoded.

# this.query

Содержит значения GET параметров запроса.

Пример:

// При запросе страницы http://localhost:8081/MyController/action?foo=bar
this.send(this.query);
// отправит в ответ { "foo": "bar" }

# this.session

Внимание!

Доступно, только если сессии включены и корректно настроены в файле конфигурации.

Содержит данные текущей сессии.

См. также: Сессия

# Методы HTTP обработчиков

# this.drop

Сбрасывает соединение без ответа на запрос.

# this.header

  • name: String - имя заголовка
  • value: String - значение, по-умолчанию не указано

Использование:

Если значение не указано, то возвращает значение заголовка из запроса, иначе устанавливает заголовок name в значение value для ответа.

Пример:

Код ниже при запросе с заголовком X-Data: my custom header отправит ответ с заголовком X-Data-Status: Accepted.

if (this.header('X-Data') == 'my custom header') {
    this.header('X-Data-Status', 'Accepted');
}

# this.redirect

Аргументы:

  • url: String

Использование:

Перенаправляет пользователя на указанный URL.

Пример:

this.redirect('https://google.com');

# this.send

Аргументы:

  • data: Any - данные для отправки
  • code: Number - HTTP код ответа, по-умолчанию 200
  • isPure: Boolean - если true, то data передаётся без изменений, иначе data будет сериализован, по-умолчанию false

Использование:

  • Отправка JSON совместимых данных (строки, числа, объекты и т.д.)

    this.send({ hello: true });
    
  • Отправка буфера или файла

    Внимание!

    При отправке файла нужно обязательно указывать аргументы code и isPure.

    this.send(fs.readFileSync('cat.png'), 200, true);
    

# Хуки WebSocket обработчиков

# open

Вызывается сразу после установки подключения.

# close

Вызывается сразу после отключения клиента.

# error

Аргументы:

Вызывается при возникновении ошибки на уровне WebSocket соединения. Также в этом случае вызывается хук close.

# Методы WebSocket обработчиков

# this.emit

Аргументы:

  • event: String - имя события
  • ...args: Any - любые аргументы, которые будут переданны в обработчик события

Использование:

Отправляет событие event через открытое WebSocket соединение.

Пример:

controllers/Socket.js:

this.emit('test-event', 'works', true);

Где-то в клиентской части (пример для dc-api-client):

API.Socket.on('test-event', (prop, value) => {
    console.log(prop + ': ' + value);
    // works: true
});

# this.subscribe

Аргументы:

  • channel: String - имя канала

Использование:

Добавляет для данного соединения подписку на данные из указанного канала.

Пример:

controllers/Socket.js:

// Добавляем соединению подписку на канал
this.subscribe('chat');

// Выполняет отправку данных, аналогично `this.emit('chat-message', 'Hello there!')`,
// для всех соединений, подписанных на канал "chat".
this.broadcast('chat', 'chat-message', 'Hello there!');

# this.unsubscribe

Аргументы:

  • channel: String - имя канала (опционально)

Использование:

Удаляет для данного соединения подписку на указанный канал, иначе удаляет все подписки.

# this.broadcast

Аргументы:

  • channel: String - имя канала
  • event: String - имя события
  • ...args: Any - аргументы, передаваемые в обработчик события

Использование:

Отправляет событие через все соединения, имеющие подписку на указанный канал. Если вместо имени канала передаётся null, то выполняется рассылка события для всех активных WebSocket соединений.

# this.end

Аргументы:

  • msg: String - по-умолчанию пустая строка
  • code: Number - по-умолчанию 1000 (закрытие без ошибкок)

Использование:

Закрывает текущее WebSocket соединение с сообщением msg и кодом закрытия code.

Обычное закрытие соединения:

this.end();

Закрытие с сообщением:

this.end('Internal server error', 1011);

См. также: Коды закрытия WebSocket (opens new window)