Skip to content

Commit cca07dd

Browse files
committed
Added the c++ source and header files
1 parent 831c148 commit cca07dd

File tree

3 files changed

+400
-0
lines changed

3 files changed

+400
-0
lines changed

HttpRequest.cpp

Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
#include "HttpRequest.h"
2+
3+
// Definitions //
4+
5+
HttpRequest::HttpRequest(std::string url, httpTypes::REQUEST_METHOD method)
6+
{
7+
// launch the winsock API on windows machines
8+
#ifdef _PLATFORM_WINDOWS
9+
this->startWinsock();
10+
#endif
11+
12+
// Store the parameters for further operations
13+
std::cout << "http request object created!" << std::endl;
14+
m_url = url;
15+
m_requestMethod = method;
16+
m_protocol = "http";
17+
m_connected = false;
18+
19+
// Setup a tcp socket
20+
this->m_tcpSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
21+
#ifdef _PLATFORM_WINDOWS
22+
if (m_tcpSocket == INVALID_SOCKET)
23+
{
24+
std::cerr << "Could not create tcp socket!" << std::endl;
25+
return;
26+
}
27+
#else
28+
if (m_tcpSocket < 0)
29+
{
30+
std::cerr << "Could not create tcp socket!" << std::endl;
31+
return;
32+
}
33+
#endif
34+
35+
// Now extract the hostaddress, protocol(http/https) and request path from the URL
36+
std::vector<std::string> tempStr = this->splitString(this->m_url, '/');
37+
this->m_host = tempStr.at(2);
38+
this->m_protocol = tempStr.at(0);
39+
for (int i = 3; i < tempStr.size(); i++)
40+
{
41+
this->m_requestPath += tempStr.at(i) + "/";
42+
}
43+
std::cout << "Webserver address: " << this->m_host << std::endl;
44+
std::cout << "Request protocol: " << this->m_protocol << std::endl;
45+
46+
// Choose the corresponding port for the detected protocol
47+
int port = 80;
48+
if (this->m_protocol == "https:") {
49+
port = 443;
50+
}
51+
52+
std::cout << "Connection port: " << port << std::endl;
53+
54+
// Get the IP Address of the target server and create the connection endpoint
55+
struct hostent* host = gethostbyname(this->m_host.c_str());
56+
std::cout << "Final IP Address: " << inet_ntoa(*((struct in_addr*)host->h_addr_list[0])) << std::endl;
57+
58+
// Create the target webserver endpoint using the
59+
// struct sockaddr_in address = {};
60+
this->m_serverAddr = {};
61+
m_serverAddr.sin_port = htons(port);
62+
m_serverAddr.sin_family = AF_INET;
63+
m_serverAddr.sin_addr.s_addr = inet_addr(inet_ntoa(*((struct in_addr*)host->h_addr_list[0])));
64+
}
65+
66+
HttpRequest::~HttpRequest()
67+
{
68+
// close the connection and the tcp socket
69+
#ifdef _PLATFORM_WINDOWS
70+
closesocket(m_tcpSocket);
71+
#else
72+
close(m_tcpSocket);
73+
#endif
74+
75+
std::cout << "Connection closed" << std::endl;
76+
std::cout << "request object released!" << std::endl;
77+
78+
// close the winsock API on windows machines
79+
#ifdef _PLATFORM_WINDOWS
80+
this->closeWinsock();
81+
#endif
82+
}
83+
84+
void HttpRequest::sendRequest()
85+
{
86+
87+
// Connect to the webserver if it isnt't done already
88+
if (m_connected == false)
89+
{
90+
// Attempt to connect to the webserver
91+
std::cout << "Connection ..." << std::endl;
92+
int error = connect(this->m_tcpSocket, (struct sockaddr*)&m_serverAddr, sizeof(m_serverAddr));
93+
if (error != 0)
94+
{
95+
std::cerr << "Failed to connect to the webserver!" << std::endl;
96+
return;
97+
}
98+
99+
std::cout << "Connection established" << std::endl;
100+
this->m_connected = true;
101+
}
102+
103+
104+
// Now construct the HTTP Request Header text
105+
std::string requestText = this->constructRequestText();
106+
107+
108+
// Send the http request to the webserver
109+
std::cout << "Sending " << this->m_protocol << " Request ... ";
110+
int bytesSent = send(m_tcpSocket, requestText.c_str(), (int)strlen(requestText.c_str()), 0);
111+
std::cout << " Done" << std::endl;
112+
113+
// Wait for a response message
114+
const int maxResponseLength = 2048;
115+
116+
std::cout << "Waiting for a response ... ";
117+
char recvBuffer[maxResponseLength];
118+
int bytesReceived = recv(m_tcpSocket, recvBuffer, sizeof(recvBuffer), 0);
119+
if (bytesReceived < 0)
120+
{
121+
std::cerr << "\nNo response from the webserver!" << std::endl;
122+
}
123+
else
124+
{
125+
std::cout << " Done" << std::endl;
126+
// Nullterminate and store the response text
127+
if (bytesReceived < maxResponseLength)
128+
{
129+
recvBuffer[bytesReceived] = '\0';
130+
}
131+
this->m_responseText = recvBuffer;
132+
}
133+
134+
return;
135+
}
136+
137+
void HttpRequest::addParameter(std::string name, std::string value)
138+
{
139+
// Add the parameter to the list
140+
httpTypes::REQUEST_PARAM parameter;
141+
parameter.name = name;
142+
parameter.value = value;
143+
144+
this->m_parameters.push_back(parameter);
145+
146+
return;
147+
}
148+
149+
void HttpRequest::removeParameter(std::string paramName)
150+
{
151+
// Remove the parameter with the given name from the list
152+
for (int i = 0; i < this->m_parameters.size(); i++)
153+
{
154+
if (this->m_parameters.at(i).name == paramName) {
155+
// Remove this one and exit
156+
this->m_parameters.erase(this->m_parameters.begin() + i);
157+
break;
158+
}
159+
}
160+
161+
return;
162+
}
163+
164+
void HttpRequest::removeAllParameters()
165+
{
166+
// Empty the list of parameters
167+
this->m_parameters.clear();
168+
return;
169+
}
170+
171+
httpTypes::HTTP_RESPONSE HttpRequest::getResponse()
172+
{
173+
// create a response
174+
httpTypes::HTTP_RESPONSE response = {};
175+
176+
// ...
177+
// response.statusCode = 200;
178+
// response.text = "<p> Just a dummy response </p>";
179+
response.text = this->m_responseText;
180+
181+
return response;
182+
}
183+
184+
// Private helper functions //
185+
186+
std::vector<std::string> HttpRequest::splitString(const std::string& s, char delimiter)
187+
{
188+
std::vector<std::string> tokens;
189+
std::string token;
190+
std::istringstream tokenStream(s);
191+
while (std::getline(tokenStream, token, delimiter))
192+
{
193+
tokens.push_back(token);
194+
}
195+
return tokens;
196+
}
197+
198+
std::string HttpRequest::constructRequestText()
199+
{
200+
std::string requestStr = "";
201+
202+
// estimate all parts of the request string
203+
std::string methodStr = "GET";
204+
if (this->m_requestMethod == httpTypes::REQUEST_METHOD::HTTP_POST)
205+
{
206+
methodStr = "POST";
207+
}
208+
std::string httpVersion = "HTTP/1.1";
209+
210+
// put all together
211+
requestStr += methodStr + " /" + this->m_requestPath;
212+
// In case of a GET request, append the parameters here
213+
if (methodStr == "GET") {
214+
for (int i = 0; i < this->m_parameters.size(); i++)
215+
{
216+
// The first GET parameter must have a ? präfix
217+
if (i == 0)
218+
{
219+
requestStr += "?" + this->m_parameters.at(i).name + "=" + this->m_parameters.at(i).value;
220+
}
221+
// All other GET parameters must have a & präfix
222+
else
223+
{
224+
requestStr += "&" + this->m_parameters.at(i).name + "=" + this->m_parameters.at(i).value;
225+
}
226+
}
227+
}
228+
requestStr += " " + httpVersion + "\r\n";
229+
requestStr += "Host: " + this->m_host + "\r\n\r\n";
230+
231+
// quickly output the constructed text
232+
std::cout << std::endl;
233+
std::cout << requestStr;
234+
std::cout << std::endl;
235+
236+
return requestStr;
237+
}
238+
239+
// Winsock functions - WINDOWS ONLY
240+
#ifdef _PLATFORM_WINDOWS
241+
242+
void HttpRequest::startWinsock()
243+
{
244+
// launch the Winsock API
245+
WSADATA wsa;
246+
int error = WSAStartup(MAKEWORD(2, 2), &wsa);
247+
if (error != 0)
248+
{
249+
// Error!
250+
}
251+
252+
return;
253+
}
254+
255+
void HttpRequest::closeWinsock()
256+
{
257+
// Close the winsock API
258+
WSACleanup();
259+
return;
260+
}
261+
262+
#endif

