In VC++, I am trying to send an HTTP POST request and get its response.
I have the below code, which compiles successfully, yet fails to POST.
First I try to send the POST request to the request bin for testing purpose
int main(int argc, _TCHAR* argv[])
{
static CHAR hdrs[] = "Content-Type: application/x-www-form-urlencoded";
static CHAR frmdata[] = "name=John+Doe&userid=hithere&other=P%26Q";
HINTERNET hSession = InternetOpenA("MyAgent", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
HINTERNET hConnect = InternetConnect(hSession "pipedream.com", 8733, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
HINTERNET hRequest = HttpOpenRequestA(hConnect, "POST", "/r/enj77inn26shk", NULL, NULL, NULL, 0, 1);
HttpSendRequestA(hRequest, hdrs, strlen(hdrs), frmdata, strlen(frmdata));
Then read the response using
DWORD dwContentLen;
DWORD dwBufLen = sizeof(dwContentLen);
if (HttpQueryInfo(hRequest,
HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
(LPVOID)&dwContentLen,
&dwBufLen,
0))
{
char *pData = (char*)GlobalAlloc(GMEM_FIXED, dwContentLen + 1);
DWORD dwReadSize = dwContentLen / 10; // We will read 10% of data
// with each read.
DWORD cReadCount;
DWORD dwBytesRead;
char *pCopyPtr = pData;
for (cReadCount = 0; cReadCount < 10; cReadCount++)
{
InternetReadFile(hRequest, pCopyPtr, dwReadSize, &dwBytesRead);
pCopyPtr = pCopyPtr + dwBytesRead;
}
// extra read to account for integer division round off
InternetReadFile(hRequest,
pCopyPtr,
dwContentLen - (pCopyPtr - pData),
&dwBytesRead);
// Null terminate data
pData[dwContentLen] = 0;
std::cout << pData << std::endl;
system("pause");
}
return 0;
}
The endpoint I'm posting to
Related
i am coding at an key authentication system with imgui. I use the Download String function to get the key. But the if says that the user input and the downloaded key are not the same.
this is the DownloadString function:
std::string DownloadString(std::string URL) {
HINTERNET interwebs = InternetOpenA("Mozilla/5.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, NULL);
HINTERNET urlFile;
std::string rtn;
if (interwebs) {
urlFile = InternetOpenUrlA(interwebs, URL.c_str(), NULL, NULL, NULL, NULL);
if (urlFile) {
char buffer[2000];
DWORD bytesRead;
do {
InternetReadFile(urlFile, buffer, 2000, &bytesRead);
rtn.append(buffer, bytesRead);
memset(buffer, 0, 2000);
} while (bytesRead);
InternetCloseHandle(interwebs);
InternetCloseHandle(urlFile);
std::string p = replaceAll(rtn, "|n", "\r\n");
return p;
}
}
InternetCloseHandle(interwebs);
std::string p = replaceAll(rtn, "|n", "\r\n");
return p;
}
and this is my code:
std::string key = DownloadString("https://pastebin.com/raw/sGjce0HG");
char buf[500]{"Your key here"};
ImGui::InputText("", buf, 500);
std::string user_key = buf;
if (user_key == key)
{
ImGui::Text("key is working");
}
i hope you can help me
I have a function to upload information to a byte array, but it ends with - if (!Httpsendrequest(httprequest, szHeaders, strlen(szhheaders), szRequest, strlen(szRequest)))
string GetUrlData(const string& url, LPCSTR host, string& output)
{
string request_data = "";
output = "";
HINTERNET hIntSession = InternetOpenA("token", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (!hIntSession)
{
return request_data;
}
HINTERNET hHttpSession = InternetConnectA(hIntSession, host, 80, 0, 0, INTERNET_SERVICE_HTTP, 0, NULL);
if (!hHttpSession)
{
return request_data;
}
HINTERNET hHttpRequest = HttpOpenRequestA(hHttpSession, "GET", url.c_str()
, 0, 0, 0, INTERNET_FLAG_RELOAD, 0);
if (!hHttpSession)
{
return request_data;
}
char* szHeaders = ("Content-Type: text/html\r\nUser-Agent: License");
char szRequest[1024] = { 0 };
if (!HttpSendRequestA(hHttpRequest, szHeaders, strlen(szHeaders), szRequest, strlen(szRequest)))
{
qDebug()<<"BLYA";
return request_data;
}
CHAR szBuffer[1024] = { 0 };
DWORD dwRead = 0;
while (InternetReadFile(hHttpRequest, szBuffer, sizeof(szBuffer) - 1, &dwRead) && dwRead)
{
request_data.append(szBuffer, dwRead);
}
InternetCloseHandle(hHttpRequest);
InternetCloseHandle(hHttpSession);
InternetCloseHandle(hIntSession);
output = request_data;
}
The failure might have something to do with the fact that szHeaders is missing \r\n on the User-Agent header. Every header you send ust be terminated with \r\n. And BTW, there is no reason to send a Content-Type header in a GET request, since there is no message body being sent to the server.
Also, your code has a bunch of memory leaks if anything goes wrong. You need to close every handle you successfully open.
Also, there is no point in having both a return value and an output parameter that return the same data. Pick one or the other. I would suggest using a bool return value and a string output parameter.
Try something more like this:
bool GetUrlData(const string& resource, const string& host)
{
output.clear();
bool result = false;
HINTERNET hIntSession = InternetOpenA("token", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (!hIntSession) {
qDebug() << "InternetOpen failed, error: " << GetLastError();
return false;
}
HINTERNET hHttpSession = InternetConnectA(hIntSession, host.c_str(), 80, 0, 0, INTERNET_SERVICE_HTTP, 0, NULL);
if (!hHttpSession) {
qDebug() << "InternetConnect failed, error: " << GetLastError();
InternetCloseHandle(hIntSession);
return false;
}
HINTERNET hHttpRequest = HttpOpenRequestA(hHttpSession, "GET", resource.c_str(), 0, 0, 0, INTERNET_FLAG_RELOAD, 0);
if (!hHttpRequest) {
qDebug() << "HttpOpenRequest failed, error: " << GetLastError();
InternetCloseHandle(hHttpSession);
InternetCloseHandle(hIntSession);
return false;
}
const char* szHeaders = "User-Agent: License\r\n";
if (!HttpSendRequestA(hHttpRequest, szHeaders, -1, NULL, 0)) {
qDebug() << "HttpSendRequest failed, error: " << GetLastError();
InternetCloseHandle(hHttpRequest);
InternetCloseHandle(hHttpSession);
InternetCloseHandle(hIntSession);
return false;
}
char szBuffer[1024];
DWORD dwRead = 0;
do {
if (!InternetReadFile(hHttpRequest, szBuffer, sizeof(szBuffer), &dwRead)) {
qDebug() << "InternetReadFile failed, error: " << GetLastError();
InternetCloseHandle(hHttpRequest);
InternetCloseHandle(hHttpSession);
InternetCloseHandle(hIntSession);
return false;
}
if (dwRead == 0)
break;
output.append(szBuffer, dwRead);
}
while (true);
return true;
}
INTRODUCTION AND RELEVANT INFORMATION:
I am learning WinInet on my own. I have written (in my humble opinion) "typical" piece of code, that needs to perform cleanup in the end:
DWORD CSomeClass::MVCE4StackOverflow()
{
DWORD errorCode = ERROR_SUCCESS;
URL_COMPONENTS urlComp;
::ZeroMemory(&urlComp, sizeof(URL_COMPONENTS));
urlComp.dwStructSize = sizeof(URL_COMPONENTS);
urlComp.dwHostNameLength = -1;
urlComp.dwSchemeLength = -1;
urlComp.dwUrlPathLength = -1;
if (!::InternetCrackUrl(m_URL.c_str(), m_URL.length(), 0, &urlComp))
{
errorCode = ::GetLastError();
return errorCode;
}
HINTERNET hInternetSession = ::InternetOpen("WinInet",
INTERNET_OPEN_TYPE_DIRECT,
NULL, NULL, 0);
if (NULL == hInternetSession)
{
errorCode = ::GetLastError();
return errorCode;
}
std::string hostname(urlComp.dwHostNameLength, 0);
::memcpy(&hostname[0], urlComp.lpszHostName, urlComp.dwHostNameLength);
HINTERNET hHttpSession = ::InternetConnect(hInternetSession,
hostname.c_str(),
INTERNET_DEFAULT_HTTP_PORT, 0, 0,
INTERNET_SERVICE_HTTP, 0, NULL);
if (NULL == hHttpSession)
{
errorCode = ::GetLastError();
return errorCode;
}
HINTERNET hHttpRequest = ::HttpOpenRequest(hHttpSession, "POST",
urlComp.lpszUrlPath, 0, 0, 0,
INTERNET_FLAG_RELOAD, 0);
if (NULL == hHttpRequest)
{
errorCode = ::GetLastError();
return errorCode;
}
const char header[] = "Content-Type: application/x-www-form-urlencoded";
std::string data = "input=1234";
if (!::HttpSendRequest(hHttpRequest, header, strlen(header),
&data[0], data.length()))
{
errorCode = ::GetLastError();
return errorCode;
}
DWORD dwBytesRead = 0;
BOOL result = false;
char szBuffer[1025] = "";
char *temp = szBuffer;
const DWORD dwBytes2Read = sizeof(szBuffer) - 1;
do{
result = ::InternetReadFile(hHttpRequest, szBuffer, dwBytes2Read, &dwBytesRead);
if (FALSE == result)
{
errorCode = ::GetLastError();
}
temp += dwBytesRead;
} while (result && dwBytesRead > 0);
// need error handling for below 3
result = ::InternetCloseHandle(hHttpRequest);
result = ::InternetCloseHandle(hHttpSession);
result = ::InternetCloseHandle(hInternetSession);
return errorCode;
}
PROBLEM:
In the provided code example, I need to call InternetCloseHandle 3 times consecutively.
I do not know how to structure that part of code to perform proper error handling.
My idea would be to do do the following:
result = ::InternetCloseHandle(hHttpRequest);
if(result)
{
result = ::InternetCloseHandle(hHttpSession);
if (result)
{
result = ::InternetCloseHandle(hInternetSession);
if(!result) return ::GetLastError();
}
else return ::GetLastError();
}
else return ::GetLastError();
However, being new to WinInet, I am not sure if my solution is correct.
QUESTION:
Can you please instruct me on how to handle the scenario in the provided code example?
I understand that my question might be confusing, but please take into consideration that English is not my native. Please leave a comment seeking further clarifications.
UPDATE #1:
I have tried to apply RAII:
#include <Windows.h>
#include <iostream>
#include <WinInet.h>
#pragma comment(lib, "Wininet.lib")
class CInternetOpenRAII
{
HINTERNET hIntSession;
public:
CInternetOpenRAII(){}
HINTERNET get() const { return hIntSession; }
DWORD init()
{
hIntSession = ::InternetOpen("WinInet", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
return hIntSession ? ERROR_SUCCESS : ::GetLastError();
}
~CInternetOpenRAII()
{
if(hIntSession)
{
if(!::InternetCloseHandle(hIntSession))
{
std::cerr << "InternetOpen failed with GetLastErrorCode: " << ::GetLastError();
}
}
}
};
class CInternetConnectRAII
{
HINTERNET hHttpSession;
public:
CInternetConnectRAII() {}
HINTERNET get() const { return hHttpSession; }
DWORD init(const HINTERNET &hIntSession, const char *url)
{
hHttpSession = ::InternetConnect(hIntSession, url, INTERNET_DEFAULT_HTTP_PORT, 0, 0, INTERNET_SERVICE_HTTP, 0, NULL);
return hHttpSession ? ERROR_SUCCESS : ::GetLastError();
}
~CInternetConnectRAII()
{
if(hHttpSession)
{
if(!::InternetCloseHandle(hHttpSession))
{
std::cerr << "InternetConnect failed with GetLastErrorCode: " << ::GetLastError();
}
}
}
};
class CHttpOpenRequestRAII
{
HINTERNET hHttpRequest;
public:
CHttpOpenRequestRAII() {}
HINTERNET get() const { return hHttpRequest; }
DWORD init(const HINTERNET &hHttpSession, const char *request)
{
hHttpRequest = ::HttpOpenRequest(hHttpSession, "POST", request, 0, 0, 0, INTERNET_FLAG_RELOAD, 0);
return hHttpRequest ? ERROR_SUCCESS : ::GetLastError();
}
DWORD doRequest(const char *data, size_t dataLength, const char *header, size_t headerLength)
{
if (!::HttpSendRequest(hHttpRequest, header, headerLength, (void *)data, dataLength))
return ::GetLastError();
CHAR szBuffer[10] = "";
DWORD dwRead = 0;
const int dwBytes2Read = sizeof(szBuffer) - 1;
while (::InternetReadFile(hHttpRequest, szBuffer, dwBytes2Read, &dwRead) && dwRead)
{
std::cout << szBuffer;
}
return ERROR_SUCCESS;
}
~CHttpOpenRequestRAII()
{
if(hHttpRequest)
{
if(!::InternetCloseHandle(hHttpRequest))
{
std::cerr << "HttpOpenRequest failed with GetLastErrorCode: " << ::GetLastError();
}
}
}
};
int main()
{
DWORD error = ERROR_SUCCESS;
CInternetOpenRAII session;
error = session.init();
if(error) return error;
CInternetConnectRAII conn;
error = conn.init(session.get(), "www.test.com");
if(error) return error;
CHttpOpenRequestRAII req;
error = req.init(conn.get(), "/home/something");
if(error) return error;
error = req.doRequest("parameter=1234", strlen("parameter=1234"),
"Content-Type: application/x-www-form-urlencoded", strlen("Content-Type: application/x-www-form-urlencoded"));
if(error) return error;
return 0;
}
Now I do not know how to handle error in destructor. Can somebody please look at the code and provide some advice on that?
I need help with http get. I use vsc++ 2015. I have my own code, but it seems to be wrong, so I get reply from server in a strange format.
Example : 034a0686bc29ca826dbb2f1ea4dd1879═
so the Source is:
#include "Connection.h"
CConnector g_pConnector;
CConnector::CConnector() {
}
CConnector::~CConnector() {
}
void CConnector::Connect(char* Url, char* Host) { m_Url = Url; m_Host = Host; }
void CConnector::SendPOST(const char* data, std::string &sDestBuffer) { try { char httpUseragent[512]; DWORD szhttpUserAgent = sizeof(httpUseragent); ObtainUserAgentString(0, httpUseragent, &szhttpUserAgent);
CString sMsg = ""; sMsg += /*\r\ncontent-type: application/x-www-form-urlencoded*/"\r\ncontent-type: application/x-www-form-urlencoded"; sMsg += /*\r\ncontent-lenght:
*/"\r\ncontent-lenght: "; sMsg += std::to_string(strlen(data)).c_str(); sMsg += /*\r\nuser-agent: secret_agent\r\n\r\n*/"\r\nuser-agent: secret_agent\r\n\r\n";
HINTERNET internet = InternetOpenA(httpUseragent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if (internet != NULL) {
HINTERNET connect = InternetConnectA(internet, m_Host, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); if (connect != NULL) {
HINTERNET request = HttpOpenRequestA(connect, /*POST*/"POST", m_Url, /*HTTP/1.1*/"HTTP/1.1", NULL, NULL,
INTERNET_FLAG_HYPERLINK | INTERNET_FLAG_IGNORE_CERT_CN_INVALID |
INTERNET_FLAG_IGNORE_CERT_DATE_INVALID |
INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP |
INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS |
INTERNET_FLAG_NO_AUTH |
INTERNET_FLAG_NO_CACHE_WRITE |
INTERNET_FLAG_NO_UI |
INTERNET_FLAG_PRAGMA_NOCACHE |
INTERNET_FLAG_RELOAD, NULL);
if (request != NULL)
{
int datalen = 0;
if (data != NULL) datalen = strlen(data);
int headerlen = 0;
if (!sMsg.IsEmpty()) headerlen = strlen(sMsg);
HttpSendRequestA(request, sMsg, headerlen, _strdup(data), datalen);
if (request)
{
DWORD dataSize = 0;
DWORD dwBytesRead = 0;
DWORD dwBytesWritten = 0;
char* data = NULL;
do {
char buffer[2000];
InternetReadFile(request, (LPVOID)buffer, _countof(buffer), &dwBytesRead);
char *tempData = new char[dataSize + dwBytesRead];
memcpy(tempData, data, dataSize);
memcpy(tempData + dataSize, buffer, dwBytesRead);
delete[] data;
data = tempData;
dataSize += dwBytesRead;
} while (dwBytesRead);
sDestBuffer = data;
}
InternetCloseHandle(request);
} } InternetCloseHandle(connect); } InternetCloseHandle(internet); } catch (...) {} }
void CConnector::SendGET(const char* data, std::string &sDestBuffer) { try { char httpUseragent[512]; DWORD szhttpUserAgent = sizeof(httpUseragent); ObtainUserAgentString(0, httpUseragent, &szhttpUserAgent);
CString sMsg = ""; CString Url = m_Url; Url += "?"; Url += data;
HINTERNET internet = InternetOpenA(httpUseragent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if (internet != NULL) {
HINTERNET connect = InternetConnectA(internet, m_Host, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); if (connect != NULL) {
HINTERNET request = HttpOpenRequestA(connect, /*GET*/"GET", Url, /*HTTP/1.1*/"HTTP/1.1", NULL, NULL,
INTERNET_FLAG_HYPERLINK | INTERNET_FLAG_IGNORE_CERT_CN_INVALID |
INTERNET_FLAG_IGNORE_CERT_DATE_INVALID |
INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP |
INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS |
INTERNET_FLAG_NO_AUTH |
INTERNET_FLAG_NO_CACHE_WRITE |
INTERNET_FLAG_NO_UI |
INTERNET_FLAG_PRAGMA_NOCACHE |
INTERNET_FLAG_RELOAD, NULL);
if (request != NULL)
{
int datalen = 0;
if (data != NULL) datalen = strlen(data);
int headerlen = 0;
if (!sMsg.IsEmpty()) headerlen = strlen(sMsg);
HttpSendRequestA(request, sMsg, headerlen, _strdup(data), datalen);
if (request)
{
DWORD dataSize = 0;
DWORD dwBytesRead = 0;
DWORD dwBytesWritten = 0;
char* data = NULL;
do {
char buffer[2000];
InternetReadFile(request, (LPVOID)buffer, _countof(buffer), &dwBytesRead);
char *tempData = new char[dataSize + dwBytesRead];
memcpy(tempData, data, dataSize);
memcpy(tempData + dataSize, buffer, dwBytesRead);
delete[] data;
data = tempData;
dataSize += dwBytesRead;
} while (dwBytesRead);
sDestBuffer = data;
}
InternetCloseHandle(request);
} } InternetCloseHandle(connect); }
InternetCloseHandle(internet); } catch (...) {} }
and I try getting reply like this
std::string request;
char key[128];
g_pConnector.Connect(script.php?something=139, "sample.com");
g_pConnector.SendGET(key, request);
I have been trying this the whole day but no luck i want to upload an image file to a php file which i have created but when ever i try to do that winhttpsendrequest throws 183 error that means cannot send file that is already sent please can someone point out where i am wrong
c++ code:
int _tmain(int argc, _TCHAR* argv[]) {
HINTERNET hSession = NULL,
hConnect = NULL,
hRequest = NULL;
BOOL bResults = FALSE;
FILE *pFile;
long lSize;
char *buffer;
size_t result;
pFile = fopen("blog.jpg", "rb");
fseek(pFile, 0, SEEK_END);
lSize = ftell(pFile);
rewind(pFile);
buffer = (char *) malloc(sizeof(char) * lSize);
result = fread(buffer, 1, lSize, pFile);
fclose(pFile);
hSession = WinHttpOpen( L"WinHTTP Example/1.0",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0);
if (hSession)
hConnect = WinHttpConnect(hSession, L"localhost",
INTERNET_DEFAULT_HTTP_PORT, 0);
if (hConnect)
hRequest = WinHttpOpenRequest(hConnect, L"POST", L"locker/upload.php",
NULL, WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
WINHTTP_FLAG_REFRESH);
static WCHAR frmdata[2048] = L"Connection: keep-alive\r\nContent-Type: multipart/form-data; -----------------------------7d82751e2bc0858\r\nContent-Disposition: form-data; name=\"file\"; filename=\"blog.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";
bResults = WinHttpSendRequest(hRequest,
frmdata, wcslen(frmdata), buffer,
lSize, wcslen(frmdata)+lSize, 0);
if (bResults) {
/*
DWORD dwBytesWritten = 0;
bResults = WinHttpWriteData(hRequest, buffer,
lSize,
&dwBytesWritten);
if (bResults) {
printf_s("Data: %d", dwBytesWritten);
}
*/
} else {
printf_s("SendReq: %d", GetLastError());
}
free(buffer);
if (hRequest) { WinHttpCloseHandle(hRequest); }
if (hConnect) { WinHttpCloseHandle(hConnect); }
if (hSession) { WinHttpCloseHandle(hSession); }
getchar();
return 0;
}
php code:
if (isset($_FILES["file"])) {
$target_path = "uploads/";
$target_path = $target_path . basename( $_FILES['file']['name']);
if(move_uploaded_file($_FILES['file']['tmp_name'], $target_path)) {
echo "The file ". basename( $_FILES['file']['name']). " has been uploaded";
} else{
echo "There was an error uploading the file, please try again!";
}
}
Keshav Nair.
try to this code:
CHAR postData[1024];
CHAR postData2[1024];
ZeroMemory(&postData,1024);
ZeroMemory(&postData2,1024);
WinHttpAddRequestHeaders(hRequest,L"Content-Type: multipart/form-data; boundary=----OiRBxC0fjdSEpqhd",-1L,WINHTTP_ADDREQ_FLAG_ADD);
wsprintfA(postData,"%s","----OiRBxC0fjdSEpqhd\r\nContent-Disposition: form-data; name=\"file\"; filename=\"blog.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n");
wsprintfA(postData2,"%s","\r\n----OiRBxC0fjdSEpqhd\r\nContent-Disposition: form-data; name=\"submit\"\r\n\r\nSubmit\r\n----OiRBxC0fjdSEpqhd--\r\n");
bResults = WinHttpSendRequest( hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,
0, WINHTTP_NO_REQUEST_DATA, 0,
lstrlenA(postData)+lstrlenA(postData2)+lSize, NULL);
if (bResults)
{
bResults=WinHttpWriteData(hRequest,LPCVOID)postData,lstrlenA(postData),NULL);
bResults = WinHttpWriteData(hRequest, buffer, lSize, &dwBytesWritten);
bResults=WinHttpWriteData(hRequest,(LPCVOID)postData2,lstrlenA(postData2),NULL);
}
WinHttpWriteData:
POST data - postData, postData2 must be 8 bit encoding.