TLS Client in MSVC++ for localhost:Port - c++

I have a local server which has a REST API running at https://localhost:61000, to which I can send the following Curl request:
curl -X POST "https://localhost:61000/users/logout" -H "accept: */*" -H "Locale: en"
and it would return me the following response
In MSVC++ using the WinSock and OpenSSL library I can get the response code 200 from google.com at port 443, but when I try for localhost at port 61000 I always get a HTTP/1.1 400 Bad Request
// Client
int main(int argc, char* argv[])
{
WSADATA wsadata;
if ((WSAStartup(MAKEWORD(2, 0), &wsadata)) == 0) {
cout << "-WSAStartup Initialized." << endl;
struct addrinfo hints, * res;
int sockfd;
memset(&hints, 0, sizeof hints);
hints.ai_socktype = 0;// SOCK_STREAM;
hints.ai_protocol = 0;// IPPROTO_TCP;
hints.ai_family = AF_UNSPEC;
if (getaddrinfo("localhost", "61000", &hints, &res) != 0) {
cout << "-getaddrinfo unsuccessful." << WSAGetLastError() << endl;
}
if ((sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == INVALID_SOCKET) {
cout << "-Unable to create socket." << WSAGetLastError() << endl;
}
if ((connect(sockfd, res->ai_addr, res->ai_addrlen)) != SOCKET_ERROR) {
cout << "-Connection Established." << endl;
}
cout << "-Client connected to: " << res->ai_addr << endl;
SSL_library_init();
SSLeay_add_ssl_algorithms();
SSL_load_error_strings();
const SSL_METHOD* meth = TLSv1_2_client_method();
SSL_CTX* ctx = SSL_CTX_new(meth);
ssl = SSL_new(ctx);
if (!ssl) {
printf("Error creating SSL.\n");
log_ssl();
return -1;
}
sock = SSL_get_fd(ssl);
SSL_set_fd(ssl, sockfd);
int err = SSL_connect(ssl);
if (err <= 0) {
printf("Error creating SSL connection. err=%x\n", err);
log_ssl();
fflush(stdout);
return -1;
}
printf("SSL connection using %s\n", SSL_get_cipher(ssl));
const char* request = "GET /users HTTPS/1.1\r\n\r\n";
//SendPacket
int len = SSL_write(ssl, request, strlen(request));
if (len < 0) {
int err = SSL_get_error(ssl, len);
switch (err) {
case SSL_ERROR_WANT_WRITE:
return 0;
case SSL_ERROR_WANT_READ:
return 0;
case SSL_ERROR_ZERO_RETURN:
case SSL_ERROR_SYSCALL:
case SSL_ERROR_SSL:
default:
return -1;
}
}
//RecvPacket
len = 100;
char buf[20000];
do {
len = SSL_read(ssl, buf, 100);
buf[len] = 0;
printf(buf);
} while (len > 0);
if (len < 0) {
int err = SSL_get_error(ssl, len);
if (err == SSL_ERROR_WANT_READ)
return 0;
if (err == SSL_ERROR_WANT_WRITE)
return 0;
if (err == SSL_ERROR_ZERO_RETURN || err == SSL_ERROR_SYSCALL || err == SSL_ERROR_SSL)
return -1;
}
}
else {
cout << "-WSAStartup Initialization failed." << endl;
if (WSACleanup() != 0) {
cout << "-WSACleanup Successful." << endl;
}
else {
cout << "-WSACleanup Failed." << endl;
}
}
return 0;
}
Response:
Assuming that the (HTTP) 400 Bad Request response status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error, but I can not figure out how to create the request in right way.

Related

Winsock manually send HTTP request gives 403 Forbidden

I am currently trying to understand how HTTP requests work so I am using winsock2 for c++ to try and send some HTTP requests manually.
My code looks like this:
#include <iostream>
#include <SFML/Graphics.hpp>
#include "EasyWinSock.h"
char ip[] = "prnt.sc";
char port[] = "80";
int main() {
easy_win_sock ews(ip, port);
ews.init_win_sock();
ews.create_win_sock();
ews.connect_win_sock();
char sendbuf2[] = "GET /t/gh17d-1645175682/post HTTP/1.1\r\nUser-Agent: kekwtestkekw\r\nHost: ptsv2.com\r\n\r\n";
char sendbuf[] = "GET /111111 HTTP/1.1\r\nHost: www.prnt.sc\r\n\r\n";
ews.send_win_sock(sendbuf, (int)strlen(sendbuf));
DATA *result = ews.recieve_win_sock_text(512); // dynamically allocated
/*
for (int i = 0; i < result->content->size(); i++) {
std::cout << (*result->content)[i];
}
*/
ews.cleanup_win_sock();
return 0;
}
With the Winsocket tucked away in the struct:
#pragma once
#pragma comment(lib, "ws2_32.lib")
#include <iostream>
#include <vector>
#include <winsock2.h>
#include <WS2tcpip.h>
struct DATA {
std::vector<char*>* content;
int size;
};
struct easy_win_sock {
char *ip;
char *port;
WSADATA *wsaData;
addrinfo* result = nullptr;
addrinfo* ptr = nullptr;
SOCKET *sock;
easy_win_sock(char* ip, char* port) {
this->ip = ip;
this->port = port;
this->sock = new SOCKET;
this->wsaData = new WSADATA;
}
void init_win_sock() {
int i_result = WSAStartup(MAKEWORD(2, 2), wsaData);
if (i_result != 0) {
std::cout << "WASStartup failed: " << i_result << std::endl;
exit(1);
}
}
void create_win_sock() {
this->result = NULL;
this->ptr = NULL;
addrinfo hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// get ip adress of hostname
int i_result = getaddrinfo(this->ip, this->port, &hints, &this->result);
if (i_result != 0) {
std::cout << "getaddrinfo failed: " << i_result << std::endl;
WSACleanup();
exit(1);
}
// create socket
*this->sock = INVALID_SOCKET;
// Attempt to connect to the first adress returned by the call to getaddrinfo
this->ptr = this->result;
// create socket for connecting to server
*this->sock = socket(this->ptr->ai_family, this->ptr->ai_socktype, this->ptr->ai_protocol);
if (*this->sock == INVALID_SOCKET) {
std::cout << "Error at socket(): " << WSAGetLastError() << std::endl;
freeaddrinfo(this->result);
WSACleanup();
exit(1);
}
}
void connect_win_sock() {
// connect to server
int i_result = connect(*this->sock, this->ptr->ai_addr, (int)this->ptr->ai_addrlen);
if (i_result == SOCKET_ERROR) {
closesocket(*this->sock);
*this->sock = INVALID_SOCKET;
}
// if connection failed we just close everithing instead of trying other adresses from getadressinfo()
freeaddrinfo(result);
if (*this->sock == INVALID_SOCKET) {
std::cout << "Unable to connect to server!" << std::endl;
WSACleanup();
exit(1);
}
}
void send_win_sock(char* data, int buf_len) {
int i_result = send(*this->sock, data, buf_len, 0);
if (i_result == SOCKET_ERROR) {
std::cout << "Send failed: " << WSAGetLastError() << std::endl;
closesocket(*this->sock);
WSACleanup();
exit(1);
}
}
DATA* recieve_win_sock_text(int buf_size) {
std::vector<char*>* recvbufs = new std::vector<char*>;
DATA* data = new DATA;
// recieve data till server closes connection
int i_result = 1; // number of recieved bytes
while (i_result > 0) {
recvbufs->push_back(new char[buf_size]);
i_result = recv(*this->sock, (*recvbufs)[recvbufs->size() - 1], buf_size - 1, 0);
if (i_result >= 0) {
(*recvbufs)[recvbufs->size() - 1][i_result] = '\0';
std::cout << (*recvbufs)[recvbufs->size() - 1];
}
else {
std::cout << "recv failed: " << WSAGetLastError() << std::endl;
}
}
data->content = recvbufs;
return data;
}
void cleanup_win_sock() {
// shutdown the connection for sending
// still can recieve
int i_result = shutdown(*this->sock, SD_SEND);
if (i_result == SOCKET_ERROR) {
std::cout << "Shutdown failed: " << WSAGetLastError() << std::endl;
closesocket(*this->sock);
WSACleanup();
exit(0);
}
closesocket(*this->sock);
WSACleanup();
delete this->sock;
delete this->wsaData;
}
};
I am using http://ptsv2.com/ to try out my HTTP requests and on this site they work. When I however try to send a GET request to the site prnt.sc/111111 I get different Error codes depending on my GET request. When I just do a
GET /111111 HTTP/1.1
Host: prnt.sc
<empty line>
for example, I get a 403 Forbidden.
When I use the Website https://reqbin.com/ to test HTTP requests and i put in prnt.sc/111111 it generates the same request but the response it shows is 200 OK.
Can anyone help me? I'm seriously stuck here.
Thanks in advance.

HTTP GET request using C++ WinSock, Binance API

I'm trying first to connect with Binance api endpoint which is /api/v3/ping.
However I'm getting "HTTP/1.1 400 Bad Request" response, what should be updated in this code?
int main()
{
WSADATA wsa;
SOCKET s;
struct sockaddr_in server;
char buffer[BUFFERSIZE];
std::string request;
std::cout<<("Initialising Winsock...\n");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
std::cout<<("Failed. Error Code : %d", WSAGetLastError());
return 1;
}
std::cout<<("Initialised.\n");
if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
std::cout << ("Could not create socket : %d", WSAGetLastError());
}
std::cout << ("Socket created.\n");
const wchar_t* IP = _T("52.84.198.235");
InetPton(AF_INET, IP, &server.sin_addr.s_addr);
server.sin_family = AF_INET;
server.sin_port = htons(443);
if (connect(s, (struct sockaddr*)&server, sizeof(server)) < 0)
{
std::cout<<("connect error\n");
return 1;
}
std::cout<<("Connected\n");
request += "GET /api/v3/ping HTTP/1.1\r\nHost: api.binance.com\r\n\r\n";
if (send(s, request.c_str(), strlen(request.c_str()), 0) < 0)
{
std::cout<<("Send failed\n");
return 1;
}
std::cout << ("Data Send\n");
std::string response;
int resp_leng;
response = "";
resp_leng = BUFFERSIZE;
while (resp_leng)
{
resp_leng = recv(s, (char*)&buffer, BUFFERSIZE, 0);
if (resp_leng > 0)
response += std::string(buffer).substr(0, resp_leng);
}
std::cout << response << "\n";
closesocket(s);
WSACleanup();
return 0;
}
I was using info from a few sites and stackoverflow questions, I'm wondering if it can be about SSL?

