-2

I have worked with POST and GET in C# but trying to implement it in C is becoming a bit confusing for me.

I have successfully connected to a socket using 8443 port on my local machine.

Now I am trying to send a POST request, with 3 parameters to the 127.0.0.1:8443/xxxx/xxxAPI URL.

Usually in GET I can attach the query strings in my URL itself... but in POST I need a message body, contentHeader, Type etc and then my parameters.

I have a custom TCP code in C that helps me connect to the server. After successful connection I am trying to do something like the following pseudo code.... But obviously I don't know what I am doing... Can anyone guide me?

            sprintf(szBuff, "POST /xxxx/xxxxxxAPI HTTP/1.1\r\n");
            sprintf(contentHeader, "Content-Length: %d\r\n", 20);

            send(iSock, szBuff, strlen(szBuff), 0);
            send(iSock, "Accept: */*\r\n", 15, 0);
            send(iSock, "User-Agent: Mozilla/4.0\r\n", 27, 0);
            send(iSock, contentHeader, strlen(contentHeader), 0);
            send(iSock, "Accept-Language: en-us\r\n", 26, 0);
            send(iSock, "Accept-Encoding: gzip, deflate\r\n", 34, 0);
            send(iSock, "Host: ", 6, 0);
            send(iSock, "hostname", 8, 0);
            send(iSock, "\r\n", 4, 0);
            send(iSock, "Content-Type: application/x-www-form-urlencoded\r\n", 50, 0);
            send(iSock, "\r\n", 4, 0);
            send(iSock, "\r\n", 4, 0);
            send(iSock, parameters, strlen(parameters), 0);
            send(iSock, "\r\n", 4, 0);
            /*if (write(iSock, szBuff, sizeof(szBuff)) == -1)
                LogToFile("Error while request being sent to the server");*/
jotik
  • 17,044
  • 13
  • 58
  • 123
Philo
  • 1,931
  • 12
  • 39
  • 77
  • 'do{...} while(0); ' ??? – Martin James Apr 12 '16 at 16:16
  • sorry thats part of the error checking that I am not showing in the code... I removed it to avoid confusion – Philo Apr 12 '16 at 16:18
  • 1
    Those hardcoded lengths are a bad idea. And some of them are wrong. `"\r\n"` is a string of 2 characters, not 4. Also you're sending 3 consecutive `\r\n` pairs after the Content-Type, which is 1 too many. Are you sure you don't just want to use `fdopen`? –  Apr 12 '16 at 16:23
  • Try looking at [this SO Question](http://stackoverflow.com/questions/22077802/simple-c-example-of-doing-an-http-post-and-consuming-the-response) for an example of how to do this. – Icemanind Apr 12 '16 at 16:24
  • I am not sure what I should be using, I am very new to C, my primary language is C# and the skills do not necessarily transfer over.. Hence I am looking for some guidance. – Philo Apr 12 '16 at 16:24
  • 1
    don't implement http yourself. it's a huge protocol. use already existing C library – David Haim Apr 12 '16 at 16:27
  • You don't check return values of functions you are calling. Could just as well not bother calling them. No sign of reading the server response either. And please don't tell me you have sat down and manually counted the numner of characters in each string you send. – n. m. could be an AI Apr 12 '16 at 16:30
  • Hey n.m. as I said this is a pseudo code, I have not written anything substantial either. I have also not posted my pseudo code for my server response. Mock me if you will, but my question clearly states that I dont know what I am doing as of yet, which is why I am asking for help. – Philo Apr 12 '16 at 16:33
  • I presume you've not implemented a full HTTP/1.1 stack with chunking and long connections and whatnot properly, so perhaps you should add the `Connection: close` header. – Antti Haapala -- Слава Україні Apr 12 '16 at 16:52
  • 1
    If you're set on using 'C' for this I would say that your first send (`send(iSock, szBuff, strlen(szBuff), 0);`) is the model to follow, create a string to send and then send it with the `strlen()` because (trust me) the other method will fail (spectacularly) some day in the future. – KevinDTimm Apr 12 '16 at 16:55
  • @KevinDTimm should I combine everything into the szBuffer variable? – Philo Apr 12 '16 at 17:38
  • That's a style/personal decision, dependent upon your level of confidence and familiarity. Only you can make that call. note the recommendation for `libcurl` - it's usage gets rid of many of these items, it just depends upon what you want to accomplish in the 'C' world. – KevinDTimm Apr 12 '16 at 20:53
  • Your post has "C programming" in the title and tagged with the C tag. I assume your code is C. Please ask a question related to C programming, or remove the tag and the title portion. – n. m. could be an AI Apr 13 '16 at 17:45

2 Answers2

4

I suggest to use libraries something like libcurl

FargolK
  • 169
  • 1
  • 14
1

Try something more like this:

int sendStr(int iSock, const char *szStr)
{
    int ret;
    int len = strlen(szStr);
    while (len > 0) {
        ret = send(iSock, szStr, len, 0);
        if (ret == -1) {
            //LogToFile("Error while request being sent to the server");
            return -1;
        }
        szStr += ret;
        len -= ret;
    }
    return 0;
}
char szContentHeader[32];
sprintf(szContentHeader, "Content-Length: %d\r\n", strlen(parameters));

sendStr(iSock, "POST /xxxx/xxxxxxAPI HTTP/1.1\r\n");
sendStr(iSock, "Host: hostname:8443\r\n");
sendStr(iSock, "User-Agent: Mozilla/4.0\r\n");
sendStr(iSock, "Accept: */*\r\n");
sendStr(iSock, "Accept-Language: en-us\r\n");
sendStr(iSock, "Accept-Encoding: gzip, deflate\r\n");
sendStr(iSock, szContentHeader);
sendStr(iSock, "Content-Type: application/x-www-form-urlencoded\r\n");
sendStr(iSock, "\r\n");
sendStr(iSock, parameters);

Then you can read the server's response. Which in of itself can be quite involved (and outside the scope of this question) depending on how the response is sent. Refer to RFC 2616 Section 4.4 Message Length for details about that, and refer to my answer for the following question for the kind of pseudo code you would need to implement:

When is an HTTP response finished?

Community
  • 1
  • 1
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770