diff --git a/src/node_http_common.h b/src/node_http_common.h index 5afb6b97becc4d..6836e0075b01ec 100644 --- a/src/node_http_common.h +++ b/src/node_http_common.h @@ -16,6 +16,8 @@ class Environment; #define DEFAULT_MAX_HEADER_LIST_PAIRS 128u #define DEFAULT_MAX_HEADER_LENGTH 8192 +constexpr size_t kMaxInternalizedHeaderNameLength = 64; + #define HTTP_SPECIAL_HEADERS(V) \ V(STATUS, ":status") \ V(METHOD, ":method") \ @@ -432,7 +434,7 @@ class NgRcBufPointer : public MemoryRetainer { return v8::String::Empty(env->isolate()); } - if (ptr.IsInternalizable() && len < 64) { + if (ptr.IsInternalizable() && len < kMaxInternalizedHeaderNameLength) { v8::MaybeLocal ret = GetInternalizedString(env, ptr); ptr.reset(); return ret; diff --git a/src/node_http_parser.cc b/src/node_http_parser.cc index d99b61780fad6c..f2a99a0c2f3bc2 100644 --- a/src/node_http_parser.cc +++ b/src/node_http_parser.cc @@ -28,6 +28,7 @@ #include "llhttp.h" #include "memory_tracker-inl.h" #include "node_external_reference.h" +#include "node_http_common.h" #include "stream_base-inl.h" #include "v8.h" @@ -65,6 +66,7 @@ using v8::Isolate; using v8::Local; using v8::LocalVector; using v8::MaybeLocal; +using v8::NewStringType; using v8::Number; using v8::Object; using v8::ObjectTemplate; @@ -233,6 +235,18 @@ struct StringPtr { return String::Empty(env->isolate()); } + Local ToInternalizedString(Environment* env) const { + // Only internalize short names to avoid pressuring the string table. + if (size_ != 0 && size_ < kMaxInternalizedHeaderNameLength) { + return String::NewFromOneByte(env->isolate(), + reinterpret_cast(str_), + NewStringType::kInternalized, + size_) + .ToLocalChecked(); + } + return ToString(env); + } + // Strip trailing OWS (SPC or HTAB) from string. Local ToTrimmedString(Environment* env) { while (size_ > 0 && IsOWS(str_[size_ - 1])) { @@ -940,7 +954,8 @@ class Parser : public AsyncWrap, public StreamListener { Local headers_v[kMaxHeaderFieldsCount * 2]; for (size_t i = 0; i < num_values_; ++i) { - headers_v[i * 2] = fields_[i].ToString(env()); + // Field names repeat across requests, so internalize them. + headers_v[i * 2] = fields_[i].ToInternalizedString(env()); headers_v[i * 2 + 1] = values_[i].ToTrimmedString(env()); }