spacer
spacer

libcurl

A common method for accessing Hypertext Transfer Protocol (HTTP) 1) 2) based services using C/C++ is using libcurl 3). Since REST Web Services are based on HTTP, libcurl can be used to access any REST service.

Installation

The libcurl library is installed via:

  1. System package manager install/update the appropriate package, for example libcurl for Debain based Linux systems (e.g. Ubuntu or Bio-Linux). Depending on the package system it may be necessary to install a seperate development package to be able to compile clients which use libcurl.
  2. Downloading the libcurl distribution and installing manually

HTTP GET

HTTP GET is simplest of the HTTP requests and is used to get a document given a URL. So to use a GET the URL of the required Web Service resource is needed. Depending on the service this may be a static URL or more commonly the URL has to be constructed based on the parameters for the request. The following examples illustrate the process using the dbfetch and WSDbfetch (REST) services.

dbfetch

The dbfetch service (http://www.ebi.ac.uk/cgi-bin/dbfetch) provides a generic interface to retrieve data entries given an identifier (Id or accession) from a wide range of biological databases available at EMBL-EBI. Two styles of URL can be used to access dbfetch:

  1. Parametrised URL:
    http://www.ebi.ac.uk/cgi-bin/dbfetch?db={DB}&id={IDS}&format={FORMAT}&style={STYLE}
  2. Document style URL:
    http://www.ebi.ac.uk/Tools/webservices/rest/dbfetch/{DB}/{IDS}/{FORMAT}

The dbfetch documentation (http://www.ebi.ac.uk/cgi-bin/dbfetch) details the valid values for the database name ({DB}), data format ({FORMAT}) and data style ({STYLE}). The identifier list ({IDS}) is a comma separated list of entry identifiers. The identifiers can be either Ids, names or accessions. For example to retrieve the rat and mouse WAP proteins from UniProtKB:

  1. Parametrised URL:
    http://www.ebi.ac.uk/cgi-bin/dbfetch?db=uniprotkb&id=WAP_RAT,WAP_HUMAN&format=uniprot&style=raw
  2. Document style URL:
    http://www.ebi.ac.uk/Tools/webservices/rest/dbfetch/uniprotkb/WAP_RAT,WAP_MOUSE/uniprot

For example fetching ADH1A_HUMAN from UniProtKB (examples/REST/libcurl/dbfetch_libcurl_get.c):

/* Include libraries */
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
 
int main(int argc, char* argv[])
{
  /* Exit status to return */
  int exitStatus = 0;
  /* Base URL for the service */
  const char* baseUrl = "http://www.ebi.ac.uk/Tools/webservices/rest/dbfetch";
  // Parameters for call
  const char* db = "UNIPROT";
  const char* id = "ADH1A_HUMAN";
  const char* format = "fasta";
 
  /* Construct resource URL */
  int urlLen = strlen(baseUrl) + strlen(db) + strlen(id) + 4;
  if(strlen(format) > 0) {
    urlLen += strlen(format);
  }
  char* url = (char*)malloc(sizeof(char) * (urlLen));
  if(url == NULL) {
    printf("Error: unable to allocate memory for URL\n");
  }
  strcpy(url, baseUrl);
  strncat(url, "/", 1);
  strncat(url, db, strlen(db));
  strncat(url, "/", 1);
  strncat(url, id, strlen(id));
  if(strlen(format) > 0) {
    strncat(url, "/", 1);
    strncat(url, format, strlen(format));
  }
 
  /* Initialise libcurl */
  curl_global_init(CURL_GLOBAL_ALL);
  char* curlErrStr = (char*)malloc(CURL_ERROR_SIZE);
  /* Get a curl handle */
  CURL* curlHandle = curl_easy_init(); 
  if(curlHandle) {
    curl_easy_setopt(curlHandle, CURLOPT_ERRORBUFFER, curlErrStr);
    /* Get resouce from URL and send to STDOUT */
    curl_easy_setopt(curlHandle, CURLOPT_URL, url);
    CURLcode curlErr = curl_easy_perform(curlHandle);
    if(curlErr) {
      printf("%s\n", curl_easy_strerror(curlErr));
    }
    /* Clean-up libcurl */
    curl_global_cleanup();
  }
  else {
    exitStatus = 1;
  }
  free(url);
  /* Return the exit status */
  return exitStatus;
}

examples/REST/libcurl/dbfetch_libcurl_get.c.

HTTP POST

While HTTP GET is great for retrieving information there are restrictions on the amount of data that can be sent using GET. Thus for transferring large amounts of data or complex parameters an alternative method has to be used. Since HTTP POST sends the data independently of the URL, POST is used in circumstances where complex or large data needs to be transferred.

dbfetch

The dbfetch service accepts HTTP POST requests as well as HTTP GET requests, this is useful when using list of identifiers.

For example fetching WAP_MOUSE and WAP_RAT from UniProtKB (examples/REST/libcurl/dbfetch_libcurl_post.c):

/* Include libraries */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
 
int main(int argc, char* argv[])
{
  /* Exit status to return */
  int exitStatus = 0;
  /* Endpoint for POST */
  const char* endpointUrl = "http://www.ebi.ac.uk/cgi-bin/dbfetch";
  // Parameters for call
  const char* db = "UNIPROT";
  const char* id = "WAP_MOUSE,WAP_RAT";
  const char* format = "fasta";
  const char* style = "raw";
  /* Construct resource POST data */
  int postDataLen = strlen(db) + strlen(id) + 26;
  if(strlen(format) > 0) {
    postDataLen += strlen(format);
  }
  if(strlen(style) > 0) {
    postDataLen += strlen(style);
  }
  char* postData = (char*)malloc(sizeof(char) * (postDataLen));
  if(postData == NULL) {
    printf("Error: unable to allocate memory for POST data\n");
  }
  strcpy(postData, "db=");
  strncat(postData, db, strlen(db));
  strncat(postData, "&id=", 4);
  strncat(postData, id, strlen(id));
  if(strlen(format) > 0) {
    strncat(postData, "&format=", 8);
    strncat(postData, format, strlen(format));
  }
  if(strlen(style) > 0) {
    strncat(postData, "&style=", 8);
    strncat(postData, style, strlen(style));
  }
  /* printf("%s\n", postData); */
 
  /* Initialise libcurl */
  curl_global_init(CURL_GLOBAL_ALL);
  char* curlErrStr = (char*)malloc(CURL_ERROR_SIZE);
  /* Get a curl handle */
  CURL* curlHandle = curl_easy_init(); 
  if(curlHandle) {
    curl_easy_setopt(curlHandle, CURLOPT_ERRORBUFFER, curlErrStr);
    /* Set the endpoint to send the POST to */
    curl_easy_setopt(curlHandle, CURLOPT_URL, endpointUrl);
    /* Specify the POST data */
    curl_easy_setopt(curlHandle, CURLOPT_POSTFIELDS, postData);
    /* Execute the POST, response goes to STDOUT */
    CURLcode curlErr = curl_easy_perform(curlHandle);
    /* Report any errors */
    if(curlErr) {
      printf("%s\n", curl_easy_strerror(curlErr));
    }
    /* Clean-up libcurl */
    curl_global_cleanup();
  }
  else {
    exitStatus = 1;
  }
  free(postData);
  /* Return the exit status */
  return exitStatus;
}

examples/REST/libcurl/dbfetch_libcurl_post.c.


Up C/C++ Contents Contents
1) RFC1945 - Hypertext Transfer Protocol – HTTP/1.0 - http://www.faqs.org/rfcs/rfc1945.html
2) RFC2616 - Hypertext Transfer Protocol – HTTP/1.1 - http://www.faqs.org/rfcs/rfc2616.html
 
tutorials/06_programming/c_cpp/rest/libcurl.txt · Last modified: 2010/09/17 09:33 by hpm
spacer
spacer