• Advertisement
Sign in to follow this  

GET or POST url in any language

This topic is 3953 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Recently I have been looking at the different ways to create a web service. I am not talking about a web page service, but a service that could be used by an application, like when you put a CD in your computer and it downloads the track names. I have looked at rcp, xml-rpc, SOAP, REST, JSON-RPC, and custom peer-to-peer. Of all these choices, the RESTful web-service is the most interesting. An example of getting some information from java looks like this...
import java.io.BufferedInputStream;
import java.io.StringWriter;
import java.net.URL;
import java.net.URLConnection;

public class UrlTest {

    public static void main( String[] args ) throws Exception {
        URLConnection conn = new URL("http://www.gamedev.net").openConnection();
        BufferedInputStream in = new BufferedInputStream(conn.getInputStream());
        StringWriter out = new StringWriter();
        int read;
        while((read = in.read()) != -1) {
            out.write(read);
        }
        System.out.println(out.toString());
    }

}

It is amazing that you can get information in this way without messing with connections, ports, sockets, threads, etc... Now I realize that getting the webpage is a neat trick, but if that URL returned some data in xml, you have a service. So my question is, does anyone out there know how do this in C++. I spent some time looking at libraries, but I could not find one that I liked. I am sure the right library is out there, I just don't know what it is. If you have ever done this in C++, please share it with us. Thanks

Share this post


Link to post
Share on other sites
Advertisement
libcurl

Quote:

libcurl is a free and easy-to-use client-side URL transfer library, supporting FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE and LDAP. libcurl supports SSL certificates, HTTP POST, HTTP PUT, FTP uploading, HTTP form based upload, proxies, cookies, user+password authentication (Basic, Digest, NTLM, Negotiate, Kerberos4), file transfer resume, http proxy tunneling and more!

libcurl is highly portable, it builds and works identically on numerous platforms, including Solaris, NetBSD, FreeBSD, OpenBSD, Darwin, HPUX, IRIX, AIX, Tru64, Linux, UnixWare, HURD, Windows, Amiga, OS/2, BeOs, Mac OS X, Ultrix, QNX, OpenVMS, RISC OS, Novell NetWare, DOS and more...

libcurl is free, thread-safe, IPv6 compatible, feature rich, well supported, fast, thoroughly documented and is already used by many known, big and successful companies and numerous applications.


and I suppose a sample couldn't hurt...


#include <stdio.h>
#include <curl/curl.h>

int main(void)
{
CURL *curl;
CURLcode res;

curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "curl.haxx.se");
res = curl_easy_perform(curl);

/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}


Share this post


Link to post
Share on other sites
Well, it's certainly doable, but a total pain in the butt using straight C++ - libcurl is certainly an easier alternative... BUT - if you want a straight implementation - here's a win32 version (I also have a linux version if you want that also):


#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <winsock2.h>
#include <errno.h>

/** be sure to include wsock32.lib library! **/
#pragma comment (lib, "wsock32.lib")

/** function prototypes **/
char *extendString(char *currentString, int numExtra);
char *getRequest(char *host, char *request, char *username, char *password);

/**
* a simple main to test the code
*/

void main() {
// you need to startup the winsock library!
WSAData wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);

char *retText=getRequest("www.test.com", "index.html");

if (retText) {
printf("OK:\nText: %s\n\n", retText);
delete retText;
} else {
printf("Error retrieving text!\n";
}
// and cleanup the winsock library...
WSACleanup();
}

/**
* Extends the string by numExtra bytes and returns a new string
*/

char *extendString(char *currentString, int numExtra) {
// make sure we have proper parameters
if (!currentString || (numExtra < 1)) return NULL;

// get the new string allocation length
int currentLen=strlen(currentString);
int newLen=currentLen+numExtra+1;

// create the new string
char *newString=new char[newLen];
if (!newString) return NULL;

// copy the old string into the new one
sprintf(newString, "%s\0", currentString);
return newString;
}


/**
* our main function:
* takes a host and the request line
* and fetches the data from the server.
*
* returns NULL on failure.
*/

char *getRequest(char *host, char *request) {
// ensure we have valid parameters
if (!host || !request) return NULL;

// open a connection to the host
int socketID;
struct sockaddr_in serverSocket;
struct hostent *serverIP;

memset ((char *) &serverSocket, 0, sizeof (serverSocket));

// make sure we can get the host's IP address
if ((serverIP = gethostbyname (host))==NULL) return NULL;

// setup our socket parameters
serverSocket.sin_family = AF_INET;
memcpy (&(serverSocket.sin_addr.s_addr), serverIP->h_addr_list[0], serverIP->h_length);

// set our socket for port 80
serverSocket.sin_port = htons (80);

// create the socket
if ((socketID = socket (AF_INET, SOCK_STREAM, 0)) < 0) return NULL;

// connect to the HTTP server
if (connect (socketID, (struct sockaddr *) &serverSocket, sizeof (serverSocket)) < 0) return NULL;

// create our return char[]
// and initialize it with nothing
char *retVal=new char[1];
retVal[0]=0;

// keep a counter of how many bytes we've allocated...
int currentRetValAlloc=1;

// create our GET command
// make sure to use the "Host:" command if there's the
// possibility of the website hosted with virtual hosting
// and and emulate Mozilla 4.0 compatibility
char getCmd[2048];
sprintf(getCmd, "GET %s HTTP/1.1\nHost: %s:80\nUser-Agent: Mozilla/4.0 (compatible)\n\n", request, host);

// send our GET command
if (sendto (socketID, getCmd, strlen(getCmd), 0, (struct sockaddr *) &serverSocket, sizeof(serverSocket)) < 0) {
closesocket(socketID);
delete retVal;
return NULL;
}

// get the response
// header and all

// create a temp buffer to read into
char tmpReadBuffer[8192];
memset(tmpReadBuffer, 0, 8192);

int nread=0;

// our read loop
while ((nread = recvfrom (socketID, tmpReadBuffer, 8192, 0, NULL, NULL)) > 0) {
// get the length of the current string
// to see if we need to extend it
int currentLen=strlen(retVal);
if ((currentLen+nread) > (currentRetValAlloc-1)) {
// yes - extend it...
char *tmpExtent=extendString(retVal, nread);
if (!tmpExtent) {
// error - abort.
closesocket(socketID);
delete retVal;
return NULL;
}

// replace the old one with the new
delete retVal;
retVal=tmpExtent;

// and add our additional length to the counter
currentRetValAlloc+=nread;
}
// concatenate the new string to the end
strncat(retVal, tmpReadBuffer, nread);
// clear our buffer (just in case)
memset(tmpReadBuffer, 0, 8192);
}

// close the socket
closesocket(socketID);

// return the buffer - caller is responsible
// for deleting the return value
return retVal;
}


Share this post


Link to post
Share on other sites
Yikes. A lot of allocation errors in that one. Why, oh why not use the STL?

Share this post


Link to post
Share on other sites
Quote:
Original post by DJHoy
Well, it's certainly doable, but a total pain in the butt using straight C++ - libcurl is certainly an easier alternative...


Using the pure C++ code is realy a pain, isn't it. RESTful web services don't look so great if it is not easy to call them.

Quote:
Original post by drowner
and I suppose a sample couldn't hurt...


Thats what I was looking for. A simple C++ wrapper around that library and it could be really easy.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement