github.com/moontrade/nogc@v0.1.7/net/http/README.md (about)

     1  PicoHTTPParser
     2  =============
     3  
     4  Copyright (c) 2009-2014 [Kazuho Oku](https://github.com/kazuho), [Tokuhiro Matsuno](https://github.com/tokuhirom), [Daisuke Murase](https://github.com/typester), [Shigeo Mitsunari](https://github.com/herumi)
     5  
     6  PicoHTTPParser is a tiny, primitive, fast HTTP request/response parser.
     7  
     8  Unlike most parsers, it is stateless and does not allocate memory by itself.
     9  All it does is accept pointer to buffer and the output structure, and setups the pointers in the latter to point at the necessary portions of the buffer.
    10  
    11  The code is widely deployed within Perl applications through popular modules that use it, including [Plack](https://metacpan.org/pod/Plack), [Starman](https://metacpan.org/pod/Starman), [Starlet](https://metacpan.org/pod/Starlet), [Furl](https://metacpan.org/pod/Furl).  It is also the HTTP/1 parser of [H2O](https://github.com/h2o/h2o).
    12  
    13  Check out [test.c] to find out how to use the parser.
    14  
    15  The software is dual-licensed under the Perl License or the MIT License.
    16  
    17  Usage
    18  -----
    19  
    20  The library exposes four functions: `phr_parse_request`, `phr_parse_response`, `phr_parse_headers`, `phr_decode_chunked`.
    21  
    22  ### phr_parse_request
    23  
    24  The example below reads an HTTP request from socket `sock` using `read(2)`, parses it using `phr_parse_request`, and prints the details.
    25  
    26  ```c
    27  char buf[4096], *method, *path;
    28  int pret, minor_version;
    29  struct phr_header headers[100];
    30  size_t buflen = 0, prevbuflen = 0, method_len, path_len, num_headers;
    31  ssize_t rret;
    32  
    33  while (1) {
    34      /* read the request */
    35      while ((rret = read(sock, buf + buflen, sizeof(buf) - buflen)) == -1 && errno == EINTR)
    36          ;
    37      if (rret <= 0)
    38          return IOError;
    39      prevbuflen = buflen;
    40      buflen += rret;
    41      /* parse the request */
    42      num_headers = sizeof(headers) / sizeof(headers[0]);
    43      pret = phr_parse_request(buf, buflen, &method, &method_len, &path, &path_len,
    44                               &minor_version, headers, &num_headers, prevbuflen);
    45      if (pret > 0)
    46          break; /* successfully parsed the request */
    47      else if (pret == -1)
    48          return ParseError;
    49      /* request is incomplete, continue the loop */
    50      assert(pret == -2);
    51      if (buflen == sizeof(buf))
    52          return RequestIsTooLongError;
    53  }
    54  
    55  printf("request is %d bytes long\n", pret);
    56  printf("method is %.*s\n", (int)method_len, method);
    57  printf("path is %.*s\n", (int)path_len, path);
    58  printf("HTTP version is 1.%d\n", minor_version);
    59  printf("headers:\n");
    60  for (i = 0; i != num_headers; ++i) {
    61      printf("%.*s: %.*s\n", (int)headers[i].name_len, headers[i].name,
    62             (int)headers[i].value_len, headers[i].value);
    63  }
    64  ```
    65  
    66  ### phr_parse_response, phr_parse_headers
    67  
    68  `phr_parse_response` and `phr_parse_headers` provide similar interfaces as `phr_parse_request`.  `phr_parse_response` parses an HTTP response, and `phr_parse_headers` parses the headers only.
    69  
    70  ### phr_decode_chunked
    71  
    72  The example below decodes incoming data in chunked-encoding.  The data is decoded in-place.
    73  
    74  ```c
    75  struct phr_chunked_decoder decoder = {}; /* zero-clear */
    76  char *buf = malloc(4096);
    77  size_t size = 0, capacity = 4096, rsize;
    78  ssize_t rret, pret;
    79  
    80  /* set consume_trailer to 1 to discard the trailing header, or the application
    81   * should call phr_parse_headers to parse the trailing header */
    82  decoder.consume_trailer = 1;
    83  
    84  do {
    85      /* expand the buffer if necessary */
    86      if (size == capacity) {
    87          capacity *= 2;
    88          buf = realloc(buf, capacity);
    89          assert(buf != NULL);
    90      }
    91      /* read */
    92      while ((rret = read(sock, buf + size, capacity - size)) == -1 && errno == EINTR)
    93          ;
    94      if (rret <= 0)
    95          return IOError;
    96      /* decode */
    97      rsize = rret;
    98      pret = phr_decode_chunked(&decoder, buf + size, &rsize);
    99      if (pret == -1)
   100          return ParseError;
   101      size += rsize;
   102  } while (pret == -2);
   103  
   104  /* successfully decoded the chunked data */
   105  assert(pret >= 0);
   106  printf("decoded data is at %p (%zu bytes)\n", buf, size);
   107  ```
   108  
   109  Benchmark
   110  ---------
   111  
   112  ![benchmark results](http://i.gyazo.com/a85c18d3162dfb46b485bb41e0ad443a.png)
   113  
   114  The benchmark code is from [fukamachi/fast-http@6b91103](https://github.com/fukamachi/fast-http/tree/6b9110347c7a3407310c08979aefd65078518478).
   115  
   116  The internals of picohttpparser has been described to some extent in [my blog entry]( http://blog.kazuhooku.com/2014/11/the-internals-h2o-or-how-to-write-fast.html).