How can I find if a webpage exists using WinINet - c++

I am trying to connect and ensure various pages exist on a webserver provided by an instrument we design. I am trying to do this through C++ Win32 using WinInet commands.
I am happy that I have connected correctly to the webserver via HTTP:
hInternet = InternetOpen("Test", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0/*INTERNET_FLAG_ASYNC*/);
hhttp = InternetConnect(hInternet, "192.168.111.222", INTERNET_DEFAULT_HTTP_PORT, "admin", "admin", INTERNET_SERVICE_HTTP, 0, 0);
I believe I then have to open a request.
hHttpRequest = HttpOpenRequest(hhttp, "GET", "galogo.png", NULL, "192.168.111.222", lplpszAcceptTypes, INTERNET_FLAG_RELOAD | INTERNET_FLAG_PRAGMA_NOCACHE, 0);
and then send the request.
HttpSendRequest(hHttpRequest, NULL, 0, NULL, 0)
Note: 192.168.111.222 is the address of the unit running the webserver and galogo.png is an image displayed on the home page. Please also note that I am error checking between each statements so if I do disconnect the Ethernet then I do get a failure.
Initially I did try just connecting to the home.html page but this always passed so I thought I should try and get the image but I am probably lacking in knowledge. Other examples seem to then stream data but I wasn't sure if I needed to do this.
Most of the examples I have seen seem to show the HtppSendRequest in this format and I don't really understand about headers etc. Maybe it is here I am going wrong.

