Make content-length not buggy as hell
This commit is contained in:
parent
30fe078447
commit
5bbda3dd24
|
@ -47,7 +47,7 @@ struct http_message build_basic_request(const char *method, const char *host, co
|
|||
|
||||
int path_length = strlen(path) + 1;
|
||||
message.path = malloc(path_length * sizeof(char));
|
||||
strcpy(message.path, host);
|
||||
strcpy(message.path, path);
|
||||
|
||||
const char *request_line_components[] = {method, " ", path, " ", HTTP_VERSION, "\r\n"};
|
||||
const char *host_header[] = {"Host: ", host, "\r\n"};
|
||||
|
@ -122,8 +122,12 @@ char *send_request(struct http_message req) {
|
|||
}
|
||||
|
||||
send(socket_fd, req.contents, strlen(req.contents), 0);
|
||||
char * remote_parts = get_all_remote_parts(socket_fd);
|
||||
struct http_message res;
|
||||
memset(&res, 0, sizeof(struct http_message));
|
||||
enum socket_read_result result = get_all_remote_parts(socket_fd, &res);
|
||||
printf("result: %d\n", result);
|
||||
printf("%s", res.contents);
|
||||
close(socket_fd);
|
||||
|
||||
return remote_parts;
|
||||
return res.contents;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "http_types.h"
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
@ -14,13 +15,14 @@ static char *strcpy_lstrip(char *dest, const char *src) {
|
|||
char *dest_cursor;
|
||||
const char *src_cursor;
|
||||
bool non_whitespace_hit = false;
|
||||
for (dest_cursor = dest, src_cursor = src; *src_cursor != '\0'; (dest_cursor++, src_cursor++)) {
|
||||
for (dest_cursor = dest, src_cursor = src; *src_cursor != '\0'; src_cursor++) {
|
||||
if (non_whitespace_hit || !(*src_cursor == ' ' || *src_cursor == '\t')) {
|
||||
*dest_cursor = *src_cursor;
|
||||
} else {
|
||||
non_whitespace_hit = true;
|
||||
*dest_cursor = *src_cursor;
|
||||
dest_cursor++;
|
||||
}
|
||||
}
|
||||
*dest_cursor = '\0';
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
@ -43,7 +45,7 @@ struct http_header *insert_header(const char *header_name, const char *header_va
|
|||
new_header->name = malloc(name_length * sizeof(char));
|
||||
strcpy(new_header->name, header_name);
|
||||
|
||||
int contents_length = strlen(header_name) + 1;
|
||||
int contents_length = strlen(header_value) + 1;
|
||||
new_header->value = malloc(contents_length * sizeof(char));
|
||||
strcpy_lstrip(new_header->value, header_value);
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "socket_helper.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
@ -47,24 +48,26 @@ static struct line_read_result read_line(const char *buffer, int buffer_size, st
|
|||
|
||||
int line_length = 0;
|
||||
const char *header_delim = NULL;
|
||||
const char *prev_cursor = NULL;
|
||||
for (const char *cursor = buffer; cursor != line_terminator; (cursor++, line_length++)) {
|
||||
if (*cursor == ':') {
|
||||
if (header_delim == NULL && *cursor == ':') {
|
||||
header_delim = cursor;
|
||||
}
|
||||
prev_cursor = cursor;
|
||||
}
|
||||
|
||||
struct line_read_result result;
|
||||
// If the last character was a \r, we must have a CRLF sequence.
|
||||
if (prev_cursor != NULL && *prev_cursor == '\r') {
|
||||
result.line_type = RESULT_BLANK_LINE;
|
||||
} else if (header_delim != NULL) {
|
||||
result.line_type = RESULT_HEADER_LINE;
|
||||
// Add the space for the \n
|
||||
int line_size = line_length + 1;
|
||||
result.line = malloc((line_size + 1) * sizeof(char));
|
||||
memcpy(result.line, buffer, line_size);
|
||||
result.line[line_size] = '\0';
|
||||
result.bytes_read = line_size;
|
||||
if (header_delim != NULL) {
|
||||
result.line_type = RESULT_HEADER;
|
||||
int name_size = header_delim - buffer;
|
||||
char *header_name = malloc((name_size + 1) * sizeof(char));
|
||||
// Start of the buffer + the number of bytes read - 1 for the \r
|
||||
// Need to subtract \r\n and colon.
|
||||
// TODO: Support line-continued headers
|
||||
int value_size = (line_terminator - buffer) + line_length - 1;
|
||||
int value_size = line_size - name_size - 3;
|
||||
char *header_value = malloc((value_size + 1) * sizeof(char));
|
||||
memcpy(header_name, buffer, name_size);
|
||||
header_name[name_size] = '\0';
|
||||
|
@ -77,16 +80,10 @@ static struct line_read_result read_line(const char *buffer, int buffer_size, st
|
|||
}
|
||||
free(header_value);
|
||||
free(header_name);
|
||||
} else if (strcmp(result.line, "\r\n") == 0) {
|
||||
result.line_type = RESULT_BLANK_LINE;
|
||||
} else {
|
||||
result.line_type = RESULT_START_LINE;
|
||||
}
|
||||
// Add the space for the \n
|
||||
int line_size = line_length + 1;
|
||||
result.line = malloc((line_size + 1) * sizeof(char));
|
||||
memcpy(result.line, buffer, line_size);
|
||||
result.line[line_size] = '\0';
|
||||
result.bytes_read = line_size;
|
||||
if (result.line_type == RESULT_START_LINE) {
|
||||
message->start_line = malloc((line_size + 1) * sizeof(char));
|
||||
strcpy(message->start_line, result.line);
|
||||
message->start_line = result.line;
|
||||
|
@ -106,7 +103,6 @@ static struct socket_read_info get_read_info(const struct http_header *headers)
|
|||
const struct http_header *header_cursor = headers;
|
||||
struct socket_read_info info = {STRATEGY_EOF, -1};
|
||||
while (header_cursor != NULL) {
|
||||
header_cursor = header_cursor->next_header;
|
||||
if (headercmp(header_cursor, HEADER_TRANSFER_ENCODING) == 0 &&
|
||||
case_insensitive_strcmp(header_cursor->value, ENCODING_TYPE_CHUNKED)) {
|
||||
info.strategy = STRATEGY_CHUNKED;
|
||||
|
@ -115,6 +111,7 @@ static struct socket_read_info get_read_info(const struct http_header *headers)
|
|||
info.strategy = STRATEGY_CONTENT_LENGTH;
|
||||
info.length = atoi(header_cursor->value);
|
||||
}
|
||||
header_cursor = header_cursor->next_header;
|
||||
}
|
||||
|
||||
return info;
|
||||
|
@ -126,9 +123,13 @@ static char *read_body_by_content_length(int socket_fd, int content_length) {
|
|||
int total_bytes_read = 0;
|
||||
int bytes_read = 0;
|
||||
int write_offset = 0;
|
||||
while ((total_bytes_read += bytes_read = read(socket_fd, buffer, content_length)) < content_length && bytes_read > 0) {
|
||||
memcpy(result + write_offset, buffer, content_length)
|
||||
while ((total_bytes_read += bytes_read = read(socket_fd, buffer, content_length)) <= content_length && bytes_read > 0) {
|
||||
memcpy(result + write_offset, buffer, content_length);
|
||||
write_offset += bytes_read;
|
||||
// If we've read exactly the number of bytes we need to, we don't need to wait for more data.
|
||||
if (total_bytes_read == content_length) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(buffer);
|
||||
result[total_bytes_read] = '\0';
|
||||
|
@ -144,21 +145,21 @@ enum socket_read_result get_all_remote_parts(int socket_fd, struct http_message
|
|||
ssize_t bytes_read;
|
||||
int write_offset = 0;
|
||||
bool have_start_line = false;
|
||||
bool have_blank_line = false;
|
||||
// Loop through all available info until we hit the end of the headers.
|
||||
while ((bytes_read = read(socket_fd, buffer, BUFFER_SIZE)) > 0) {
|
||||
while (!have_blank_line && (bytes_read = read(socket_fd, buffer, BUFFER_SIZE)) > 0) {
|
||||
current_result_size += bytes_read;
|
||||
//Allocate a new result buffer if we need to, otherwise grow the existing one.
|
||||
if (result == NULL) {
|
||||
result = malloc(bytes_read);
|
||||
read_cursor = result;
|
||||
} else {
|
||||
write_offset = current_result_size;
|
||||
current_result_size += bytes_read;
|
||||
result = realloc(result, current_result_size);
|
||||
}
|
||||
memcpy(result + write_offset, buffer, BUFFER_SIZE);
|
||||
memcpy(result + write_offset, buffer, bytes_read);
|
||||
struct line_read_result line_result;
|
||||
memset(&line_result, 0, sizeof(struct line_read_result));
|
||||
while ((line_result = read_line(read_cursor, result + current_result_size - read_cursor, message),
|
||||
while ((line_result = read_line(read_cursor, current_result_size, message),
|
||||
line_result.line_type != RESULT_NO_LINE)) {
|
||||
read_cursor += line_result.bytes_read;
|
||||
free(line_result.line);
|
||||
|
@ -172,6 +173,7 @@ enum socket_read_result get_all_remote_parts(int socket_fd, struct http_message
|
|||
return RESULT_MALFORMED;
|
||||
} else if (line_result.line_type == RESULT_BLANK_LINE) {
|
||||
// If we hit a blank line, we're done reading headers.
|
||||
have_blank_line = true;
|
||||
break;
|
||||
} else if (line_result.line_type == RESULT_START_LINE) {
|
||||
if (have_start_line) {
|
||||
|
@ -184,13 +186,19 @@ enum socket_read_result get_all_remote_parts(int socket_fd, struct http_message
|
|||
have_start_line = true;
|
||||
}
|
||||
}
|
||||
write_offset += current_result_size;
|
||||
}
|
||||
struct socket_read_info read_info = get_read_info(message->headers);
|
||||
char *body_result;
|
||||
if (read_info.strategy == STRATEGY_CHUNKED) {
|
||||
// TODO: Implement
|
||||
} else if (read_info.strategy == STRATEGY_CONTENT_LENGTH) {
|
||||
body_result = read_body_by_content_length(socket_fd, read_info.length);
|
||||
int header_length = read_cursor - result;
|
||||
int net_content_length = read_info.length - (current_result_size - header_length);
|
||||
// Include space for null term
|
||||
current_result_size += net_content_length + 1;
|
||||
result = realloc(result, current_result_size);
|
||||
body_result = read_body_by_content_length(socket_fd, net_content_length);
|
||||
} else {
|
||||
// TODO: Implement
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue