Skip to content

Parser in response mode does not reset on finish #128

Closed

Description

@bryanp

I noticed some unexpected behavior when parsing responses. If the response does not include a content-length header, calling llhttp_finish does not seem to reset the parser. Here's an example:

#include <stdio.h>
#include <string.h>
#include "llhttp.h"

int handle_on_headers_complete(llhttp_t *parser) {
  printf("  headers complete\n");

  return 0;
}

int handle_on_message_begin(llhttp_t *parser) {
  printf("  message begin\n");

  return 0;
}

int handle_on_message_complete(llhttp_t *parser) {
  printf("  message complete\n");

  return 0;
}

int main (void) {
  llhttp_t parser;
  llhttp_settings_t settings;

  llhttp_settings_init(&settings);

  settings.on_headers_complete = handle_on_headers_complete;
  settings.on_message_begin = handle_on_message_begin;
  settings.on_message_complete = handle_on_message_complete;

  llhttp_init(&parser, HTTP_RESPONSE, &settings);

  const char* data = "HTTP/1.1 200 OK\r\n\r\n";
  int data_len = strlen(data);
  enum llhttp_errno err;
  int i = 0;

  while (i < 3) {
    printf("parsing\n");

    err = llhttp_execute(&parser, data, data_len);

    if (err == HPE_OK) {
      // all good
    } else {
      fprintf(stderr, "  ! %s %s\n", llhttp_errno_name(err), parser.reason);
    }

    llhttp_finish(&parser);

    i++;
  }
}

Output:

parsing
  message begin
  headers complete
  message complete
parsing
  message complete
parsing
  message complete

I'd expect to see this:

parsing
  message begin
  headers complete
  message complete
parsing
  message begin
  headers complete
  message complete
parsing
  message begin
  headers complete
  message complete

Activity

  1. pallas commented on Sep 9, 2021

    @pallas
    Contributor

    I think this is expected, but willing to be shown otherwise. Without a content-length, the parser has no way to know the length of the response. The point of llhttp_finish is not to reset the parser, it's to figure out the final state of the current parse, possibly based on a call to on_message_complete. Once you are done with the parser, to reuse it you need to call llhttp_reset to put it back in its initial state, preserving any flags, callbacks, & cookies you've set on it.

  2. bryanp commented on Sep 9, 2021

    @bryanp
    Author

    Ah, the issue is with my implementation. Thank you for pointing me in the right direction, I already have things fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions