How to send a POST with a JSON in a WebRequest() call using MQL4?

koul picture koul · Oct 10, 2016 · Viewed 15.6k times · Source

I would like to send a POST from MQL4-script, using a JSON-format to a Node-server.

I've tried the webRequest() standard function in MQL4, based on the following documentation, but it did NOT success.

From MQL4 Documentation:

Sending simple requests of type "key=value" using the header `Content-Type: application/x-www-form-urlencoded`.    

    int  WebRequest( const string  method,           // HTTP method  
                     const string  url,              // URL 
                     const string  cookie,           // cookie 
                     const string  referer,          // referer 
                     int           timeout,          // timeout 
                     const char   &data[],           // the array of the HTTP message body 
                     int           data_size,        // data[] array size in bytes 
                     char         &result[],         // an array containing server response data 
                      string      &result_headers    // headers of server response
                     );

and

Sending a request of any type specifying the custom set of headers for a more flexible interaction with various Web services.

    int  WebRequest( const string  method,           // HTTP method 
                     const string  url,              // URL 
                     const string  headers,          // headers  
                     int           timeout,          // timeout 
                     const char   &data[],           // the array of the HTTP message body 
                     char         &result[],         // an array containing server response data 
                     string       &result_headers    // headers of server response 
                     );


Parameters

    method          [in]  HTTP method.
    url             [in]  URL.
    headers         [in]  Request headers of type "key: value", separated by a line break "\r\n".
    cookie          [in]  Cookie value.
    referer         [in]  Value of the Referer header of the HTTP request.
    timeout         [in]  Timeout in milliseconds.
    data[]          [in]  Data array of the HTTP message body.
    data_size       [in]  Size of the data[] array.
    result[]       [out]  An array containing server response data.
    result_headers [out]  Server response headers. 

Returned value:
    HTTP server response code or -1 for an error.

Does anyone know how to perfom it?


UPDATE:


Here is the code on the MQL4-script side :

#include <Json\hash.mqh>
#include <Json\KoulJSONMgmt.mqh>
void OnStart()

    {
       string strParam = StringConcatenate("{","\"currency\"",":","\"",Symbol(),"\"",",","\"timeframe\"",":","\"",IntegerToString(Period()),"\"",",","\"ticktime\"",":","\"",TimeToString(TimeLocal(),TIME_DATE|TIME_SECONDS),"\"",",","\"bid\"",":",DoubleToString(MarketInfo(Symbol(),MODE_BID),4),",","\"ask\"",":",DoubleToString(MarketInfo(Symbol(),MODE_ASK),4),",","\"spread\"",":",DoubleToString(MarketInfo(Symbol(),MODE_SPREAD),0),"}");


        JSONParser *parser = new JSONParser();
        JSONValue *jv = parser.parse(strParam);
        string strJson = jv.toString();
        if (jv == NULL) {
            Print("error:"+(string)parser.getErrorCode()+parser.getErrorMessage());
        } else {
            Print("PARSED:"+strJson);
    //Example of json String :
    //EURUSD,M15: PARSED:{"bid" : 1.1152,"ask" : 1.1154,"spread" : 13,"ticktime" : "2016.10.10 16:24:01","currency" : "EURUSD","timeframe" : "15"}
        }

          string cookie=NULL,headers;
          char post[],result[];
          int res;
          string strResult,result_header;

          headers = "application/json";
          prmUrl=StringConcatenate("http://localhost/api"+"/"+"ticks");
          //--- Reset the last error code
          ResetLastError();
          int timeout=1000; //--- Timeout below 1000 (1 sec.) is not enough for slow Internet connection

          int intHostNameLength=StringLen(prmParameter);
          StringToCharArray(prmParameter,post,0,intHostNameLength);

          res=WebRequest("POST",prmUrl,headers,timeout,post,result,result_header);

          //--- Checking errors
          if(res==-1)
            {
             Print("Error in WebRequest. Error code  =",GetLastError());
             //--- Perhaps the URL is not listed, display a message about the necessity to add the address
             Print("Add the address '"+prmUrl+"' in the list of allowed URLs on tab 'Expert Advisors'","Error",MB_ICONINFORMATION);
            }
          else
           {
               for(int i=0;i<ArraySize(result);i++)
               {

                   if( (result[i] == 10) || (result[i] == 13)) {
                      continue;
                   } else {
                      strResult += CharToStr(result[i]);
                   }
               }
               ArrayCopy(strResult,result,0,0,WHOLE_ARRAY);

           }
           Print(strResult);

    }

And the Node side is :

server.js

//Create new Tick
app.post('/api/ticks', function(req, res) {
    console.log('Inserting New Tick');

    var tick = req.body;
    console.log('>'+JSON.stringify(tick,null,4));

    Tick.addTick(tick, function(err, tick){
        if(err) res.json(err);
        res.json(tick);
    });
});

and in model ticks.js

var mongoose = require('mongoose');


// User Schema
var TickSchema = mongoose.Schema({
    currency:{
        type: String
    },
    timeframe: {
        type: String
    },
    ticktime: {
        type: Date
    },
    bid: {
        type: Number
    },
    ask: {
        type: Number
    },
    spread: {
        type: Number
    },
    createddate :{
        type: Date,
        default:  Date.now
    }
}, {collection : 'fxTicks'});

var Tick = module.exports = mongoose.model('Tick', TickSchema);

//Create New Tick
module.exports.addTick = function(tick, callback){
    Tick.create(tick, callback);
};

// Get Ticks
module.exports.getTicks = function(callback, limit){
    Tick.find(callback).limit(limit);
};

Answer

Matthieu H picture Matthieu H · Dec 4, 2018

It works well for me, I have someone like this :

string response = SendResquest("POST", "GetPrediction", "[4, 7]", "Content-Type: application/json", 5000);

string SendResquest(string httpType, string methodName, string bodyData = "", string headers = "", int timeout)
{
    uchar bodyDataCharArray[];
    ArrayResize(bodyDataCharArray, StringToCharArray(bodyData, bodyDataCharArray)-1);

    int response = WebRequest(httpType, this.address+methodName, headers, timeout, bodyDataCharArray, this.resultDataCharArray, this.resultHeader);

    string result = CharArrayToString(this.resultDataCharArray); 

    if(response == 200)
        return result;
    Print("Error when trying to call API : ", response);
    return "";
}