Home > Back-end >  Bad Request: message text is empty when sending get request via winapi to telegram bot
Bad Request: message text is empty when sending get request via winapi to telegram bot

Time:07-07

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?

CodePudding user response:

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 ...
  • Related