Skip to content

Commit dd6444d

Browse files
committed
src,http2: DRY header/trailer handling code up
Remove duplicate code through minor refactoring. PR-URL: #14688 Reviewed-By: Daniel Bevenius <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James Snell <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
1 parent af85b6e commit dd6444d

File tree

5 files changed

+44
-63
lines changed

5 files changed

+44
-63
lines changed

src/node_http2.cc

Lines changed: 3 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -104,47 +104,6 @@ Http2Options::Http2Options(Environment* env) {
104104
}
105105
}
106106

107-
inline void CopyHeaders(Isolate* isolate,
108-
Local<Context> context,
109-
MaybeStackBuffer<nghttp2_nv>* list,
110-
Local<Array> headers) {
111-
Local<Value> item;
112-
Local<Array> header;
113-
114-
for (size_t n = 0; n < headers->Length(); n++) {
115-
item = headers->Get(context, n).ToLocalChecked();
116-
header = item.As<Array>();
117-
Local<Value> key = header->Get(context, 0).ToLocalChecked();
118-
Local<Value> value = header->Get(context, 1).ToLocalChecked();
119-
CHECK(key->IsString());
120-
CHECK(value->IsString());
121-
size_t keylen = StringBytes::StorageSize(isolate, key, ASCII);
122-
size_t valuelen = StringBytes::StorageSize(isolate, value, ASCII);
123-
nghttp2_nv& nv = (*list)[n];
124-
nv.flags = NGHTTP2_NV_FLAG_NONE;
125-
Local<Value> flag = header->Get(context, 2).ToLocalChecked();
126-
if (flag->BooleanValue(context).ToChecked())
127-
nv.flags |= NGHTTP2_NV_FLAG_NO_INDEX;
128-
nv.name = Malloc<uint8_t>(keylen);
129-
nv.value = Malloc<uint8_t>(valuelen);
130-
nv.namelen =
131-
StringBytes::Write(isolate,
132-
reinterpret_cast<char*>(nv.name),
133-
keylen, key, ASCII);
134-
nv.valuelen =
135-
StringBytes::Write(isolate,
136-
reinterpret_cast<char*>(nv.value),
137-
valuelen, value, ASCII);
138-
}
139-
}
140-
141-
inline void FreeHeaders(MaybeStackBuffer<nghttp2_nv>* list) {
142-
for (size_t n = 0; n < list->length(); n++) {
143-
free((*list)[n].name);
144-
free((*list)[n].value);
145-
}
146-
}
147-
148107
void Http2Session::OnFreeSession() {
149108
::delete this;
150109
}
@@ -860,7 +819,7 @@ void Http2Session::Send(uv_buf_t* buf, size_t length) {
860819
}
861820

862821
void Http2Session::OnTrailers(Nghttp2Stream* stream,
863-
MaybeStackBuffer<nghttp2_nv>* trailers) {
822+
const SubmitTrailers& submit_trailers) {
864823
DEBUG_HTTP2("Http2Session: prompting for trailers on stream %d\n",
865824
stream->id());
866825
Local<Context> context = env()->context();
@@ -879,8 +838,8 @@ void Http2Session::OnTrailers(Nghttp2Stream* stream,
879838
if (ret->IsArray()) {
880839
Local<Array> headers = ret.As<Array>();
881840
if (headers->Length() > 0) {
882-
trailers->AllocateSufficientStorage(headers->Length());
883-
CopyHeaders(isolate, context, trailers, headers);
841+
Headers trailers(isolate, context, headers);
842+
submit_trailers.Submit(*trailers, trailers.length());
884843
}
885844
}
886845
}

src/node_http2.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ class Http2Session : public AsyncWrap,
387387
size_t length) override;
388388
void OnFrameError(int32_t id, uint8_t type, int error_code) override;
389389
void OnTrailers(Nghttp2Stream* stream,
390-
MaybeStackBuffer<nghttp2_nv>* trailers) override;
390+
const SubmitTrailers& submit_trailers) override;
391391
void AllocateSend(size_t recommended, uv_buf_t* buf) override;
392392

