Skip to content

Instantly share code, notes, and snippets.

@nvurgaft
Last active November 19, 2016 17:44
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nvurgaft/8086853 to your computer and use it in GitHub Desktop.
Save nvurgaft/8086853 to your computer and use it in GitHub Desktop.
A simple HTTP/1.0 request client. This is a free software code, use fairly!
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
/*
* a simple http/1.0 client
* 2013 nvurgaft
*
* usage: httpclient -h <URL>
* -h: sends HEAD request instead of GET
* <URL>: the requested url, should start with either 'http://' or 'www.'
*/
// main
int main(int argc, char* argv[])
{
// sanity check
if (argc>3 || argc<2) {
printf("invalid argument count, format is: client [–h] <URL>\n");
return 1;
}
// start assigning values for param processing
int responseHeaderFlag = 0;
char* URL = "null"; // we'll use this later to check if our url is a good one
int i;
// lookup for -h flag
for (i=1; i<argc; i++) {
if ((strncmp(argv[i], "-h", 2))==0) {
responseHeaderFlag = 1;
break;
}
}
// lookup for <URL> argument, format is: http://hostname[:port]/filepath.
for (i=1; i<argc; i++) {
// a URL can start with either or without the 'http://' prefix
if ((strncmp(argv[i], "www.", 4))==0 || (strncmp(argv[i], "http://", 7))==0) {
URL = argv[i];
printf("URL: %s\n", URL);
break;
}
}
if (URL=="null") {
printf("invalid or malformed url was given\n");
return 1;
}
struct sockaddr_in serv_addr; // server address
struct hostent *server_host; // host (will be the URL provided)
int sockfd, nbytes, size = 0; // socket and IO byte count
char buff[1024]; // message buffer
server_host = gethostbyname(URL);
if (server_host==NULL) {
herror("error, unable to resolve hostname\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd<0) {
perror("error, cannot create a socket\n");
exit(1);
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(80);
serv_addr.sin_addr = *(struct in_addr*)server_host->h_addr;
// connect to server
if (connect(sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) <0) {
perror("error, cannot connect\n");
exit(1);
}
// use the parameters to build the http message
bzero(buff, sizeof(buff));
// if -h send HEAD instead of default GET, when -t <time-since> enter with If-Modified_since header
if (responseHeaderFlag) {
printf("Sending HEAD query to %s for response!\n", URL);
sprintf(buff, "HEAD %s HTTP/1.0\r\nConnection: Close\r\n\r\n", URL);
} else { // send a GET if -h was not entered
printf("Sending GET query to %s for response!\n", URL);
sprintf(buff, "GET %s HTTP/1.0\r\nConnection: Close\r\n\r\n", URL);
}
printf("HTTP request =\n%s\nLEN = %d\n", buff, strlen(buff));
// send the request to server
if ((nbytes = write(sockfd, buff, strlen(buff))) < 0) {
perror("error on write\n");
exit(1);
}
buff[sizeof(buff)-1] = '\0';
// read the response from the server
while ((nbytes = read(sockfd, buff, strlen(buff))) > 0) {
if (nbytes<0) {
perror("error on read\n");
exit(1);
}
if (nbytes==0) {
break;
}
size += nbytes;
if (nbytes<sizeof(buff)) {
buff[nbytes] = '\0';
}
printf("%s", buff); // print the response
}
printf("\n\tTotal received response bytes: %d\n", size);
// close socket and exit
close(sockfd);
exit(0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment