Home > OS >  C Socket programming HTTP request: bad request after successful request
C Socket programming HTTP request: bad request after successful request

Time:02-28

I am learning socket programming using C. I am trying to make HTTP request and get its response.

I put the response into a file called "response.txt". Since I have no idea how long the response will be, I put the recv() inside a while loop, append the received content to "response.txt", and break the loop when the socket receives 0 bytes.

The question I have is that I am receiving 2 responses. One is "HTTP/1.1 200 OK", another one is "HTTP/1.1 400 Bad Request".

I want to know why this happen. Is it because there is some unwanted bug in my code, or is it because of some networking or protocol design?

This is the part of the code related to http requests.

// create socket
int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct hostent *server = gethostbyname(www_ip); // www_ip is command line argument
struct sockaddr_in addr; 
memset(&addr, 0, sizeof(addr)); 
addr.sin_family = AF_INET; 
addr.sin_addr.s_addr = * (unsigned long *) server->h_addr_list[0];
addr.sin_port = htons(80);
// connect
int connection_status = connect(sockfd, (struct sockaddr *) &addr, sizeof(addr));

// sending HTTP request
char test_msg[] = "GET /code/romeo.txt HTTP/1.1\r\nHost: www.py4inf.com\r\n\r\n";
int byte_sent;
byte_sent = send(sockfd, test_msg, sizeof(test_msg), 0);

// receiving HTTP response
char recv_data[1000];
int byte_recv;
FILE* fp = fopen("response.txt", "a");
while (1){
    byte_recv = recv(sockfd, &recv_data, 1000, 0);
    if (byte_recv == -1) {
        exit(-1);
    }
    if (byte_recv == 0) {
        break;
    }
    fputs(recv_data, fp);
}
fclose(fp);

// close connection
close(sockfd);

This is the content in response.txt.

The line "Who is already sick and pale with grief" supposed to be the last line of the requested file. But after that there is a "HTTP/1.1 400 Bad Request"

HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 167
Connection: keep-alive
Keep-Alive: timeout=15
Date: Sun, 27 Feb 2022 16:38:11 GMT
Server: Apache
Last-Modified: Fri, 04 Dec 2015 19:05:04 GMT
ETag: "a7-526172f58b800"
Accept-Ranges: bytes
Cache-Control: max-age=604800, public
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: origin, x-requested-with, content-type
Access-Control-Allow-Methods: GET

But soft what light through yonder window breaks
It is the east and Juliet is the sun
Arise fair sun and kill the envious moon
Who is already sick and pale with grief
HTTP/1.1 400 Bad Request
Server: nginx
Date: Sun, 27 Feb 2022 16:38:11 GMT
Content-Type: text/html
Content-Length: 150
Connection: close

<html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<hr><center>nginx</center>
</body>
</html>
c
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: origin, x-requested-with, content-type
Access-Control-Allow-Methods: GET

But soft what light through yonder window breaks
It is the east and Juliet is the sun
Arise fair sun and kill the envious moon
Who is already sick and pale with grief

CodePudding user response:

char test_msg[] = "GET /code/romeo.txt HTTP/1.1\r\nHost: www.py4inf.com\r\n\r\n";
int byte_sent;
byte_sent = send(sockfd, test_msg, sizeof(test_msg), 0);

sizeof(test_msg) is the length of the request plus one. This means it will send not only the request but also the \0 for the end of the string. This will be read as the next - and wrong request.

Instead of sizeof(test_msg) use strlen(test_msg) - which gives the size of the string and not the string buffer.

  • Related