Node.js  v8.x
Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine
node_http_parser.cc
Go to the documentation of this file.
1 // Copyright Joyent, Inc. and other Node contributors.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
21 
22 #include "node.h"
23 #include "node_buffer.h"
24 
25 #include "async-wrap.h"
26 #include "async-wrap-inl.h"
27 #include "env.h"
28 #include "env-inl.h"
29 #include "http_parser.h"
30 #include "stream_base.h"
31 #include "stream_base-inl.h"
32 #include "util.h"
33 #include "util-inl.h"
34 #include "v8.h"
35 
36 #include <stdlib.h> // free()
37 #include <string.h> // strdup()
38 
39 // This is a binding to http_parser (https://github.com/nodejs/http-parser)
40 // The goal is to decouple sockets from parsing for more javascript-level
41 // agility. A Buffer is read from a socket and passed to parser.execute().
42 // The parser then issues callbacks with slices of the data
43 // parser.onMessageBegin
44 // parser.onPath
45 // parser.onBody
46 // ...
47 // No copying is performed when slicing the buffer, only small reference
48 // allocations.
49 
50 
51 namespace node {
52 namespace {
53 
54 using v8::Array;
55 using v8::Boolean;
56 using v8::Context;
57 using v8::EscapableHandleScope;
58 using v8::Exception;
59 using v8::Function;
60 using v8::FunctionCallbackInfo;
61 using v8::FunctionTemplate;
62 using v8::HandleScope;
63 using v8::Integer;
64 using v8::Local;
65 using v8::MaybeLocal;
66 using v8::Object;
67 using v8::String;
68 using v8::Uint32;
69 using v8::Undefined;
70 using v8::Value;
71 
72 const uint32_t kOnHeaders = 0;
73 const uint32_t kOnHeadersComplete = 1;
74 const uint32_t kOnBody = 2;
75 const uint32_t kOnMessageComplete = 3;
76 const uint32_t kOnExecute = 4;
77 
78 
79 #define HTTP_CB(name) \
80  static int name(http_parser* p_) { \
81  Parser* self = ContainerOf(&Parser::parser_, p_); \
82  return self->name##_(); \
83  } \
84  int name##_()
85 
86 
87 #define HTTP_DATA_CB(name) \
88  static int name(http_parser* p_, const char* at, size_t length) { \
89  Parser* self = ContainerOf(&Parser::parser_, p_); \
90  return self->name##_(at, length); \
91  } \
92  int name##_(const char* at, size_t length)
93 
94 
95 // helper class for the Parser
96 struct StringPtr {
97  StringPtr() {
98  on_heap_ = false;
99  Reset();
100  }
101 
102 
103  ~StringPtr() {
104  Reset();
105  }
106 
107 
108  // If str_ does not point to a heap string yet, this function makes it do
109  // so. This is called at the end of each http_parser_execute() so as not
110  // to leak references. See issue #2438 and test-http-parser-bad-ref.js.
111  void Save() {
112  if (!on_heap_ && size_ > 0) {
113  char* s = new char[size_];
114  memcpy(s, str_, size_);
115  str_ = s;
116  on_heap_ = true;
117  }
118  }
119 
120 
121  void Reset() {
122  if (on_heap_) {
123  delete[] str_;
124  on_heap_ = false;
125  }
126 
127  str_ = nullptr;
128  size_ = 0;
129  }
130 
131 
132  void Update(const char* str, size_t size) {
133  if (str_ == nullptr) {
134  str_ = str;
135  } else if (on_heap_ || str_ + size_ != str) {
136  // Non-consecutive input, make a copy on the heap.
137  // TODO(bnoordhuis) Use slab allocation, O(n) allocs is bad.
138  char* s = new char[size_ + size];
139  memcpy(s, str_, size_);
140  memcpy(s + size_, str, size);
141 
142  if (on_heap_)
143  delete[] str_;
144  else
145  on_heap_ = true;
146 
147  str_ = s;
148  }
149  size_ += size;
150  }
151 
152 
153  Local<String> ToString(Environment* env) const {
154  if (str_)
155  return OneByteString(env->isolate(), str_, size_);
156  else
157  return String::Empty(env->isolate());
158  }
159 
160 
161  const char* str_;
162  bool on_heap_;
163  size_t size_;
164 };
165 
166 
167 class Parser : public AsyncWrap {
168  public:
169  Parser(Environment* env, Local<Object> wrap, enum http_parser_type type)
170  : AsyncWrap(env, wrap, AsyncWrap::PROVIDER_HTTPPARSER),
172  current_buffer_data_(nullptr) {
173  Wrap(object(), this);
174  Init(type);
175  }
176 
177 
178  ~Parser() override {
179  ClearWrap(object());
180  persistent().Reset();
181  }
182 
183 
184  size_t self_size() const override {
185  return sizeof(*this);
186  }
187 
188 
189  HTTP_CB(on_message_begin) {
190  num_fields_ = num_values_ = 0;
191  url_.Reset();
192  status_message_.Reset();
193  return 0;
194  }
195 
196 
197  HTTP_DATA_CB(on_url) {
198  url_.Update(at, length);
199  return 0;
200  }
201 
202 
203  HTTP_DATA_CB(on_status) {
204  status_message_.Update(at, length);
205  return 0;
206  }
207 
208 
209  HTTP_DATA_CB(on_header_field) {
210  if (num_fields_ == num_values_) {
211  // start of new field name
212  num_fields_++;
213  if (num_fields_ == arraysize(fields_)) {
214  // ran out of space - flush to javascript land
215  Flush();
216  num_fields_ = 1;
217  num_values_ = 0;
218  }
219  fields_[num_fields_ - 1].Reset();
220  }
221 
222  CHECK_LT(num_fields_, arraysize(fields_));
223  CHECK_EQ(num_fields_, num_values_ + 1);
224 
225  fields_[num_fields_ - 1].Update(at, length);
226 
227  return 0;
228  }
229 
230 
231  HTTP_DATA_CB(on_header_value) {
232  if (num_values_ != num_fields_) {
233  // start of new header value
234  num_values_++;
235  values_[num_values_ - 1].Reset();
236  }
237 
238  CHECK_LT(num_values_, arraysize(values_));
239  CHECK_EQ(num_values_, num_fields_);
240 
241  values_[num_values_ - 1].Update(at, length);
242 
243  return 0;
244  }
245 
246 
247  HTTP_CB(on_headers_complete) {
248  // Arguments for the on-headers-complete javascript callback. This
249  // list needs to be kept in sync with the actual argument list for
250  // `parserOnHeadersComplete` in lib/_http_common.js.
251  enum on_headers_complete_arg_index {
252  A_VERSION_MAJOR = 0,
253  A_VERSION_MINOR,
254  A_HEADERS,
255  A_METHOD,
256  A_URL,
257  A_STATUS_CODE,
258  A_STATUS_MESSAGE,
259  A_UPGRADE,
260  A_SHOULD_KEEP_ALIVE,
261  A_MAX
262  };
263 
264  Local<Value> argv[A_MAX];
265  Local<Object> obj = object();
266  Local<Value> cb = obj->Get(kOnHeadersComplete);
267 
268  if (!cb->IsFunction())
269  return 0;
270 
271  Local<Value> undefined = Undefined(env()->isolate());
272  for (size_t i = 0; i < arraysize(argv); i++)
273  argv[i] = undefined;
274 
275  if (have_flushed_) {
276  // Slow case, flush remaining headers.
277  Flush();
278  } else {
279  // Fast case, pass headers and URL to JS land.
280  argv[A_HEADERS] = CreateHeaders();
281  if (parser_.type == HTTP_REQUEST)
282  argv[A_URL] = url_.ToString(env());
283  }
284 
285  num_fields_ = 0;
286  num_values_ = 0;
287 
288  // METHOD
289  if (parser_.type == HTTP_REQUEST) {
290  argv[A_METHOD] =
291  Uint32::NewFromUnsigned(env()->isolate(), parser_.method);
292  }
293 
294  // STATUS
295  if (parser_.type == HTTP_RESPONSE) {
296  argv[A_STATUS_CODE] =
297  Integer::New(env()->isolate(), parser_.status_code);
298  argv[A_STATUS_MESSAGE] = status_message_.ToString(env());
299  }
300 
301  // VERSION
302  argv[A_VERSION_MAJOR] = Integer::New(env()->isolate(), parser_.http_major);
303  argv[A_VERSION_MINOR] = Integer::New(env()->isolate(), parser_.http_minor);
304 
305  argv[A_SHOULD_KEEP_ALIVE] =
306  Boolean::New(env()->isolate(), http_should_keep_alive(&parser_));
307 
308  argv[A_UPGRADE] = Boolean::New(env()->isolate(), parser_.upgrade);
309 
310  Environment::AsyncCallbackScope callback_scope(env());
311 
312  MaybeLocal<Value> head_response =
313  MakeCallback(cb.As<Function>(), arraysize(argv), argv);
314 
315  if (head_response.IsEmpty()) {
316  got_exception_ = true;
317  return -1;
318  }
319 
320  return head_response.ToLocalChecked()->IntegerValue();
321  }
322 
323 
324  HTTP_DATA_CB(on_body) {
325  EscapableHandleScope scope(env()->isolate());
326 
327  Local<Object> obj = object();
328  Local<Value> cb = obj->Get(kOnBody);
329 
330  if (!cb->IsFunction())
331  return 0;
332 
333  // We came from consumed stream
334  if (current_buffer_.IsEmpty()) {
335  // Make sure Buffer will be in parent HandleScope
336  current_buffer_ = scope.Escape(Buffer::Copy(
337  env()->isolate(),
339  current_buffer_len_).ToLocalChecked());
340  }
341 
342  Local<Value> argv[3] = {
344  Integer::NewFromUnsigned(env()->isolate(), at - current_buffer_data_),
345  Integer::NewFromUnsigned(env()->isolate(), length)
346  };
347 
348  MaybeLocal<Value> r = MakeCallback(cb.As<Function>(),
349  arraysize(argv),
350  argv);
351 
352  if (r.IsEmpty()) {
353  got_exception_ = true;
354  return -1;
355  }
356 
357  return 0;
358  }
359 
360 
361  HTTP_CB(on_message_complete) {
362  HandleScope scope(env()->isolate());
363 
364  if (num_fields_)
365  Flush(); // Flush trailing HTTP headers.
366 
367  Local<Object> obj = object();
368  Local<Value> cb = obj->Get(kOnMessageComplete);
369 
370  if (!cb->IsFunction())
371  return 0;
372 
373  Environment::AsyncCallbackScope callback_scope(env());
374 
375  MaybeLocal<Value> r = MakeCallback(cb.As<Function>(), 0, nullptr);
376 
377  if (r.IsEmpty()) {
378  got_exception_ = true;
379  return -1;
380  }
381 
382  return 0;
383  }
384 
385 
386  static void New(const FunctionCallbackInfo<Value>& args) {
387  Environment* env = Environment::GetCurrent(args);
388  http_parser_type type =
389  static_cast<http_parser_type>(args[0]->Int32Value());
390  CHECK(type == HTTP_REQUEST || type == HTTP_RESPONSE);
391  new Parser(env, args.This(), type);
392  }
393 
394 
395  static void Close(const FunctionCallbackInfo<Value>& args) {
396  Parser* parser;
397  ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
398 
399  if (--parser->refcount_ == 0)
400  delete parser;
401  }
402 
403 
404  void Save() {
405  url_.Save();
406  status_message_.Save();
407 
408  for (size_t i = 0; i < num_fields_; i++) {
409  fields_[i].Save();
410  }
411 
412  for (size_t i = 0; i < num_values_; i++) {
413  values_[i].Save();
414  }
415  }
416 
417 
418  // var bytesParsed = parser->execute(buffer);
419  static void Execute(const FunctionCallbackInfo<Value>& args) {
420  Parser* parser;
421  ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
422  CHECK(parser->current_buffer_.IsEmpty());
423  CHECK_EQ(parser->current_buffer_len_, 0);
424  CHECK_EQ(parser->current_buffer_data_, nullptr);
425  CHECK_EQ(Buffer::HasInstance(args[0]), true);
426 
427  Local<Object> buffer_obj = args[0].As<Object>();
428  char* buffer_data = Buffer::Data(buffer_obj);
429  size_t buffer_len = Buffer::Length(buffer_obj);
430 
431  // This is a hack to get the current_buffer to the callbacks with the least
432  // amount of overhead. Nothing else will run while http_parser_execute()
433  // runs, therefore this pointer can be set and used for the execution.
434  parser->current_buffer_ = buffer_obj;
435 
436  Local<Value> ret = parser->Execute(buffer_data, buffer_len);
437 
438  if (!ret.IsEmpty())
439  args.GetReturnValue().Set(ret);
440  }
441 
442 
443  static void Finish(const FunctionCallbackInfo<Value>& args) {
444  Environment* env = Environment::GetCurrent(args);
445 
446  Parser* parser;
447  ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
448 
449  CHECK(parser->current_buffer_.IsEmpty());
450  parser->got_exception_ = false;
451 
452  int rv = http_parser_execute(&(parser->parser_), &settings, nullptr, 0);
453 
454  if (parser->got_exception_)
455  return;
456 
457  if (rv != 0) {
458  enum http_errno err = HTTP_PARSER_ERRNO(&parser->parser_);
459 
460  Local<Value> e = Exception::Error(env->parse_error_string());
461  Local<Object> obj = e->ToObject(env->isolate());
462  obj->Set(env->bytes_parsed_string(), Integer::New(env->isolate(), 0));
463  obj->Set(env->code_string(),
464  OneByteString(env->isolate(), http_errno_name(err)));
465 
466  args.GetReturnValue().Set(e);
467  }
468  }
469 
470 
471  static void Reinitialize(const FunctionCallbackInfo<Value>& args) {
472  Environment* env = Environment::GetCurrent(args);
473 
474  http_parser_type type =
475  static_cast<http_parser_type>(args[0]->Int32Value());
476 
477  CHECK(type == HTTP_REQUEST || type == HTTP_RESPONSE);
478  Parser* parser;
479  ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
480  // Should always be called from the same context.
481  CHECK_EQ(env, parser->env());
482  // The parser is being reused. Reset the uid and call init() callbacks.
483  parser->AsyncReset();
484  parser->Init(type);
485  }
486 
487 
488  template <bool should_pause>
489  static void Pause(const FunctionCallbackInfo<Value>& args) {
490  Environment* env = Environment::GetCurrent(args);
491  Parser* parser;
492  ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
493  // Should always be called from the same context.
494  CHECK_EQ(env, parser->env());
495  http_parser_pause(&parser->parser_, should_pause);
496  }
497 
498 
499  static void Consume(const FunctionCallbackInfo<Value>& args) {
500  Parser* parser;
501  ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
502  CHECK(args[0]->IsExternal());
503  Local<External> stream_obj = args[0].As<External>();
504  StreamBase* stream = static_cast<StreamBase*>(stream_obj->Value());
505  CHECK_NE(stream, nullptr);
506 
507  stream->Consume();
508 
509  parser->prev_alloc_cb_ = stream->alloc_cb();
510  parser->prev_read_cb_ = stream->read_cb();
511 
512  stream->set_alloc_cb({ OnAllocImpl, parser });
513  stream->set_read_cb({ OnReadImpl, parser });
514  }
515 
516 
517  static void Unconsume(const FunctionCallbackInfo<Value>& args) {
518  Parser* parser;
519  ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
520 
521  // Already unconsumed
522  if (parser->prev_alloc_cb_.is_empty())
523  return;
524 
525  // Restore stream's callbacks
526  if (args.Length() == 1 && args[0]->IsExternal()) {
527  Local<External> stream_obj = args[0].As<External>();
528  StreamBase* stream = static_cast<StreamBase*>(stream_obj->Value());
529  CHECK_NE(stream, nullptr);
530 
531  stream->set_alloc_cb(parser->prev_alloc_cb_);
532  stream->set_read_cb(parser->prev_read_cb_);
533  stream->Unconsume();
534  }
535 
536  parser->prev_alloc_cb_.clear();
537  parser->prev_read_cb_.clear();
538  }
539 
540 
541  static void GetCurrentBuffer(const FunctionCallbackInfo<Value>& args) {
542  Parser* parser;
543  ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
544 
545  Local<Object> ret = Buffer::Copy(
546  parser->env(),
547  parser->current_buffer_data_,
548  parser->current_buffer_len_).ToLocalChecked();
549 
550  args.GetReturnValue().Set(ret);
551  }
552 
553  protected:
554  class ScopedRetainParser {
555  public:
556  explicit ScopedRetainParser(Parser* p) : p_(p) {
557  CHECK_GT(p_->refcount_, 0);
558  p_->refcount_++;
559  }
560 
561  ~ScopedRetainParser() {
562  if (0 == --p_->refcount_)
563  delete p_;
564  }
565 
566  private:
567  Parser* const p_;
568  };
569 
570  static const size_t kAllocBufferSize = 64 * 1024;
571 
572  static void OnAllocImpl(size_t suggested_size, uv_buf_t* buf, void* ctx) {
573  Parser* parser = static_cast<Parser*>(ctx);
574  Environment* env = parser->env();
575 
576  if (env->http_parser_buffer() == nullptr)
577  env->set_http_parser_buffer(new char[kAllocBufferSize]);
578 
579  buf->base = env->http_parser_buffer();
580  buf->len = kAllocBufferSize;
581  }
582 
583 
584  static void OnReadImpl(ssize_t nread,
585  const uv_buf_t* buf,
586  uv_handle_type pending,
587  void* ctx) {
588  Parser* parser = static_cast<Parser*>(ctx);
589  HandleScope scope(parser->env()->isolate());
590 
591  if (nread < 0) {
592  uv_buf_t tmp_buf;
593  tmp_buf.base = nullptr;
594  tmp_buf.len = 0;
595  parser->prev_read_cb_.fn(nread,
596  &tmp_buf,
597  pending,
598  parser->prev_read_cb_.ctx);
599  return;
600  }
601 
602  // Ignore, empty reads have special meaning in http parser
603  if (nread == 0)
604  return;
605 
606  ScopedRetainParser retain(parser);
607 
608  parser->current_buffer_.Clear();
609  Local<Value> ret = parser->Execute(buf->base, nread);
610 
611  // Exception
612  if (ret.IsEmpty())
613  return;
614 
615  Local<Object> obj = parser->object();
616  Local<Value> cb = obj->Get(kOnExecute);
617 
618  if (!cb->IsFunction())
619  return;
620 
621  // Hooks for GetCurrentBuffer
622  parser->current_buffer_len_ = nread;
623  parser->current_buffer_data_ = buf->base;
624 
625  parser->MakeCallback(cb.As<Function>(), 1, &ret);
626 
627  parser->current_buffer_len_ = 0;
628  parser->current_buffer_data_ = nullptr;
629  }
630 
631 
632  Local<Value> Execute(char* data, size_t len) {
633  EscapableHandleScope scope(env()->isolate());
634 
637  got_exception_ = false;
638 
639  size_t nparsed =
640  http_parser_execute(&parser_, &settings, data, len);
641 
642  Save();
643 
644  // Unassign the 'buffer_' variable
645  current_buffer_.Clear();
647  current_buffer_data_ = nullptr;
648 
649  // If there was an exception in one of the callbacks
650  if (got_exception_)
651  return scope.Escape(Local<Value>());
652 
653  Local<Integer> nparsed_obj = Integer::New(env()->isolate(), nparsed);
654  // If there was a parse error in one of the callbacks
655  // TODO(bnoordhuis) What if there is an error on EOF?
656  if (!parser_.upgrade && nparsed != len) {
657  enum http_errno err = HTTP_PARSER_ERRNO(&parser_);
658 
659  Local<Value> e = Exception::Error(env()->parse_error_string());
660  Local<Object> obj = e->ToObject(env()->isolate());
661  obj->Set(env()->bytes_parsed_string(), nparsed_obj);
662  obj->Set(env()->code_string(),
663  OneByteString(env()->isolate(), http_errno_name(err)));
664 
665  return scope.Escape(e);
666  }
667  return scope.Escape(nparsed_obj);
668  }
669 
670  Local<Array> CreateHeaders() {
671  Local<Array> headers = Array::New(env()->isolate());
672  Local<Function> fn = env()->push_values_to_array_function();
673  Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX * 2];
674  size_t i = 0;
675 
676  do {
677  size_t j = 0;
678  while (i < num_values_ && j < arraysize(argv) / 2) {
679  argv[j * 2] = fields_[i].ToString(env());
680  argv[j * 2 + 1] = values_[i].ToString(env());
681  i++;
682  j++;
683  }
684  if (j > 0) {
685  fn->Call(env()->context(), headers, j * 2, argv).ToLocalChecked();
686  }
687  } while (i < num_values_);
688 
689  return headers;
690  }
691 
692 
693  // spill headers and request path to JS land
694  void Flush() {
695  HandleScope scope(env()->isolate());
696 
697  Local<Object> obj = object();
698  Local<Value> cb = obj->Get(kOnHeaders);
699 
700  if (!cb->IsFunction())
701  return;
702 
703  Local<Value> argv[2] = {
704  CreateHeaders(),
705  url_.ToString(env())
706  };
707 
708  MaybeLocal<Value> r = MakeCallback(cb.As<Function>(),
709  arraysize(argv),
710  argv);
711 
712  if (r.IsEmpty())
713  got_exception_ = true;
714 
715  url_.Reset();
716  have_flushed_ = true;
717  }
718 
719 
720  void Init(enum http_parser_type type) {
721  http_parser_init(&parser_, type);
722  url_.Reset();
723  status_message_.Reset();
724  num_fields_ = 0;
725  num_values_ = 0;
726  have_flushed_ = false;
727  got_exception_ = false;
728  }
729 
730 
731  http_parser parser_;
732  StringPtr fields_[32]; // header fields
733  StringPtr values_[32]; // header values
734  StringPtr url_;
735  StringPtr status_message_;
736  size_t num_fields_;
737  size_t num_values_;
740  Local<Object> current_buffer_;
743  StreamResource::Callback<StreamResource::AllocCb> prev_alloc_cb_;
744  StreamResource::Callback<StreamResource::ReadCb> prev_read_cb_;
745  int refcount_ = 1;
746  static const struct http_parser_settings settings;
747 
748  friend class ScopedRetainParser;
749 };
750 
751 
752 const struct http_parser_settings Parser::settings = {
753  Parser::on_message_begin,
754  Parser::on_url,
755  Parser::on_status,
756  Parser::on_header_field,
757  Parser::on_header_value,
758  Parser::on_headers_complete,
759  Parser::on_body,
760  Parser::on_message_complete,
761  nullptr, // on_chunk_header
762  nullptr // on_chunk_complete
763 };
764 
765 
766 void InitHttpParser(Local<Object> target,
767  Local<Value> unused,
768  Local<Context> context,
769  void* priv) {
770  Environment* env = Environment::GetCurrent(context);
771  Local<FunctionTemplate> t = env->NewFunctionTemplate(Parser::New);
772  t->InstanceTemplate()->SetInternalFieldCount(1);
773  t->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "HTTPParser"));
774 
775  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "REQUEST"),
776  Integer::New(env->isolate(), HTTP_REQUEST));
777  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "RESPONSE"),
778  Integer::New(env->isolate(), HTTP_RESPONSE));
779  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnHeaders"),
780  Integer::NewFromUnsigned(env->isolate(), kOnHeaders));
781  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnHeadersComplete"),
782  Integer::NewFromUnsigned(env->isolate(), kOnHeadersComplete));
783  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnBody"),
784  Integer::NewFromUnsigned(env->isolate(), kOnBody));
785  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnMessageComplete"),
786  Integer::NewFromUnsigned(env->isolate(), kOnMessageComplete));
787  t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnExecute"),
788  Integer::NewFromUnsigned(env->isolate(), kOnExecute));
789 
790  Local<Array> methods = Array::New(env->isolate());
791 #define V(num, name, string) \
792  methods->Set(num, FIXED_ONE_BYTE_STRING(env->isolate(), #string));
793  HTTP_METHOD_MAP(V)
794 #undef V
795  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "methods"), methods);
796 
797  AsyncWrap::AddWrapMethods(env, t);
798  env->SetProtoMethod(t, "close", Parser::Close);
799  env->SetProtoMethod(t, "execute", Parser::Execute);
800  env->SetProtoMethod(t, "finish", Parser::Finish);
801  env->SetProtoMethod(t, "reinitialize", Parser::Reinitialize);
802  env->SetProtoMethod(t, "pause", Parser::Pause<true>);
803  env->SetProtoMethod(t, "resume", Parser::Pause<false>);
804  env->SetProtoMethod(t, "consume", Parser::Consume);
805  env->SetProtoMethod(t, "unconsume", Parser::Unconsume);
806  env->SetProtoMethod(t, "getCurrentBuffer", Parser::GetCurrentBuffer);
807 
808  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "HTTPParser"),
809  t->GetFunction());
810 }
811 
812 } // anonymous namespace
813 } // namespace node
814 
815 NODE_MODULE_CONTEXT_AWARE_BUILTIN(http_parser, node::InitHttpParser)
StreamResource::Callback< StreamResource::AllocCb > prev_alloc_cb_
bool got_exception_
bool HasInstance(Local< Value > val)
Definition: node_buffer.cc:201
unsigned char * buf
Definition: cares_wrap.cc:483
#define V(num, name, string)
StringPtr status_message_
NODE_MODULE_CONTEXT_AWARE_BUILTIN(inspector, node::inspector::Agent::InitInspector)
int len
Definition: cares_wrap.cc:485
QueryWrap * wrap
Definition: cares_wrap.cc:478
Local< Object > current_buffer_
size_t num_values_
union node::cares_wrap::@8::CaresAsyncData::@0 data
bool have_flushed_
bool on_heap_
const char * str_
char * current_buffer_data_
size_t current_buffer_len_
int refcount_
size_t Length(Local< Value > val)
Definition: node_buffer.cc:227
#define HTTP_DATA_CB(name)
size_t num_fields_
char * Data(Local< Value > val)
Definition: node_buffer.cc:211
dtrace p
Definition: v8ustack.d:615
dtrace s
Definition: v8ustack.d:615
dtrace t
Definition: v8ustack.d:582
http_parser parser_
size_t size_
MaybeLocal< Object > New(Isolate *isolate, Local< String > string, enum encoding enc)
Definition: node_buffer.cc:241
MaybeLocal< Value > MakeCallback(Isolate *isolate, Local< Object > recv, Local< Function > callback, int argc, Local< Value > *argv, async_id asyncId, async_id triggerAsyncId)
Definition: async-wrap.cc:802
StringPtr url_
#define HTTP_CB(name)
StringPtr fields_[32]
this ctx
Definition: v8ustack.d:369
StringPtr values_[32]
void Init(int *argc, const char **argv, int *exec_argc, const char ***exec_argv)
Definition: node.cc:4351
MaybeLocal< Object > Copy(Isolate *isolate, const char *data, size_t length)
Definition: node_buffer.cc:320
StreamResource::Callback< StreamResource::ReadCb > prev_read_cb_