IPv6 connect error WSAEAFNOSUPPORT

I code a small client for IPv4 / IPv6 with a hostname resolver.
For IPv4 and resolver it's fine but not with IPv6 when connect() I have a problem WSAGetLastError() say WSAEAFNOSUPPORT.
I have a switch all structures (AF_INET -> AF_INET6, SOCKADDR_IN -> SOCKADDR_IN6) to IPv6 versions.
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
int main()
{
printf("Simple_Client IPv4 & IPv6\n\n");
// Initiates Winsock
WSADATA WSAData;
WSAStartup(MAKEWORD(2, 0), &WSAData);
// Get Parameters IP/PORT and request
std::string str_HOSTNAME = "mirror.neostrada.nl";
int PORT = 21;
// RESOLVE IP
BOOL is_IPv6 = FALSE;
std::string str_dest_ip = "";
addrinfo hints = { 0 };
hints.ai_flags = AI_ALL;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
addrinfo * pResult;
getaddrinfo(str_HOSTNAME.c_str(), NULL, &hints, &pResult);
if (pResult == NULL)
{
printf("pResult error\n");
return -1;
}
if (pResult->ai_family == AF_INET)
{
printf("getaddrinfo = AF_INET (IPv4)\n");
is_IPv6 = FALSE;
}
if (pResult->ai_family == AF_INET6)
{
printf("getaddrinfo = AF_INET6 (IPv6)\n");
is_IPv6 = TRUE;
}
char str[128];
memset(str, 0, sizeof(str));
if (is_IPv6 == FALSE) // IPv4
{
if (inet_ntop(AF_INET, &(*((ULONG*)&(((sockaddr_in*)pResult->ai_addr)->sin_addr))), str, INET_ADDRSTRLEN))
str_dest_ip = char_to_string(str, strlen(str)); // Copy char in std::string
else
printf("inet_ntop error\n");
}
if (is_IPv6 == TRUE) // IPv6
{
if (inet_ntop(AF_INET6, &(*((ULONG*)&(((sockaddr_in6 *)pResult->ai_addr)->sin6_addr))), str, INET6_ADDRSTRLEN))
str_dest_ip = char_to_string(str, strlen(str)); // Copy char in std::string
}
printf("%s : %s | Port : %i\n", is_IPv6 ? "IPv6" : "IPv4", str_dest_ip.c_str(), PORT);
// Connect to the HOSTNAME
SOCKET sock;
if (is_IPv6 == TRUE)
{
SOCKADDR_IN6 sin;
sin.sin6_family = AF_INET6;
if(inet_pton(sin.sin6_family, str_dest_ip.c_str(), &sin) != 1)
printf("ERROR inet_pton %i\n", WSAGetLastError());
sin.sin6_port = htons(PORT);
sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
return -2;
if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) != SOCKET_ERROR)
{
printf("Connect Success to %s | PORT : %i\n", str_dest_ip.c_str(), PORT);
}
else
{
printf("ERROR connect to %s | PORT : %i : %i\n", str_dest_ip.c_str(), PORT, WSAGetLastError());
Sleep(10000);
return -2;
}
}
char buf[1024] = { 0 };
int size_recv = recv(sock, buf, sizeof(buf), 0);
printf("SIZE RECV = %i | DATA RECV = %s\n", size_recv, char_to_string(buf, size_recv).c_str());
WSACleanup();
getchar();
return 0;
}
If somebody have a idea, thanks for reading.
The problem is here:
inet_pton(sin.sin6_family, str_dest_ip.c_str(), &sin)
This writes the IPv6 address on top of the sin6_family field, damaging the whole structure.
It should be:
inet_pton(sin.sin6_family, str_dest_ip.c_str(), &sin.sin6_addr)
It's also a good idea to zero-initialize the whole sin structure in the beginning because it has more fields than you're filling in.
You are not using getaddrinfo() correctly.
For one thing, getaddrinfo() returns an error code that you are ignoring.
For another thing, getaddrinfo() returns a linked list that potentially contains multiple addresses in a mix of IPv4 and/or IPv6, due to your use of AF_UNSPEC. If you are only interested in IPv6, set hints.ai_family to AF_INET6 rather than AF_UNSPEC.
But either way, a given hostname may have multiple IPs associated with it, and they might not all be reachable from your location, so you should be connect()'ing to each address in the list, either one at a time or in parallel, until one of them succeeds.
Also, there is no need to use inet_pton() in this situation at all (which you are not using correctly, as explained by #rustyx's answer). getaddrinfo() returns fully populated sockaddr_in(6) structs that you can pass as-is to connect().
Try something more like this instead:
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>
#include <string>
#pragma comment(lib, "ws2_32.lib")
std::string addr_to_str(addrinfo *addr)
{
char str[128];
switch (addr->ai_family)
{
case AF_INET: // IPv4
{
if (inet_ntop(AF_INET, &(((sockaddr_in*)(addr->ai_addr))->sin_addr), str, INET_ADDRSTRLEN))
return str;
ret = WSAGetLastError();
break;
}
case AF_INET6: // IPv6
{
if (inet_ntop(AF_INET6, &(((sockaddr_in6*)(addr->ai_addr))->sin6_addr), str, INET6_ADDRSTRLEN))
return str;
ret = WSAGetLastError();
break;
}
default:
ret = WSAEAFNOSUPPORT;
break;
}
std::cerr << "inet_ntop error: " << ret << std::endl;
return "";
}
int main()
{
std::cout << "Simple_Client IPv4 & IPv6" << std::endl << std::endl;
// Initiates Winsock
WSADATA WSAData;
int ret = WSAStartup(MAKEWORD(2, 0), &WSAData);
if (ret != 0)
{
std::cerr << "WSAStartup error: " << ret << std::endl;
return -1;
}
// Get Parameters IP/PORT and request
std::string str_HOSTNAME = "mirror.neostrada.nl";
int PORT = 21;
// RESOLVE IP
addrinfo hints = { 0 };
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
addrinfo *pResult = NULL;
ret = getaddrinfo(str_HOSTNAME.c_str(), std::to_string(PORT).c_str(), &hints, &pResult);
if (ret != 0)
{
std::cerr << "getaddrinfo error: " << ret << std::endl;
WSACleanup();
return -1;
}
// Log the IPs
bool has_IPv4 = false;
bool has_IPv6 = false;
for (addrinfo *addr = pResult; addr != NULL; addr = addr->ai_next)
{
switch (addr->ai_family)
{
case AF_INET: // IPv4
{
has_IPv4 = true;
std::cout << "IPv4 : " << addr_to_str(addr);
break;
}
case AF_INET6: // IPv6
{
has_IPv6 = true;
std::cout << "IPv6 : " << addr_to_str(addr);
break;
}
}
}
// Connect to the HOSTNAME
SOCKET sock = INVALID_SOCKET;
if (has_IPv6)
{
// try IPv6 first...
for (addrinfo *addr = pResult; addr != NULL; addr = addr->ai_next)
{
if (addr->ai_family != AF_INET6)
continue;
std::cout << "Connecting to IPv6 : " << addr_to_str(addr) << " | Port : " << PORT << std::endl;
sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (sock == INVALID_SOCKET)
{
ret = WSAGetLastError();
std::cerr << "socket error: " << ret << std::endl;
continue;
}
if (connect(sock, addr->ai_addr, addr->ai_addrlen) == SOCKET_ERROR)
{
ret = WSAGetLastError();
std::cerr << "connect error: " << ret << std::endl;
closesocket(sock);
sock = INVALID_SOCKET;
continue;
}
break;
}
}
if ((sock == INVALID_SOCKET) && (has_IPv4))
{
// try IPv4 next...
for (addrinfo *addr = pResult; addr != NULL; addr = addr->ai_next)
{
if (addr->ai_family != AF_INET)
continue;
std::cout << "Connecting to IPv4 : " << addr_to_str(addr) << " | Port : " << PORT << std::endl;
sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (sock == INVALID_SOCKET)
{
ret = WSAGetLastError();
std::cerr << "socket error: " << ret << std::endl;
continue;
}
if (connect(sock, addr->ai_addr, addr->ai_addrlen) == SOCKET_ERROR)
{
ret = WSAGetLastError();
std::cerr << "connect error: " << ret << std::endl;
closesocket(sock);
sock = INVALID_SOCKET;
continue;
}
break;
}
}
freeaddrinfo(pResult);
if (sock == INVALID_SOCKET)
{
WSACleanup();
return -2;
}
std::cout << "Connect Successful" << std::endl;
char buf[1024];
int size_recv = recv(sock, buf, sizeof(buf), 0);
if (size_recv == SOCKET_ERROR)
{
ret = WSAGetLastError();
std::cerr << "recv error: " << ret << std::endl;
}
else
{
std::cout << "SIZE RECV = " << size_recv;
if (size_recv > 0)
{
std::cout << " | DATA RECV = ";
std::cout.write(buf, size_recv);
}
std::cout << std::endl;
}
closesocket(sock);
WSACleanup();
std::cin.get();
return 0;
}

Download data from Wikipedia page

I'm trying to download data from Wikipedia. I send a GET request, but the return status - "HTTP 301 redirection". Now I need to parse that to get the target URL, and from there I can access the article content.
I do the parse but but I cannot access to the article content. I appreciate your help if you can help me to get to the article content.
code -
#include <winsock2.h>
#include <WS2tcpip.h>
#include <windows.h>
#include <iostream>
#include <vector>
#include <ostream>
using namespace std;
int main(){
string query = "Google";
//int depth = 0;
// Initialize Dependencies to the Windows Socket.
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
cout << "WSAStartup failed.\n";
system("pause");
}
struct addrinfo hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_socktype = SOCK_STREAM;
/* connect to wikipedia //and download the article */
static const char wiki_host[] = "en.wikipedia.org";
struct addrinfo* targetAdressInfo = NULL;
DWORD getAddrRes = getaddrinfo(wiki_host, NULL, &hints, &targetAdressInfo);
if (getAddrRes != 0 || targetAdressInfo == NULL)
{
cout << "Could not resolve the Host Name" << endl;
system("pause");
WSACleanup();
return -1;
}
SOCKADDR_IN sockAddr;
sockAddr.sin_addr = ((struct sockaddr_in*) targetAdressInfo->ai_addr)->sin_addr;
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons(80);
freeaddrinfo(targetAdressInfo);
SOCKET webSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (webSocket == INVALID_SOCKET)
{
cout << "Creation of the Socket Failed" << endl;
system("pause");
WSACleanup();
return -1;
}
if (connect(webSocket, (SOCKADDR*)&sockAddr, sizeof(sockAddr)) != 0)
{
cout << "Could not connect";
system("pause");
closesocket(webSocket);
WSACleanup();
return -1;
}
string http_query = "GET /wiki/" + query + " HTTP/1.1\r\n";
http_query += string("Host: ") + wiki_host + "\r\n";
http_query += "\r\n\r\n";
if (send(webSocket, http_query.c_str(), http_query.length(), 0) == -1) {
cout << "Could not send the request to the Server" << endl;
system("pause");
closesocket(webSocket);
WSACleanup();
return -1;
}
/* prepare to fetch the wiki article */
string response = "";
while (true) {
static char recv_buffer[4096];
const int bytes_read = recv(webSocket, recv_buffer, sizeof(recv_buffer) - 1, 0);
if (!bytes_read) {
break;
}
if (bytes_read == -1) {
closesocket(webSocket);
WSACleanup();
}
recv_buffer[bytes_read] = '\0';
response += recv_buffer;
};
/* finished with the socket */
closesocket(webSocket);
WSACleanup();
/* parse the http response headers */
size_t cursor = 0;
string response_content;
vector<std::string> response_headers;
const size_t headers_end = response.find("\r\n\r\n");
while (true) {
const size_t line_end = response.find("\r\n", cursor);
if (line_end == std::string::npos) { /* probably due to http error */
break;
}
response_headers.push_back(response.substr(cursor, line_end - cursor));
if (line_end == headers_end) { /* found content */
response_content = response.substr(headers_end + 4); /* skip \r\n\r\n */
break;
}
cursor = line_end + 2; /* skip \r\n */
}
// print the respone
for (int i = 0; i < sizeof(response); i++){
cout << response[i];
}
/* print response_content not work
for (int i = 0; i < sizeof(response); i++){
cout << response_content[i];
}*/
system("pause");
return 0;
}
I'm not sure what you mean by saying "I do the parse but but I cannot access to the article content". What you need to do when you get 301 status is to look at "Location" header you received back. That header contains the URL you can use to fetch the content you are looking for.

