Проверить url.format (urlObject)? - PullRequest
       7

Проверить url.format (urlObject)?

0 голосов
/ 18 февраля 2019

Мне интересно узнать о NodeJS URL API .В частности, метод url.format(urlObject).Я хотел бы создать функцию, которая проверяет urlObject перед вызовом формата и выдает ошибку TypeError, если какая-либо из пар ключ / значение объекта является недопустимой, или "дополнительная" (не указана в спецификации).

Есть ли какой-нибудь способ, кроме типизации TypeScript, добиться этого?

1 Ответ

0 голосов
/ 19 февраля 2019

Вам будет трудно это сделать, потому что при создании экземпляра URL:

u = new URL('http://example.com/');

и Object.keys(u), и Object.getOwnPropertyNames(u) вернут пустой массив, и даже JSON.stringify(u) не будетздесь вам поможет, поскольку в результате получается одна строка верхнего уровня, а не JSON-представление объекта.

Таким образом, вы не сможете легко проверить наличие каких-либо дополнительных полей, если только вы вручную не проанализируете выводutil.format(u) или что-то в этом роде - но вам все равно нужно проверить ключи объекта (включая не перечисляемые свойства), чтобы проверить другие объекты, которые не являются экземплярами URL.

Таким образом, наиболее разумное решениебыло бы проверить, если u instanceof URL и если это правда, то поверьте, что это хорошо, но если это ложь, то проверьте конкретные свойства.

Но имейте в виду, что url.format() не нуждается в фактическомURL экземпляр, например, эти две строки имеют одинаковый эффект:

a = url.format(new URL('http://example.com/'));
b = url.format({ protocol: 'http', host: 'example.com', pathname: '/' });
// a === b

Чтобы проверить, если экземпляр URL (или любой другой объект) имеет следующие свойства и ониСтроки, как это должно быть в экземпляре URL, вы можете использовать что-то вроде:

const k = [
  'href',
  'origin',
  'protocol',
  'username',
  'password',
  'host',
  'hostname',
  'port',
  'pathname',
  'search',
  'hash',
];

const validUrl = u => k.filter(k => typeof u[k] === 'string').length === k.length;

Это вернет true для обычных URL экземпляров:

u = new URL('http://example.com/');
console.log(validUrl(u));

но и для других объектов, если у них есть все обязательные поля.Но имейте в виду, что для url.format() не требуются все поля, как вы можете видеть в приведенном выше примере, так что таким образом вы бы отклонили некоторые значения, которые были бы идеально подходящими для url.format(), например:

u = { protocol: 'http', host: 'example.com', pathname: '/' };

Подводя итог:

Реальные URL экземпляры не показывают, какие свойства у них есть, поэтому вы не сможете легко проверить дополнительные свойства, но я бы не советовал делатьчто в любом случае, потому что ваш код сломается, если URL когда-либо будет расширен с новыми свойствами, которые могут произойти в будущем.

Чтобы увидеть, есть ли у него все необходимое (по вашему мнению - не обязательно по мнениюurl.format()!) Свойств, вы можете написать простую функцию валидатора, но тогда вы не сможете пропустить пустые свойства, такие как username, если их нет, и вам придется явно передавать пустые строки для всех пустых свойств, если вы хотитечтобы иметь возможность использовать URL -подобные объекты, которые в противном случае совместимы с url.format().

Может быть, вы хотите проверить только некоторые поля, такие как protocol, host и pathname, но тогда вы должны обработать, что url.format() займет либо host, либо hostname, предпочитая host, если оба доступны и т. д.

Вы также можете попробовать взломать как этот:

const testUrl = u => {
  try {
    new URL(url.format(u));
  } catch (e) {
    throw new TypeError('your error message');
  }
};

и есть функция, которая экспериментально проверяет, работает ли заданное значение с url.format(), давая URL-адрес, доступный для new URL(), например:

testUrl(new URL('http://example.com')); // ok
testUrl({host: 'example.com', protocol: 'http'}); // ok
testUrl({host: 'example.com'}); // throws a TypeError 

Теперь в вашей функциикоторый вызывает url.format(urlObject), все, что вам нужно сделать, это добавить: testUrl(urlObject) в строке раньше, и он выдаст исключения, которые вы описываете.

В общем, это сложный вопрос.Вы можете сделать это разными способами, но у всех есть некоторые недостатки.URL экземпляры на самом деле довольно странные, и даже Джой ломается над ними!

Например:

!joi.object({ host: joi.string().required() }).validate({ host: 'example.com' }).error;
// returns true

!joi.object({ host: joi.string().required() }).validate({ nohost: 'example.com' }).error
// returns false

!joi.object({ host: joi.string().required() }).validate(new URL('http://example.com/')).error;
// this throws an exception!
// TypeError: Cannot read property 'host' of undefined
// WTF???

Если даже Джой не может проверить URL экземпляры, то их нелегко проверить.

Надеемся, что некоторые из приведенных выше примеров сделают то, что вам нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...