393393
int DoWrite(WriteWrap* w, uv_buf_t* bufs, size_t count,

src/node_http2_core-inl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,12 @@ Nghttp2Session::Callbacks::~Callbacks() {
605605
nghttp2_session_callbacks_del(callbacks);
606606
}
607607

608+
Nghttp2Session::SubmitTrailers::SubmitTrailers(
609+
Nghttp2Session* handle,
610+
Nghttp2Stream* stream,
611+
uint32_t* flags)
612+
: handle_(handle), stream_(stream), flags_(flags) { }
613+
608614
} // namespace http2
609615
} // namespace node
610616

src/node_http2_core.cc

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -172,25 +172,24 @@ void Nghttp2Session::GetTrailers(nghttp2_session* session,
172172
// any trailing headers that are to be sent. This is the only opportunity
173173
// we have to make this check. If there are trailers, then the
174174
// NGHTTP2_DATA_FLAG_NO_END_STREAM flag must be set.
175-
MaybeStackBuffer<nghttp2_nv> trailers;
176-
handle->OnTrailers(stream, &trailers);
177-
if (trailers.length() > 0) {
178-
DEBUG_HTTP2("Nghttp2Session %d: sending trailers for stream %d, "
179-
"count: %d\n", handle->session_type_, stream->id(),
180-
trailers.length());
181-
*flags |= NGHTTP2_DATA_FLAG_NO_END_STREAM;
182-
nghttp2_submit_trailer(session,
183-
stream->id(),
184-
*trailers,
185-
trailers.length());
186-
}
187-
for (size_t n = 0; n < trailers.length(); n++) {
188-
free(trailers[n].name);
189-
free(trailers[n].value);
190-
}
175+
SubmitTrailers submit_trailers { handle, stream, flags };
176+
handle->OnTrailers(stream, submit_trailers);
191177
}
192178
}
193179

180+
void Nghttp2Session::SubmitTrailers::Submit(nghttp2_nv* trailers,
181+
size_t length) const {
182+
if (length == 0) return;
183+
DEBUG_HTTP2("Nghttp2Session %d: sending trailers for stream %d, "
184+
"count: %d\n", handle_->session_type_, stream_->id(),
185+
length);
186+
*flags_ |= NGHTTP2_DATA_FLAG_NO_END_STREAM;
187+
nghttp2_submit_trailer(handle_->session_,
188+
stream_->id(),
189+
trailers,
190+
length);
191+
}
192+
194193
// Called by nghttp2 to collect the data while a file response is sent.
195194
// The buf is the DATA frame buffer that needs to be filled with at most
196195
// length bytes. flags is used to control what nghttp2 does next.

src/node_http2_core.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,13 +166,30 @@ class Nghttp2Session {
166166
int error_code) {}
167167
virtual ssize_t GetPadding(size_t frameLength,
168168
size_t maxFrameLength) { return 0; }
169-
virtual void OnTrailers(Nghttp2Stream* stream,
170-
MaybeStackBuffer<nghttp2_nv>* nva) {}
171169
virtual void OnFreeSession() {}
172170
virtual void AllocateSend(size_t suggested_size, uv_buf_t* buf) = 0;
173171

174172
virtual bool HasGetPaddingCallback() { return false; }
175173

174+
class SubmitTrailers {
175+
public:
176+
void Submit(nghttp2_nv* trailers, size_t length) const;
177+
178+
private:
179+
inline SubmitTrailers(Nghttp2Session* handle,
180+
Nghttp2Stream* stream,
181+
uint32_t* flags);
182+
183+
Nghttp2Session* const handle_;
184+
Nghttp2Stream* const stream_;
185+
uint32_t* const flags_;
186+
187+
friend class Nghttp2Session;
188+
};
189+
190+
virtual void OnTrailers(Nghttp2Stream* stream,
191+
const SubmitTrailers& submit_trailers) {}
192+
176193
private:
177194
inline void SendPendingData();
178195
inline void HandleHeadersFrame(const nghttp2_frame* frame);

0 commit comments

Comments
 (0)