forked from rosh/MQL5Book
119 lines
4.1 KiB
MQL5
119 lines
4.1 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| SocketReadWriteHTTP.mq5 |
| |||
//| Copyright 2022, MetaQuotes Ltd. |
| |||
//| https://www.mql5.com |
| |||
//+------------------------------------------------------------------+
| |||
#property description "Requests a header (meta-data) of a web-page (insecure HTTP)."
| |||
#property description "NB: Default 'Server' requires to allow 'www.mql5.com' in terminal settings - to use other servers, change the settings accordingly."
| |||
#property script_show_inputs
| |||
| |||
#include "..\..\Include\PRTF.mqh"
| |||
| |||
input string Server = "www.mql5.com";
| |||
input uint Port = 80;
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Send HTTP-request via socket (insecure connection) |
| |||
//+------------------------------------------------------------------+
| |||
bool HTTPSend(int socket, const string request)
| |||
{
| |||
char req[];
| |||
int len = StringToCharArray(request, req, 0, WHOLE_ARRAY, CP_UTF8) - 1;
| |||
if(len < 0) return false;
| |||
return SocketSend(socket, req, len) == len;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Receive HTTP-response via socket (insecure connection) |
| |||
//+------------------------------------------------------------------+
| |||
bool HTTPRecv(int socket, string &result, const uint timeout)
| |||
{
| |||
uchar response[];
| |||
int len; // must be signed int to keep -1 in case of error
| |||
uint start = GetTickCount();
| |||
result = "";
| |||
| |||
do
| |||
{
| |||
ResetLastError();
| |||
if(!(len = (int)SocketIsReadable(socket)))
| |||
{
| |||
Sleep(10); // wait for data or timeout
| |||
}
| |||
else
| |||
if((len = SocketRead(socket, response, len, 10)) > 0)
| |||
{
| |||
result += CharArrayToString(response, 0, len); // NB: no CP_UTF8 because of 'HEAD'er
| |||
const int p = StringFind(result, "\r\n\r\n");
| |||
if(p > 0)
| |||
{
| |||
// HTTP header ends with double "new line", so using this parsing
| |||
// we make sure entire header received
| |||
Print("HTTP-header found");
| |||
StringSetLength(result, p); // cut off document body
| |||
return true;
| |||
}
| |||
start = GetTickCount();
| |||
}
| |||
}
| |||
while(GetTickCount() - start < timeout && !IsStopped() && !_LastError);
| |||
| |||
if(_LastError) PRTF(_LastError);
| |||
| |||
return StringLen(result) > 0;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Script program start function |
| |||
//+------------------------------------------------------------------+
| |||
void OnStart()
| |||
{
| |||
PRTF(Server);
| |||
PRTF(Port);
| |||
const int socket = PRTF(SocketCreate());
| |||
if(socket == INVALID_HANDLE) return;
| |||
if(PRTF(SocketConnect(socket, Server, Port, 5000)))
| |||
{
| |||
if(PRTF(HTTPSend(socket, StringFormat(
| |||
"HEAD / HTTP/1.1\r\nHost: %s\r\nUser-Agent: MetaTrader 5\r\n\r\n",
| |||
Server))))
| |||
{
| |||
string response;
| |||
if(PRTF(HTTPRecv(socket, response, 5000)))
| |||
{
| |||
// may be usefull to track 'Content-Length:',
| |||
// 'Content-Language:', 'Last-Modified:'
| |||
// and other attributes in the header
| |||
Print(response);
| |||
}
| |||
}
| |||
}
| |||
SocketClose(socket);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
/*
| |||
Example:
| |||
| |||
Server=www.mql5.com / ok
| |||
Port=80 / ok
| |||
SocketCreate()=1 / ok
| |||
SocketConnect(socket,Server,Port,5000)=true / ok
| |||
HTTPSend(socket,StringFormat(HEAD / HTTP/1.1
| |||
Host: %s
| |||
| |||
,Server))=true / ok
| |||
HTTP-header found
| |||
HTTPRecv(socket,response,5000)=true / ok
| |||
HTTP/1.1 301 Moved Permanently
| |||
Server: nginx
| |||
Date: Sun, 31 Jul 2022 10:24:00 GMT
| |||
Content-Type: text/html
| |||
Content-Length: 162
| |||
Connection: keep-alive
| |||
Location: https://www.mql5.com/
| |||
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
| |||
X-Frame-Options: SAMEORIGIN
| |||
| |||
*/
| |||
//+------------------------------------------------------------------+
|