req.header против req.headers в Express - PullRequest
0 голосов
/ 25 марта 2020

Я использую Express с Body Parser. Приведенный ниже ключ заголовка:

X-Master-Key

Когда я использую приведенный ниже фрагмент кода, он не может вывести значение

req.headers['X-Master-Key'] // Fails

но при изменении вышеприведенного на это работает

req.headers['x-master-key'] // Works

Далее, когда я попытался вывести req.headers, оказалось, что Express выводит все заголовки в формат в нижнем регистре.


Я начал копать дальше и попытался использовать приведенный ниже код, любой из этих фрагментов работает

req.header('X-Master-Key'); // Works

// -- OR

req.header('x-master-key'); // Works

Так в чем здесь проблема? Почему Express заменяет все ключи заголовка на нижний регистр? Более того, чем использование req.header() отличается от req.headers[]?

Ответы [ 2 ]

2 голосов
/ 25 марта 2020

Проблема возникает из-за того, что в протоколе HTTP заголовки не чувствительны к регистру. Это означает, что content-type, Content-Type и coNTEnt-tYPe все ссылаются на один и тот же заголовок, и инфраструктура Express должна иметь возможность обрабатывать любой из них.

Различия между req.headers (объект) и req.header (функция) просто так:

Если вы хотите получить свойство из объекта Javascript, имя свойства чувствительно к регистру. Так что req.headers['content-type'] будет работать; req.headers['Content-Type'] не будет. Почему работает строчная версия? Поскольку платформа Express, пытаясь обработать все возможные варианты (помните, HTTP разрешит все), преобразует все в нижний регистр.

Но разработчики Express признают, что вы ( developer) может искать Content-Type, и вы можете не помнить о преобразовании в нижний регистр, поэтому они предоставили функцию req.header, которая позаботится об этом за вас.

Итак, вкратце:

Рекомендуется:

const myHeader = req.header('Content-Type');

Используйте любой регистр, который вы хотите - функция преобразует его в нижний регистр и ищет значение в req.headers.

Это не рекомендуется:

const myHeader = req.headers['Content-Type'];

Если вы не используете имя заголовка в нижнем регистре, вы не получите то, что ожидаете.

1 голос
/ 25 марта 2020

Проблема сводится к чувствительности к регистру.

Когда вы смотрите на документацию для req.get (с псевдонимом req.header), она гласит:

Возвращает указанное поле заголовка HTTP-запроса (совпадение без учета регистра). Поля Referrer и Referer являются взаимозаменяемыми.

Стандарт w3 указывает, что заголовки должны быть без учета регистра:

Каждое поле заголовка состоит из имя, за которым следует двоеточие (":") и значение поля. Имена полей не чувствительны к регистру.

Таким образом, может показаться, что модуль http узла, который используется express, просто обрабатывает их все как строчные буквы, чтобы "сохранить ваши шаги" в соответствии с этим GitHub Issue

Вы можете видеть , что express framework req объект фактически использует модуль узла http:

var accepts = require('accepts');
var deprecate = require('depd')('express');
var isIP = require('net').isIP;
var typeis = require('type-is');
var http = require('http');
var fresh = require('fresh');
var parseRange = require('range-parser');
var parse = require('parseurl');

Более того в коде вы можете видеть, что метод req.header преобразует все, что вы даете ему, в нижний регистр:

req.get =
req.header = function header(name) {
  if (!name) {
    throw new TypeError('name argument is required to req.get');
  }

  if (typeof name !== 'string') {
    throw new TypeError('name must be a string to req.get');
  }

  var lc = name.toLowerCase();

  switch (lc) {
    case 'referer':
    case 'referrer':
      return this.headers.referrer
        || this.headers.referer;
    default:
      return this.headers[lc];
  }
};

Наконец, модуль http анализирует заголовки, используя matchKnownFields * Функция 1040 *, которая автоматически в нижнем регистре записывает все заголовки, которые не являются "традиционными заголовками", в этом случае она нечувствительна к регистру.

Вот ответственный фрагмент, который реализует поведение, которое вы видите:

if (lowercased) {
    return '\u0000' + field;
} else {
    return matchKnownFields(field.toLowerCase(), true);
}
...