I have a function that returns a response depending on the method and the path of the request.
When I use strcmp(method, "GET")
it gives me -67
, even if the method is exactly the same (I used printf()
to see the value of method), it only works with path.
char *handle_response(char *method, char *path, char *protocol) {
char *response;
//strcmp
if (strcmp(method, "GET") == 0 && strcmp(path, "/") == 0) {
response = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nhola\n";
} else {
printf("Failed strcmp\n");
printf("%s\n", method);
printf("%s\n", path);
printf("%d\n", strcmp(method, "GET"));
printf("%d\n", strcmp(path, "/"));
}
//strstr OK
if (strstr(method, "GET") && strstr(path, "/")) {
response = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nhola\n";
} else {
response = "HTTP/1.1 404 Not Found\r\nContent-Type: text/plain\r\n\r\n404 Not Found";
}
return response;
}
I was able to make it work using strstr()
, but it doesn't make any sense to me.
I call the handle_response()
function after parsing the request:
int http_parser(char *client_socket) {
char request[BUFFER_SIZE];
char *method;
char *protocol;
char *path;
strncpy(request, client_socket, sizeof(request));
char *token = strtok(request, " ");
if (token == NULL) {
printf("\nInvalid Request Format!");
return 0;
}
//METODO
method = token;
if (token == NULL) {
printf("Invalid Request Method!\n");
return 0;
}
//PATH
token = strtok(NULL, " ");
path = token;
if (token == NULL) {
printf("Invalid Request Path\n");
return 0;
}
//PROTOCOL
token = strtok(NULL, "\n");
protocol = token;
if (token == NULL) {
printf("Invalid Request Protocol\n");
return 0;
}
//FUNCTION CALLING handling_response()
int client_fd = *client_socket;
void *response = (void *)handle_response(method, path, protocol);
send(client_fd, response, strlen(response), 0);
return 1;
}
There are multiple problems in the code:
strncpy(request, client_socket, sizeof(request))
will not null terminate the string stored in request
is the source string length is greater or equal to sizeof(request)
. strncpy
is a false friend, do not use this function, use strlcpy
instead.
there is a redundant test for Invalid Request Method
. Store the return value of strtok()
to the corresponding variable instead of using an intermediary variable token
.
it is not obvious why the calls to strcmp
in handle_response
fail to return 0
, but your printf
formats do not allow you to see if there is any white space after GET
or /
that would explain the return values. I suggest you use this for debugging:
printf("Failed strcmp:\n");
printf("|%s| -> %d\n", method, strcmp(method, "GET"));
printf("|%s| -> %d\n", path, strcmp(path, "/"));
strstr
sill return a non null pointer if the first string contains the second, eg: strstr("GET\t", "GET")
.
it would help to print the client_socket
string in case of failure: return NULL
if the comparison fails and test for error in http_parser
to output the original string.
Here is a modified version:
const char *handle_response(const char *method, const char *path, const char *protocol) {
if (strcmp(method, "GET") == 0 && strcmp(path, "/") == 0) {
return "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nhola\n";
} else {
printf("Failed strcmp:\n");
printf("|%s| -> %d\n", method, strcmp(method, "GET"));
printf("|%s| -> %d\n", path, strcmp(path, "/"));
return "HTTP/1.1 404 Not Found\r\nContent-Type: text/plain\r\n\r\n404 Not Found";
}
}
int http_parser(const char *client_socket) {
char request[BUFFER_SIZE];
// copy the string with truncation
size_t len = strlen(client_socket);
if (len >= sizeof(request)) {
len = sizeof(request) - 1;
}
memcpy(request, client_socket, len);
request[len] = '\0';
char *method = strtok(request, " ");
if (method == NULL) {
printf("\nInvalid Request Format!");
return 0;
}
char *path = strtok(NULL, " ");
if (path == NULL) {
printf("Invalid Request Path\n");
return 0;
}
char *protocol = strtok(NULL, "\n");
if (protocol == NULL) {
printf("Invalid Request Protocol\n");
return 0;
}
int client_fd = *client_socket;
const char *response = handle_response(method, path, protocol);
send(client_fd, response, strlen(response), 0);
return 1;
}