The HttpQueryInfo function will give header information relating to the request, and you can extract the HTTP status code from this.
You may be able to achieve the result more easily using higher level WinINet functions. I would suggest a sequence consisting of InternetOpen, InternetOpenUrl, HttpQueryInfo and then repeated calls to InternetReadFile if the HTTP status code is OK.
This Delphi code (from Delphi 7, so pre-Unicode) seems to do the job: -
function GetUrlContent(const Agent, Url: string): string;
var
NetHandle: HINTERNET;
UrlHandle: HINTERNET;
Buffer: array [0..1024] of Char;
BytesRead: DWORD;
Dummy: DWORD;
BufLen: DWORD;
HttpStatus: string;
begin
Result := '';
NetHandle := InternetOpen(PChar(Agent), INTERNET_OPEN_TYPE_PRECONFIG,
nil, nil, 0);
if Assigned(NetHandle) then
begin
UrlHandle := InternetOpenUrl(NetHandle, PChar(Url), nil, 0,
INTERNET_FLAG_RELOAD, 0);
if Assigned(UrlHandle) then
// UrlHandle valid? Proceed with download.
try
BufLen := Length(Buffer);
Dummy := 0;
// only get the file if the HTTP status code is 200
if HttpQueryInfo(UrlHandle, HTTP_QUERY_STATUS_CODE, #Buffer[0], BufLen, Dummy) then
begin
HttpStatus := Buffer;
if HttpStatus = '200' then
begin
FillChar(Buffer, SizeOf(Buffer), 0);
repeat
Result := Result + Buffer;
FillChar(Buffer, SizeOf(Buffer), 0);
InternetReadFile(UrlHandle, #Buffer, SizeOf(Buffer), BytesRead);
until BytesRead = 0;
end
else begin
raise Exception.CreateFmt('HTTP status code %s', [HttpStatus]);
end;
end
else begin
raise Exception.Create('Unable to read HTTP status code');
end;
finally
InternetCloseHandle(UrlHandle);
end
else begin
// UrlHandle is not valid. Raise an exception.
raise Exception.CreateFmt('Cannot open URL %s', [Url]);
end;
InternetCloseHandle(NetHandle);
end
else begin
// NetHandle is not valid. Raise an exception.
raise Exception.Create('Unable to initialize WinINet');
end;
end;

So, using a combination of cURL and Wireshark I'm finally there. I was making some fundamental mistakes but basically on the right track.
First open the connection and connect as previously stated, making sure it is not ASYNC (this lead to some overlapped IO errors):
hInternet = InternetOpen("Test", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0/*INTERNET_FLAG_ASYNC*/);
hhttp = InternetConnect(hInternet, "192.168.111.222", INTERNET_DEFAULT_HTTP_PORT, "admin", "admin", INTERNET_SERVICE_HTTP, 0, 0);
I needed to create the request and then send it. I only needed to specify the page as the request will take in connection details.
hHttpRequest = HttpOpenRequest(hhttp, "GET", "home.html", NULL, NULL, lplpszAcceptTypes, INTERNET_FLAG_RELOAD | INTERNET_FLAG_PRAGMA_NOCACHE, 0);
HttpSendRequest(hHttpRequest, NULL, 0, NULL, 0);
Then use the HttpQueryInfo function to retrieve the status and convert back to integer. Make sure you are sending the handle from the Request not the Connect.
//These are defined earlier
DWORD statCharLen = 0;
char statChar[256]="";
statCharLen = sizeof(statChar);
HttpQueryInfo(hHttpRequest, HTTP_QUERY_STATUS_CODE, statChar, &statCharLen, NULL);
Finally shut down connection:
InternetCloseHandle(hInternet)
Thanks

Its is Simple following are the Steps:
1- Open Connection
2- Connect
3- Open request
4- Send request
5- Read file
6- Save file (as png or jpg)
7- Close handles
The code is as follow:
#include <iostream>
#include <string>
#include <Windows.h>
#include <wininet.h>
#pragma comment(lib, "wininet")
using namespace std;
void download(string domain,string url,string filepath)
{
//Step 1:
HINTERNET hIntSession = InternetOpenA("MyApp", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
//Step 2:
HINTERNET hHttpSession = InternetConnectA(hIntSession, domain.c_str(), 80, 0, 0, INTERNET_SERVICE_HTTP, 0, NULL);
//Step 3:
HINTERNET hHttpRequest = HttpOpenRequestA( hHttpSession, "GET",url.c_str(),0, 0, 0, INTERNET_FLAG_RELOAD, 0);
TCHAR* szHeaders = L"";
CHAR szReq[1024] = "";
//Step 4:
if( !HttpSendRequest(hHttpRequest, szHeaders, wcslen(szHeaders), szReq, strlen(szReq))) {
DWORD dwErr = GetLastError();
cout<<"error "<<dwErr<<endl;
/// handle error
}
TCHAR szBuffer[1025];
DWORD dwRead=0;
FILE *f;
f=fopen(filepath.c_str(),"wb");
//Step 5 & 6:
while(InternetReadFile(hHttpRequest,szBuffer, 1024, &dwRead) && dwRead)
{
fwrite(szBuffer,sizeof(BYTE),1024,f);
dwRead=0;
}
fclose(f);
//Step 7:
InternetCloseHandle(hHttpRequest);
InternetCloseHandle(hHttpSession);
InternetCloseHandle(hIntSession);
}
int main()
{
download("www.stacktoheap.com","images/stackoverflow.png","C:\\Example\\example.png");
}

Related

Bad Request: message text is empty when sending get request via winapi to telegram bot

I'm trying to send message to telegram chat from bot using winapi and c++.
Here is my code
char szData[1024];
// initialize WinInet
HINTERNET hInternet = ::InternetOpen(TEXT("WinInet Test"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (hInternet != NULL)
{
// open HTTP session
HINTERNET hConnect = ::InternetConnect(hInternet, L"api.telegram.org", INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, NULL, 1);
if (hConnect != NULL)
{
wstring request = L"/bot<bot_id>/sendMessage";
// open request
HINTERNET hRequest = ::HttpOpenRequest(hConnect, L"GET", (LPCWSTR)request.c_str(), NULL, NULL, 0, INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_SECURE, 1);
if (hRequest != NULL)
{
// send request
const wchar_t* params = L"?chat_id=<chat_id>&text=test";
BOOL isSend = ::HttpSendRequest(hRequest, NULL, 0, (LPVOID)params, wcslen(params));
if (isSend)
{
for (;;)
{
// reading data
DWORD dwByteRead;
BOOL isRead = ::InternetReadFile(hRequest, szData, sizeof(szData) - 1, &dwByteRead);
// break cycle if error or end
if (isRead == FALSE || dwByteRead == 0)
break;
// saving result
szData[dwByteRead] = 0;
}
}
// close request
::InternetCloseHandle(hRequest);
}
// close session
::InternetCloseHandle(hConnect);
}
// close WinInet
::InternetCloseHandle(hInternet);
}
wstring answer = CharPToWstring(szData);
return answer;
But I've got {"ok":false,"error_code":400,"description":"Bad Request: message text is empty"} response. <chat_id> is id consisted of digits(12345678).
If I run this request in postman or in browser - then everything is ok.
I also tried to run this request using WinHttp* methods and result is the same.
What should I change in my request parameters to make it work?
There are a number of issues with this code:
You don't need to typecast the return value of wstring::c_str() to LPCWSTR (aka const wchar_t*), as it is already that type.
You can't send body data in a GET request. The Telegram Bot API expects body data to be sent in a POST request instead.
You are telling HttpSendRequest() to send body data from a wchar_t* UTF-16 string, but that is not the correct encoding that the server is expecting. You need to use a char* UTF-8 string instead.
You are not sending a Content-Type request header to tell the server what the format of the body data is. The API supports several different formats. In this case, since you are sending the data in application/x-www-form-urlencoded format, you need to add a Content-Type: application/x-www-form-urlencoded header to the request.
With all of that said, try this instead:
// initialize WinInet
HINTERNET hInternet = ::InternetOpenW(L"WinInet Test", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (hInternet == NULL) ... // error handling
// open HTTP session
HINTERNET hConnect = ::InternetConnectW(hInternet, L"api.telegram.org", INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, NULL, 1);
if (hConnect == NULL) ... // error handling
// open request
wstring wsResource = L"/bot<bot_id>/sendMessage";
HINTERNET hRequest = ::HttpOpenRequestW(hConnect, L"POST", wsResource.c_str(), NULL, NULL, 0, INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_SECURE, 1);
if (hRequest == NULL) ... // error handling
// send request
string sBody = u8"chat_id=<chat_id>&text=test";
BOOL isSend = ::HttpSendRequestW(hRequest, L"Content-Type: application/x-www-form-urlencoded", -1L, sBody.c_str(), sBody.size());
if (!isSend) ... // error handling
string sReply;
char szData[1024];
DWORD dwByteRead;
while (::InternetReadFile(hRequest, szData, sizeof(szData), &dwByteRead) && dwByteRead != 0)
{
// saving result
sReply.append(szData, dwByteRead);
}
...
// use sReply as needed ...

Sending a POST using HttpSendRequestA fails with ERROR_HTTP_HEADER_NOT_FOUND?

I'm trying to post data to a test .php script using XAMPP on my local machine, but it always fails with ERROR_HTTP_HEADER_NOT_FOUND. I check the server logs and no request was sent to Apache. I can manually do it via a web browser and the php script runs as expected.
Here's the C++ code that doesn't work. Can someone point out the problem?
static const char *accepttypes[]={ "application/x-www-form-urlencoded", NULL};
static const char headers[]="application/x-www-form-urlencoded\r\n";
// open session
HINTERNET hsession;
if ((hsession=InternetOpen(_T("Whatever"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0)) != NULL) {
HINTERNET hconnect;
if ((hconnect=InternetConnect(hsession, _T("127.0.0.1"), INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0)) != NULL) {
HINTERNET hpostreq;
if ((hpostreq=HttpOpenRequestA(hconnect, "POST", "/mytest.php", NULL, NULL, accepttypes, INTERNET_FLAG_RELOAD, 0)) != NULL) {
BYTE *data=(BYTE*)"xyz=1234";
DWORD datasize=8;
if (HttpSendRequestA(hpostreq, headers, sizeof(headers), (LPVOID) data, datasize)) {
....
// ^^^^^ That always fails with ERROR_HTTP_HEADER_NOT_FOUND
I see two mistakes in your call to HttpSendRequestA():
The value of headers needs to be changed from "application/x-www-form-urlencoded\r\n" to "Content-Type: application/x-www-form-urlencoded".
sizeof(headers) needs to be changed to either -1, sizeof(headers)-1, or strlen(headers). You are expected to pass in either -1 to let the function calculate the character length of the headers string, or you can pass in the actual character length. The string's null terminator is not to be included in that length.

Unable to obtain POST request response using wininet

I need to make a POST request to an API to get some XML data (http://freecite.library.brown.edu/welcome/api_instructions). This works fine with curl:
curl -H "Accept: application/xml" --data "citation=Udvarhelyi, I.S., Gatsonis, C.A., Epstein, A.M., Pashos, C.L., Newhouse, J.P. and McNeil, B.J. Acute Myocardial Infarction in the Medicare population: process of care and clinical outcomes. Journal of the American Medical Association, 1992; 18:2530-2536. " http://freecite.library.brown.edu:80/citations/create
So I am trying to do a similar thingy using Win32 SDK. This is my code:
void LoadData()
{
wil::unique_hinternet hInternet(InternetOpen(L"Dummy", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0));
wil::unique_hinternet hConnect(InternetConnect(hInternet.get(), L"http://freecite.library.brown.edu", 80, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0));
wil::unique_hinternet hRequest(HttpOpenRequest(hConnect.get(), L"POST", L"/citations/create", NULL, NULL, NULL, NULL, NULL));
wstring data = L"citation=Udvarhelyi, I.S., Gatsonis, C.A., Epstein, A.M., Pashos, C.L., Newhouse, J.P. and McNeil, B.J. Acute Myocardial Infarction in the Medicare population: process of care and clinical outcomes. Journal of the American Medical Association, 1992; 18:2530-2536.";
PCWSTR szHeaders = L"Accept: application/xml";
HttpSendRequest(hRequest.get(), szHeaders, 0, (LPVOID)data.c_str(), static_cast<int>(data.length()));
DWORD availableBytes = 0;
InternetQueryDataAvailable(hRequest.get(), &availableBytes, 0, 0);
PBYTE outputBuffer = (PBYTE)HeapAlloc(GetProcessHeap(), 0, availableBytes);
PBYTE nextBytes = outputBuffer;
DWORD bytesUsed = 0; // number of used bytes.
while (availableBytes)
{
DWORD downloadedBytes;
InternetReadFile(hRequest.get(), nextBytes, availableBytes, &downloadedBytes);
bytesUsed = bytesUsed + downloadedBytes;
InternetQueryDataAvailable(hRequest.get(), &availableBytes, 0, 0);
if (availableBytes > 0)
{
// lazy buffer growth here. Only alloc for what we need. could be optimized if we end up with huge payloads (>10MB).
// otherwise, this is good enough.
outputBuffer = (PBYTE)HeapReAlloc(GetProcessHeap(), 0, outputBuffer, bytesUsed + availableBytes);
nextBytes = outputBuffer + bytesUsed; // careful, pointer might have moved! Update cursor.
}
}
// Convert outputed XML to wide char
int size_needed = MultiByteToWideChar(CP_UTF8, 0, (PCCH)outputBuffer, bytesUsed, NULL, 0);
std::wstring wstrTo(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, (PCCH)outputBuffer, bytesUsed, &wstrTo[0], size_needed);
wstring res = wstrTo;
}
The problem is, before entering the for loop, even after the call to InternetQueryDataAvailable, availableBytes comes out to be 0. As a result, I finally end up getting a blank string as response, whereas I was expecting a XML response.
Can anyone point me what am I doing wrongly, and how to fix it?
InternetConnect expects server name or IP address, so don't include "http://" in the address. Change to:
InternetConnect(handle, L"freecite.library.brown.edu"...);
Use UTF-8 for data. Other parameters for WinAPI functions are correctly using UTF-16, they automatically make the necessary conversions.
Change the header:
std::wstring szHeaders = L"Content-Type: application/x-www-form-urlencoded\r\n";
accept should be sent through HttpOpenRequest
const wchar_t *accept[] = { L"text/xml", NULL };
HINTERNET hrequest = HttpOpenRequest(hconnect, L"POST", L"/citations/create",
NULL, NULL, accept, 0, 0);
Note, if you don't specify accept (use NULL in its place) then the result can be in plain html.
The example below should return XML.
Note, for simplicity I put optional as ANSI string, but it should be UTF8, then you convert it to UTF16 woptional and send it. result will be UTF8 string, it should be converted to UTF16 for Windows's display.
#include <iostream>
#include <string>
#include <Windows.h>
#include <WinINet.h>
#pragma comment(lib, "wininet.lib")//include WinINet library
int main()
{
std::string result;
std::wstring server = L"freecite.library.brown.edu";
std::wstring objectname = L"/citations/create"; //file in this case!
std::wstring header = L"Content-Type: application/x-www-form-urlencoded\r\n";
std::string optional = "citation=Udvarhelyi, I.S., Gatsonis, C.A., Epstein";
HINTERNET hsession = InternetOpen(L"appname",
INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
HINTERNET hconnect = InternetConnect(hsession, server.c_str(),
INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
const wchar_t* accept[] = { L"text/xml", NULL };
HINTERNET hrequest = HttpOpenRequest(hconnect, L"POST", objectname.c_str(),
NULL, NULL, accept, 0, 0);
if(HttpSendRequest(hrequest, header.c_str(), header.size(),
&optional[0], optional.size()))
{
DWORD blocksize = 4096;
DWORD received = 0;
std::string block(blocksize, 0);
while (InternetReadFile(hrequest, &block[0], blocksize, &received)
&& received)
{
block.resize(received);
result += block;
}
std::cout << result << std::endl;
}
if (hrequest) InternetCloseHandle(hrequest);
if (hconnect) InternetCloseHandle(hconnect);
if (hsession) InternetCloseHandle(hsession);
return 0;
}

Purpose of WINHTTP_QUERY_URI in WinHTTP?

What HTTP header exactly can be queried using WINHTTP_QUERY_URI flag with WinHttpQueryHeaders function? After reading its description I was under impression this flag was supposed to be used to get the URI of the request specified in WinHttpOpenRequest function. Yet the following program gives me an error code 12019 ERROR_INTERNET_INCORRECT_HANDLE_STATE (and 12150 ERROR_HTTP_HEADER_NOT_FOUND if I uncomment two commented lines).
#include <cstdio>
#include <windows.h>
#include <winhttp.h>
#pragma comment(lib, "winhttp.lib")
int main()
{
HINTERNET hSession = WinHttpOpen(nullptr, WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
HINTERNET hConnect = WinHttpConnect(hSession, L"www.ietf.org", INTERNET_DEFAULT_HTTP_PORT, 0);
HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", L"/rfc/rfc2616.txt", nullptr, WINHTTP_NO_REFERER, nullptr, 0);
//WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
//WinHttpReceiveResponse(hRequest, 0);
wchar_t url[1024] = {};
DWORD url_size = sizeof(url);
auto success = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_URI, WINHTTP_HEADER_NAME_BY_INDEX, url, &url_size, WINHTTP_NO_HEADER_INDEX);
auto error_code = GetLastError();
wprintf(L"success=%d error_code=%u url=%s", success, error_code, url);
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
}
P.S. Yes, I know I can get request URI using WinHttpQueryOption and WINHTTP_OPTION_URL, no need to point that out.
EDIT. Adding WINHTTP_QUERY_FLAG_REQUEST_HEADERS flag as per Captain Obvlious answer below (which totally makes sense if WINHTTP_QUERY_URI was indeed supposed to return request URI) did not make much difference: now with or without WinHttpSendRequest and WinHttpReceiveResponse calls WinHttpQueryHeaders function produces error code 12150 ERROR_HTTP_HEADER_NOT_FOUND.
You are querying the response headers of the request which do not contain the URI. You need to include the WINHTTP_QUERY_FLAG_REQUEST_HEADERS modifier flag to retrieve from the request header.
WinHttpQueryHeaders(
hRequest,
WINHTTP_QUERY_URI | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
WINHTTP_HEADER_NAME_BY_INDEX,
url,
&url_size,
WINHTTP_NO_HEADER_INDEX);

POST form data using WinInet c++

I'm trying to make this program connect to a website and submit form data in order to login, but I don't know what I'm doing wrong. I have heard of others like curl and Winsock but I chose the WinINet library. So just for the testing of this program I've been using the website Pastebin to post to. So far, I haven't seen any results from this. If this program succeeds in posting the form data it will give me the header to the location of the post on their site.
Am I writing the form data char* correctly? I have seen on other stackoverflow posts where they had a large amount of dashes before some number then the put their form data.
Do I need to add something to it make it simulate clicking the submit button?
Do I need to write out values for each elements on the form?
I have tried HttpAddRequestHeaders and that didn't help me.
Also, I get the ERROR_INSUFFICIENT_BUFFER error on HttpOpenRequest but it still returns a valid HINTERNET.
#include <Windows.h>
#include <WinInet.h>
#include <iostream>
#pragma comment( lib,"Wininet.lib")
using namespace std;
char* getheaders(HINTERNET hRequest){
DWORD dwInfoLevel=HTTP_QUERY_RAW_HEADERS_CRLF;
DWORD dwInfoBufferLength=10;
char* pInfoBuffer=(char*)malloc(dwInfoBufferLength+1);
while(!HttpQueryInfo(hRequest,dwInfoLevel,pInfoBuffer,&dwInfoBufferLength,NULL)){
if (GetLastError()==ERROR_INSUFFICIENT_BUFFER){
free(pInfoBuffer);
pInfoBuffer=(char*)malloc(dwInfoBufferLength+1);
}else{
fprintf(stderr,"HttpQueryInfo failed, error = %d (0x%x)\n",GetLastError(),GetLastError());
break;
}
}
pInfoBuffer[dwInfoBufferLength] = '\0';
return pInfoBuffer;
}
void readfile(HINTERNET hRequest,char** buffs,int size){
DWORD dwBytesAvailable;
DWORD dwBytesRead;
for(int i=0;i<size;i++){
if(!InternetQueryDataAvailable(hRequest,&dwBytesAvailable,0,0)) break;
buffs[i]=(char*)malloc(dwBytesAvailable+1);
bool bResult=InternetReadFile(hRequest,buffs[i],dwBytesAvailable,&dwBytesRead);
if(!bResult | dwBytesRead==0) break;
}
}
int main(int argc,char** argv){
char* hdrs="Content-Type: application/x-www-form-urlencoded";
char* frmdata="paste_code=test";
LPCSTR accept[2]={"*/*", NULL};
HINTERNET hSession = InternetOpen("http generic",INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
HINTERNET hConnect = InternetConnect(hSession, "www.pastebin.com",INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
HINTERNET hRequest = HttpOpenRequest(hConnect, "GET","/", NULL, NULL, accept, 0, 0);
//ERROR_INSUFFICIENT_BUFFER (122) with "accept".
bool send=HttpSendRequest(hRequest, hdrs, strlen(hdrs), NULL,NULL);
if(!send){
printf("HttpSendRequest failed, code=%d",GetLastError());
system("pause>nul");
return 0;
}
char* heads=getheaders(hRequest);
printf("%s\n\n\n\n",heads);
HINTERNET hRequest2 = HttpOpenRequest(hConnect, "POST","/", NULL, NULL, accept, 0, 0);
//ERROR_INSUFFICIENT_BUFFER (122) with "accept".
send=HttpSendRequest(hRequest2, hdrs, strlen(hdrs), frmdata,strlen(frmdata));
if(!send){
printf("HttpSendRequest failed, code=%d",GetLastError());
system("pause>nul");
return 0;
}
heads=getheaders(hRequest);
printf("%s\n\n\n\n",heads);
InternetCloseHandle(hRequest);
InternetCloseHandle(hRequest2);
InternetCloseHandle(hConnect);
InternetCloseHandle(hSession);
system("pause>nul");
return 0;
}
Your code is nearly correct, you must make sure of the following points:
char* hdrs="Content-Type: application/x-www-form-urlencoded";
you must make sure that your return object from POST message will be of type x-www-form-urlencoded or JSON . if it's JSON you
need to define char* hdrs="Content-Type: application/json\r\n";
Note: you must append \r\n to the hdrs.
try to call readFile method with buffer of size 10000 for example
and print buffer , it will print the output of the response to the
connection
In HINTERNET hRequest2 = HttpOpenRequest(hConnect, "POST","/", NULL, NULL, accept, 0, 0); instead of "/" you must call the path of
the requested API for example: .
In HINTERNET hRequest2 = HttpOpenRequest(hConnect, "POST", "/users/jsonlogin", NULL, NULL, accept, 0, 0);