HttpRequest.h

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#pragma once
2+
3+
#define _WINSOCK_DEPRECATED_NO_WARNINGS
4+
5+
// THE PLATFORM MUST BE DEFINED HERE !!! //
6+
#define _PLATFORM_WINDOWS
7+
// #define _PLATFORM_UNIX
8+
9+
// General platform independent includes //
10+
#include <sstream>
11+
#include <iostream>
12+
#include <vector>
13+
#include <stdio.h>
14+
#include <stdlib.h>
15+
#include <memory>
16+
17+
// Platform dependent includes //
18+
#ifdef _PLATFORM_WINDOWS
19+
#include <string>
20+
#include <winsock.h> // winsock
21+
#include <mmsystem.h> // windows system
22+
#endif
23+
24+
#ifdef _PLATFORM_UNIX
25+
#include <string.h>
26+
#include <sys/types.h>
27+
#include <sys/socket.h> //socket
28+
#include <arpa/inet.h> //inet_addr
29+
#include <netinet/in.h>
30+
#include <netdb.h> //hostent
31+
#include <unistd.h>
32+
#endif
33+
34+
// Library linking //
35+
#ifdef _PLATFORM_WINDOWS
36+
#pragma comment(lib, "Ws2_32.lib")
37+
#pragma comment(lib, "winmm.lib")
38+
#endif
39+
40+
namespace httpTypes
41+
{
42+
enum class REQUEST_METHOD { HTTP_GET, HTTP_POST };
43+
44+
struct HTTP_RESPONSE
45+
{
46+
short statusCode;
47+
std::string text;
48+
};
49+
50+
struct REQUEST_PARAM
51+
{
52+
std::string name;
53+
std::string value;
54+
};
55+
}
56+
57+
class HttpRequest
58+
{
59+
60+
public:
61+
HttpRequest(std::string, httpTypes::REQUEST_METHOD);
62+
~HttpRequest();
63+
64+
void sendRequest();
65+
void addParameter(std::string, std::string);
66+
void removeParameter(std::string);
67+
void removeAllParameters();
68+
69+
httpTypes::HTTP_RESPONSE getResponse();
70+
71+
private:
72+
// Helper functions
73+
std::vector<std::string> splitString(const std::string& s, char delimiter);
74+
std::string constructRequestText();
75+
76+
// winsock handling - WINDOWS ONLY
77+
#ifdef _PLATFORM_WINDOWS
78+
void startWinsock();
79+
void closeWinsock();
80+
#endif
81+
82+
private:
83+
bool m_connected;
84+
#ifdef _PLATFORM_WINDOWS
85+
SOCKET m_tcpSocket;
86+
#else
87+
int m_tcpSocket;
88+
#endif
89+
sockaddr_in m_serverAddr;
90+
91+
std::string m_url, m_host, m_requestPath;
92+
httpTypes::REQUEST_METHOD m_requestMethod;
93+
std::vector<httpTypes::REQUEST_PARAM> m_parameters;
94+
std::string m_protocol;
95+
96+
std::string m_responseText;
97+
};
98+

0 commit comments

Comments
 (0)