C Write() not writing correctly (task 5)

Hello everyone, this is my issue: answering with the user-agent works, while answering with the path and echoing the message doesn’t work. Have absolutely no idea why, the printf(message) outputs the right answer. Any help is kindly appreciated.

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

const int BUFFER_SIZE = 256;

int main() {
	// Disable output buffering
	setbuf(stdout, NULL);

	// for debugging -> printf("Logs from your program will appear here!\n");

	//declaring variables ->
	int client_fd, server_fd, client_addr_len;
	struct sockaddr_in client_addr;

	//checking possible socket creation ->
	server_fd = socket(AF_INET, SOCK_STREAM, 0); //socket descriptor
	if (server_fd == -1) {
	 	printf("Socket creation failed by server-side: %s...\n", strerror(errno));
	 	return 1;
	}

	// Since the tester restarts your program quite often, setting REUSE_PORT
	// ensures that we don't run into 'Address already in use' errors
	int reuse = 1;
	if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(reuse)) < 0) {
	 	printf("SO_REUSEPORT failed: %s \n", strerror(errno));
	 	return 1;
	}

	//socket creation server side ->
	struct sockaddr_in serv_addr = { .sin_family = AF_INET ,
	 								 .sin_port = htons(4221),
	 								 .sin_addr = { htonl(INADDR_ANY) },
	 								};

	//checking for successful binding ->
	if (bind(server_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) != 0) {
		printf("Bind failed: %s \n", strerror(errno));
	 	return 1;
	}

	//checking for successful listening ->
	int connection_backlog = 5;
	if (listen(server_fd, connection_backlog) != 0) {
	 	printf("Listen failed: %s \n", strerror(errno));
	 	return 1;
	}
	printf("Waiting for a client to connect...\n");
	client_addr_len = sizeof(client_addr);

	//accepting client from server ->
	client_fd = accept(server_fd, (struct sockaddr *) &client_addr, &client_addr_len);
	if(client_fd == -1){
		printf("Unable to accept connection, error %s \n", strerror(errno)); 
		return 1;
	}
	printf("Client connected\n");
	FILE *f = fdopen(client_fd, "r");
	char method[2048], path[2048], message[4096], host[1024], agent[1024];
  	fscanf(f, "%s %s HTTP/1.1\r\nHost: %s\r\nUser-Agent: %s", method, path, host,
         agent);

	if(strlen(path) == 1 && strncmp(path, "/", 1) == 0){ //200 response 
		sprintf(message, "HTTP/1.1 200 OK\r\n\r\n");
	}
	else if(strncmp(path, "/user-agent", 11) == 0){ //output the user agent 
		sprintf(message, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %d\r\n\r\n%s", strlen(agent), agent);
	}
	else if(strncmp(path, "/echo/", 6) == 0){//output the echo -> HERE'S THE PROBLEM
		char echoing[256];
		sscanf(path, "/echo/%s", echoing);
		sprintf(message, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %ld\r\n\r\n%s",
        	strlen(echoing), echoing);
		printf("Message: %s", message);
		write(client_fd, message, strlen(message));
	}
	else{ //output error 404 
		sprintf(message, "HTTP/1.1 404 Not Found\r\n\r\n"); 
	}

	write(client_fd, message, strlen(message));
	fclose(f); 
	close(client_fd);

	return 0;
}

And here’s the logs:

[tester::#FS3] Running tests for Stage #FS3 (Read header)
[tester::#FS3] $ ./your_server.sh
[your_program] Waiting for a client to connect...
[tester::#FS3] $ curl -v -X GET http://localhost:4221/user-agent -H "User-Agent: orange/mango"
[your_program] Client connected
[tester::#FS3] Received response with 200 status code
[tester::#FS3] ✓ Content-Type header is present
[tester::#FS3] ✓ Content-Length header is present
[tester::#FS3] ✓ Body is correct
[tester::#FS3] Test passed.
[tester::#CN2] Running tests for Stage #CN2 (Respond with body)
[tester::#CN2] $ ./your_server.sh
[your_program] Waiting for a client to connect...
[tester::#CN2] $ curl -v -X GET http://localhost:4221/echo/blueberry
[your_program] Client connected
[your_program] Message: HTTP/1.1 200 OK
[tester::#CN2] Failed to read response: 
[tester::#CN2] Received: "" (no content received)
[tester::#CN2]            ^ error
[tester::#CN2] Error: Expected: HTTP-version, Received: ""
[tester::#CN2] Test failed (try setting 'debug: true' in your codecrafters.yml to see more details)
[your_program] Content-Type: text/plain
[your_program] Content-Length: 9
[your_program] 
[your_program] blueberry

@bennynonsaprogrammare mind sharing the logs you see when you run tests on this code? Does it mention what’s broken with the response for the echo test?

I put the logs in the content of the post. The response is empty, but the message variable has the right content…

@bennynonsaprogrammare I think this might have to do with the fscanf call. This would block until a request matching that signature arrives, and I don’t think we’re sending User-Agent in other stages.

The reason your logs are printed later could be that once the connection is closed, fscanf ends up returning with an error.

I think you’d be able to verify this by checking the return value of fscanf.

Tried checking the return value of fscanf, it’s always positive. The requests in the previous stages all contain the host and the user-agent, so I don’t think that’s the problem. Trying by writing a static string, it seems that the write() function just doesn’t write anything. So the problem isn’t even in the variables.

@bennynonsaprogrammare I tried enabling debug logs and it doesn’t seem like User-Agent is sent for that stage:

Tried logging the result of fscanf and I got 3:

If User-Agent was available, the return value would’ve been 4

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.