Whenever I try to decompress the body of this HTTP response, BrotliDecoderDecompress returns BROTLI_DECODER_RESULT_ERROR. However, I can’t figure out what it is I’m doing wrong here.
// RECIEVE RESPONSE
char* response_buff = NULL;
size_t total_read = 0;
size_t buff_size = INITIAL_BUFF_SIZE;
response_buff = malloc(buff_size);
if (!response_buff) {
fprintf(stderr, "Failed to allocate initial buffer sizen");
return 1;
}
memset(response_buff, 0, buff_size);
int bytes_read = 0;
while (1) {
if (total_read + INITIAL_BUFF_SIZE > buff_size) {
buff_size *= 2;
char* new_buff = realloc(response_buff, buff_size);
if (!new_buff) {
fprintf(stderr, "Failed to reallocate buffern");
free(response_buff);
return 1;
}
response_buff = new_buff;
}
bytes_read = SSL_read(ssl, response_buff + total_read, INITIAL_BUFF_SIZE);
printf("bytes_read: %dn", bytes_read);
if (bytes_read <= 0) {
if (bytes_read == 0) {
printf("HTTP connection closed.n");
break;
} else {
fprintf(stderr, "Failed to read response: %sn", ERR_error_string(ERR_get_error(), NULL));
free(response_buff);
return 1;
}
}
total_read += bytes_read;
printf("total_read: %zun", total_read);
if (total_read >= 5 && memcmp(response_buff + total_read - 5, "0rnrn", 5) == 0) {
printf("Final chunk detected.n");
response_buff[total_read] = '';
break;
}
}
char* body_start = strstr(response_buff, "rnrn");
if (body_start == NULL) {
printf("body_start not found");
} else {
size_t header_length = body_start - response_buff;
printf("Headers: n%.*sn", (int)header_length, response_buff);
}
body_start += 4;
size_t body_length = total_read - (size_t)(body_start - response_buff);
printf("nbody_length: %zun", body_length);
// DECOMPRESS THE RESPONSE (FUN!)
if (strstr(response_buff, "Content-Encoding: br") != NULL) {
size_t decompressed_size = body_length * 2;
unsigned char* decompressed_data = malloc(decompressed_size);
if (!decompressed_data) {
fprintf(stderr, "Failed to allocate memory for decompressed datan");
return 1;
}
BrotliDecoderState* state = BrotliDecoderCreateInstance(NULL, NULL, NULL);
BrotliDecoderResult result = BrotliDecoderDecompress(body_length,
(const uint8_t*)body_start, &decompressed_size, decompressed_data);
if (result != BROTLI_DECODER_RESULT_SUCCESS) {
if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) {
fprintf(stderr, "Decompression failed: needs more input.n");
} else if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
fprintf(stderr, "Decompression failed: needs more output space.n");
} else if (result == BROTLI_DECODER_RESULT_ERROR) {
BrotliDecoderErrorCode error_code = BrotliDecoderGetErrorCode(state);
fprintf(stderr, "Brotli decompression error: %sn", BrotliDecoderErrorString(error_code));
}
free(decompressed_data);
BrotliDecoderDestroyInstance(state);
return 1;
}
printf("Decompressed resoponse:n%.*sn", (int)decompressed_size, decompressed_data);
free(decompressed_data);
BrotliDecoderDestroyInstance(state);
}
I’ve double checked the logic for identifying where the body starts in the HTTP response to verify that it I’m not reading before when the body begins. I’ve also used BrotliDecoderGetErrorCode(state) to see if I can get more comprehensive error codes on why this is happening. It outputs _NO_ERROR. Though I could be using this second function incorrectly as the brotli.h documentation states this:
Should be used only after BrotliDecoderDecompressStream returns BROTLI_DECODER_RESULT_ERROR.
I’m using BrotliDecoderDecompress.
Relevant output:
Headers:
HTTP/1.1 200 OK
Server: nginx
Date: Fri, 13 Dec 2024 11:00:38 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
X-Content-Type-Options: nosniff
Content-language: en
Vary: Accept-Encoding, Cookie
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Cache-Control: private, must-revalidate, max-age=0
Last-Modified: Thu, 12 Dec 2024 20:35:05 GMT
X-Request-Id: e4b08e290080977874cfd93a
Content-Encoding: br
body_length: 53604
Brotli decompression error: _NO_ERROR
ByrontheBulb is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
2