Last active
November 19, 2016 17:44
-
-
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!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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