Read site body from get request

I try to read site body from get request but I only get the status code and some of start from html text (This is what I got -"HTTP/1.1 200 OK Server: Apa!DOCTYPE html html lang=e"). I would appreciate if you could help me fix the problem. Thanks
Code -
#include <winsock2.h>
#include <WS2tcpip.h>
#include <windows.h>
#include <iostream>
#include <vector>
#include <ostream>
int main(){
// Initialize Dependencies to the Windows Socket.
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
cout << "WSAStartup failed.\n";
system("pause");
}
struct addrinfo hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_socktype = SOCK_STREAM;
/* connect and download the article */
static const char wiki_host[] = "en.wikipedia.org";
struct addrinfo* targetAdressInfo = NULL;
DWORD getAddrRes = getaddrinfo(wiki_host, NULL, &hints, &targetAdressInfo);
if (getAddrRes != 0 || targetAdressInfo == NULL)
{
cout << "Could not resolve the Host Name" << endl;
system("pause");
WSACleanup();
return -1;
}
SOCKADDR_IN sockAddr;
sockAddr.sin_addr = ((struct sockaddr_in*) targetAdressInfo->ai_addr)->sin_addr;
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons(80);
freeaddrinfo(targetAdressInfo);
SOCKET webSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (webSocket == INVALID_SOCKET)
{
cout << "Creation of the Socket Failed" << endl;
system("pause");
WSACleanup();
return -1;
}
if (connect(webSocket, (SOCKADDR*)&sockAddr, sizeof(sockAddr)) != 0)
{
cout << "Could not connect";
system("pause");
closesocket(webSocket);
WSACleanup();
return -1;
}
string http_query = "GET / https://en.wikipedia.org/w/api.php?titles=StackOverflow&action=query&prop=extracts&format=json\r\nConnection: close\r\n\r\n";
if (send(webSocket, http_query.c_str(), http_query.length(), 0) == -1) {
cout << "Could not send the request to the Server" << endl;
system("pause");
closesocket(webSocket);
WSACleanup();
return -1;
}
/* prepare to fetch the wiki article */
string response = "";
while (true) {
static char recv_buffer[4096];
const int bytes_read = recv(webSocket, recv_buffer, sizeof(recv_buffer) - 1, 0);
if (!bytes_read) {
break;
}
if (bytes_read == -1) {
closesocket(webSocket);
WSACleanup();
}
recv_buffer[bytes_read] = '\0';
response += recv_buffer;
};
/* finished with the socket */
closesocket(webSocket);
WSACleanup();
/* parse the http response headers */
size_t cursor = 0;
string response_content;
vector<std::string> response_headers;
const size_t headers_end = response.find("\r\n\r\n");
while (true) {
const size_t line_end = response.find("\r\n", cursor);
if (line_end == std::string::npos) { /* probably due to http error */
break;
}
response_headers.push_back(response.substr(cursor, line_end - cursor));
if (line_end == headers_end) { /* found content */
response_content = response.substr(headers_end + 4); /* skip \r\n\r\n */
break;
}
cursor = line_end + 2; /* skip \r\n */
}
// print the respone
for (int i = 0; i < sizeof(response); i++){
cout << response[i];
}
//print response_content
for (int i = 0; i < sizeof(response); i++){
cout << response_content[i];
}
system("pause");
return 0;
}
This doesn't work:
for (int i = 0; i < sizeof(response); i++){
cout << response[i];
}
Because sizeof(response) is the size of the string object, not the length of the string. You should simply do
cout << response;
If you really want to iterate through the string (which is slower and not recommended) you'd have to use response.size() instead of sizeof(response).
There are a few other issue with your code as well, but this should solve the problem at hand.