Skip to content

Commit

Permalink
Adds support for Content-Encoding: gzip to in_http
Browse files Browse the repository at this point in the history
Signed-off-by: Edmund Rhudy <[email protected]>
  • Loading branch information
erhudy committed Jul 8, 2023
1 parent fb7d4c8 commit ca3fb76
Showing 1 changed file with 68 additions and 9 deletions.
77 changes: 68 additions & 9 deletions plugins/in_http/http_prot.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@
#include <fluent-bit/flb_version.h>
#include <fluent-bit/flb_error.h>
#include <fluent-bit/flb_pack.h>
#include <fluent-bit/flb_gzip.h>

#include <monkey/monkey.h>
#include <monkey/mk_core.h>

#include <string.h>

#include "http.h"
#include "http_conn.h"

Expand Down Expand Up @@ -357,6 +360,19 @@ static int process_payload(struct flb_http *ctx, struct http_conn *conn,
{
int type = -1;
struct mk_http_header *header;
struct mk_http_header *extra_headers;
char *extracted_extra_headers;
int content_encoding_header_location = -1;
char *uncompressed_data;
size_t uncompressed_size = 0;

/* used when checking content-encoding */
char *extracted;
int first_colon;
int first_newline;
char *content_encoding_header_value;
int content_encoding_compare = -1;
int gzip_ret;

header = &session->parser.headers[MK_HEADER_CONTENT_TYPE];
if (header->key.data == NULL) {
Expand All @@ -369,18 +385,67 @@ static int process_payload(struct flb_http *ctx, struct http_conn *conn,
type = HTTP_CONTENT_JSON;
}

/* handle gzip-encoded content */
/*
The way things come out of headers_extra is very strange; everything seems to be in
key->data of the first entry and val->data is everything minus the first header key.
The behavior of monkey seems to be pretty buggy here.
...so, we just grab the whole thing and then sift through it looking for content-encoding.
*/
if (session->parser.headers_extra_count > 0) {
extra_headers = &session->parser.headers_extra[0];
const char *content_encoding = "content-encoding";
if (extra_headers->key.data != NULL) {
extracted_extra_headers = mk_string_tolower(extra_headers->key.data);
content_encoding_header_location = mk_string_search(extracted_extra_headers, content_encoding, 0);
}
}

if (content_encoding_header_location == -1) {
uncompressed_data = request->data.data;
uncompressed_size = request->data.len;
} else {
/* Extract content-encoding and everything after up to the next \r\n to find the header value */
extracted = mk_string_copy_substr(extracted_extra_headers, content_encoding_header_location, strlen(extracted_extra_headers));
mk_mem_free(extracted_extra_headers);
first_colon = mk_string_search(extracted, ":", 0);
first_newline = mk_string_search(extracted, "\r\n", 0);

content_encoding_header_value = mk_string_copy_substr(extracted, first_colon+1, first_newline);
mk_mem_free(extracted);
mk_string_trim(&content_encoding_header_value);
content_encoding_compare = strncasecmp(content_encoding_header_value, "gzip", 5);
mk_mem_free(content_encoding_header_value);
if (content_encoding_compare == 0) {
gzip_ret = flb_gzip_uncompress(request->data.data, request->data.len, (void **)&uncompressed_data, &uncompressed_size);
if (gzip_ret == -1) {
flb_error("[http] gzip decompression failed");

return -1;
}
} else {
send_response(conn, 400, "error: invalid 'Content-Encoding'\n");
return -1;
}
}

if (type == -1) {
send_response(conn, 400, "error: invalid 'Content-Type'\n");
return -1;
}

if (request->data.len <= 0) {
if (uncompressed_size <= 0) {
send_response(conn, 400, "error: no payload found\n");
return -1;
}

if (type == HTTP_CONTENT_JSON) {
parse_payload_json(ctx, tag, request->data.data, request->data.len);
parse_payload_json(ctx, tag, uncompressed_data, uncompressed_size);
}
/* only needs to be freed if we ungzipped something */
if (content_encoding_compare == 0) {
flb_free(uncompressed_data);
}

return 0;
Expand Down Expand Up @@ -471,23 +536,18 @@ int http_prot_handle(struct flb_http *ctx, struct http_conn *conn,
}

mk_mem_free(uri);

/* Check if we have a Host header: Hostname ; port */
mk_http_point_header(&request->host, &session->parser, MK_HEADER_HOST);

/* Header: Connection */
mk_http_point_header(&request->connection, &session->parser,
MK_HEADER_CONNECTION);

/* HTTP/1.1 needs Host header */
if (!request->host.data && request->protocol == MK_HTTP_PROTOCOL_11) {
flb_sds_destroy(tag);
return -1;
}

/* Should we close the session after this request ? */
mk_http_keepalive_check(session, request, ctx->server);

/* Content Length */
header = &session->parser.headers[MK_HEADER_CONTENT_LENGTH];
if (header->type == MK_HEADER_CONTENT_LENGTH) {
Expand All @@ -497,16 +557,15 @@ int http_prot_handle(struct flb_http *ctx, struct http_conn *conn,
else {
request->_content_length.data = NULL;
}

if (request->method != MK_METHOD_POST) {
flb_sds_destroy(tag);
send_response(conn, 400, "error: invalid HTTP method\n");
return -1;
}

ret = process_payload(ctx, conn, tag, session, request);
flb_sds_destroy(tag);
send_response(conn, ctx->successful_response_code, NULL);

return ret;
}

Expand Down

0 comments on commit ca3fb76

Please sign in to comment.