Я работал над проектом FeathersJS, который использовал реальное время на веб-клиенте, во время проверки производительности мы искали, что можно удалить, что не было необходимо для уменьшения размеров пакетов ядра / поставщика. Поскольку реальное время не использовалось для сообщений или обновлений в реальном времени, это было относительно очевидное место для поиска.
Используя FeathersJS в течение нескольких лет, я подумал, что это будет относительно простое изменение, даже несмотря на то, что я сам еще не менял клиентские транспорты в проекте и фактически использовал реальное время для большинства проектов, которые у меня есть. Само изменение кода, как и ожидалось, было довольно простым: установить новые клиентские библиотеки для REST и установить node-fetch
, так как это было приложение с рендерингом на стороне сервера.
Проблемы начинаются
Однако после перезапуска приложения и посещения нескольких локальных страниц стало очевидно, что что-то не так. Страницы не загружались должным образом, поэтому я начал исследовать.
Проблемы с массивом
У нас были довольно сложные запросы, которые имели множество глубоко вложенных параметров, которые затем использовались в ловушке для создания ассоциаций, которые отлично работали с запросами через веб-сокеты, но полностью не работали при использовании REST. Изучив, как FeathersJS анализирует строку запроса, я обнаружил, что он использовал пакет querystring, у которого была возможность увеличить глубину анализа вложенной строки. По умолчанию он будет анализировать только до 5 дочерних элементов в глубину, что было проблемой, поскольку у нас были более глубокие запросы. Вот что произошло бы, если бы у вас был запрос с глубиной более 5 дочерних элементов:
const input = 'a[b][c][d][e][f][g][h][i]=j'
const output = {
a: {
b: {
c: {
d: {
e: {
f: {
'[g][h][i]': 'j'
}
}
}
}
}
}
}
Решение для массива
Решение выделено в разделе часто задаваемые вопросы, где вы можете установить собственный qs
экземпляр с вашими собственными параметрами. Это позволяет вам настроить глубину анализа строки запроса:
// Update limits for `qs` to allow for deeper
// parsing of objects specifically from REST
app.set('query parser', function (str) {
return qs.parse(str, {
arrayLimit: 100,
depth: 20,
parameterLimit: 2000
});
});
нулевой вопрос
Следующая проблема, которая также появляется в часто задаваемых вопросах, заключается в том, что значение null
, когда в запросе, отправляемом через REST, не обрабатывается правильно, оно будет отображаться как пустая строка. Это не работает при использовании Sequelize
с postgres
, поскольку значение null
обычно превращается в 'property' is not null
запрос, который в итоге оказывается 'property' != ''
.
нулевое решение
Для правильной обработки null
мы должны просмотреть документацию по API библиотеки qs
. Мы видим, что есть возможность разрешить strictNullHandling
, которую мы можем добавить к query parser
сервера, как мы установили выше.
// Allow for strict null handling
app.set('query parser', function (str) {
return qs.parse(str, {
arrayLimit: 100,
depth: 20,
parameterLimit: 2000,
strictNullHandling: true
});
});
Теперь проблема в том, как установить, как библиотека qs
ведет себя на клиенте, когда она вызывает qs.stringify
для объекта запроса? Что ж, в настоящее время это невозможно, нет способа передать параметры qs.stringify
через клиент FeathersJS rest, а также нет способа, который позволил бы вам расширить и настроить способ создания строки запроса.
Но не бойтесь, у меня есть пиар, который решит эту проблему. Первоначально я создал PR для возможности добавлять параметры для этого эффекта, но после короткого обсуждения и дополнительной информации от Дэвида, основного разработчика FeathersJS, было решено, что разрешение расширяемости предпочтительнее опций, поэтому был сделан новый PR, чтобы сделать это возможно. Это позволит сделать следующее:
import feathers from '@feathersjs/feathers'
import rest from '@feathersjs/rest-client'
import { FetchClient } from '@feathersjs/rest-client'
import qs from 'qs'
const app = feathers()
class MyFetchClient extends FetchClient {
getQuery (query) {
if (Object.keys(query).length !== 0) {
const queryString = qs.stringify(query, {
strictNullHandling: true
})
return `?${queryString}`
}
return ''
}
}
// Configure API url
const restClient = rest('https://feathers-api.com')
// Configure rest client
app.configure(restClient.fetch(window.fetch, MyFetchClient))
С учетом этих изменений местами это обеспечивает более плавный переход между REST и веб-клиентами реального времени для FeathersJS API.
Первоначально опубликовано на https://mattchaffe.uk.