Search code examples
chttpget

GET Request only gets empty string


I've been given an example C code, that sends user entered requests to a specified server and prints the responses. Now I should change the code, so that a HTTP Request is sent to http://www.stardrifter.org/cgi-bin/ref.cgi with a Referer header set. The request is successfully sent, but I only get empty strings in response.

I already tried to send minimal GET requests and also pasted working requests from Postman into the code, but I always only get an empty string as response. Also it actually takes quite a while until I receive a response, usually between 1 and 2 minutes.

This is my code so far. Establishing the connection seems to work fine but forming and sending the requests isn't doing what I'd expect:

#include <stdbool.h>     // use booleans in C
#include <stdlib.h>      // use common functions
#include <stdio.h>       // use input/output functions
#include <string.h>      // use string functions
#include <unistd.h>      // use POSIX functions

#include <sys/socket.h>  // use socket function
#include <netinet/in.h>  // use internet address datatypes
#include <arpa/inet.h>   // use inet_ntoa function
#include <netdb.h>       // use network database functions

int main(int argc, char *argv[]) {
    char *hostname = "stardrifter.org";
    int port = 80;

    /** -- Setup connection -- */

    // Get server host information
    struct hostent *serverInfo = gethostbyname(hostname);
    if (serverInfo == NULL) {
        printf("Failed to get info for host '%s'!\n", hostname);
        return -1;
    }

    // Create TCP/IP socket
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        printf("Failed to create socket!\n");
        return -1;
    }

    // Set address and port of server
    struct sockaddr_in serverAddr;
    serverAddr.sin_family = serverInfo->h_addrtype;
    serverAddr.sin_port = htons(port);
    memcpy(&serverAddr.sin_addr.s_addr, serverInfo->h_addr, serverInfo->h_length);

    // Connect to server
    if (connect(sock, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) < 0) {
        printf("Failed to connect to server at %s:%d!\n",
               inet_ntoa(serverAddr.sin_addr), ntohs(serverAddr.sin_port));
        return -1;
    } else {
        printf("Connected to server at %s:%d\n\n",
               inet_ntoa(serverAddr.sin_addr), ntohs(serverAddr.sin_port));
    }

    /** -- Main program -- */

    char buffer[1024];
    int len = 0;

    char *request = "GET /cgi-bin/ref.cgi HTTP/1.1\r\nHost: www.stardrifter.org\r\nReferer: I'm a Referer\r\n\r\n";

    memset(buffer, 0, 1024);
    strncpy(buffer, request, sizeof buffer - 1);

    // Send message to server
    if (send(sock, buffer, len, 0) < 0) {
        printf("Failed to send message to server!\n");
    } else {
        printf("Sent message to server: \"%s\"\n", buffer);
    }

    // Receive response from server
    printf("Waiting for response...\n");
    memset(buffer, 0, 1024);
    if (recv(sock, buffer, 1024, 0) < 0) {
        printf("Failed to receive response from server!\n");
    }

    // Print received response
    printf("Received response from server: \"%s\"\n", buffer);

    // Close socket
    close(sock);

    return 0;
}

I'd expect a valid HTTP Response with an html body, but my program only gives:

Connected to server at 69.164.214.143:80

Sent message to server: "GET /cgi-bin/ref.cgi HTTP/1.1
Host: www.stardrifter.org
Referer: I'm a Referer

"
Waiting for response...
Received response from server: ""

Process finished with exit code 0

I'm not sure, if I really get this "" as response or if there is a smth. like a timeout and then he simply reads the empty buffer.


Solution

  • You're sending zero bytes:

    char buffer[1024];
    int len = 0;
    
    char *request = "GET /cgi-bin/ref.cgi HTTP/1.1\r\nHost: www.stardrifter.org\r\nReferer: I'm a Referer\r\n\r\n";
    
    memset(buffer, 0, 1024);
    strncpy(buffer, request, sizeof buffer - 1);
    
    // Send message to server
    if (send(sock, buffer, len, 0) < 0) {
        printf("Failed to send message to server!\n");
    } else {
        printf("Sent message to server: \"%s\"\n", buffer);
    }
    

    or

    int len = 0;
    
    ...
    
    if (send(sock, buffer, len, 0) < 0) {
    ...
    

    Why are you copying the request to buffer? This works:

    ssize_t bytes_sent = send( sock, request, strlen( request ), 0 );
    

    Both send() and recv() return the number of bytes sent or received. They do the for good reasons. You need to check that returned value and make sure it's exactly what you expect.

    Also, the third argument to send() is a size_t, not an int.