Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

converting Python to Delphi code

Next python code

from urllib.request import Request, urlopen
import urllib
import json

#ID access to API
TOKEN = "{YOUR_API_TOKEN}" # e.g.: "f03c3c76cc853ee690b879909c9c6f2a"
url = "https://cloudpanel-api.1and1.com/v1"

def _setStatusServer(id, content):
  #Configure the request
  _command = url + "/servers/" + id + "/status/action"
  _method = 'PUT'
  request = Request(_command, data=content.encode(encoding='utf_8'), 
                    headers={'X-TOKEN':TOKEN, 'content-
                    type':'application/json'}, 
                    method=_method)

   #Try to get the response
   try:
     response = urlopen(request)
     content = response.read()
     return (content.decode())
  #Fetch error
  except urllib.error.URLError as e:
      return("Error " + str(e.code) + ":" + e.reason) 

  #PARAMETERS
  id = "{YOUR_SERVER_ID}" # e.g.: "5340033E7FBBC308BC329414A0DF3C20"
  action = "REBOOT"
  method = "SOFTWARE"

  data = json.dumps({'action':action, 'method':method})

  #REBOOT server
  print(_setStatusServer(id, data))

I have converted to the pascal code

function TWFServerSetState.ExecuteCommand(id, ip_id, Content: string): string;
var
  HTTP: TIdHTTP;
  Command: string;
  InputStream: TStringStream;
  ResponseStream: TStringStream;

  str: string;
begin
  Result := '';
  HTTP := TIdHTTP.Create();
  try
    HTTP.Request.ContentEncoding := 'UTF-8';
    HTTP.Request.CustomHeaders.AddValue('X-TOKEN', Token);
    HTTP.Request.CustomHeaders.AddValue('content-type', 'application/json');
    HTTP.Request.ContentType := 'application/json';
    Command := GetAddress + '/servers/' + id + '/status/action';

    str := '{"method": "' + Content + '", "action": "' + ip_id + '"}';
    str := TIdEncoderMIME.EncodeString(STR, IndyUTF8Encoding);
    InputStream := TStringStream.Create(str, TEncoding.UTF8);
    ResponseStream := TStringStream.Create('', TEncoding.UTF8, false);
    try
      HTTP.Put(Command, InputStream, ResponseStream);
      Result := ResponseStream.DataString;
    finally
      ResponseStream.Free;
      InputStream.Free;
    end;
  finally
    HTTP.Free;
  end;
end;

But, result of execution of Python code is OK. Execution of Delphi code returns

"HTTP/1.1 406 Not Acceptable"

Any suggestion where I made error in conversion?

Based on mjn suggestion I removed Mime encoding and changed url for test in both codes. Request from python code on the httpbin server is:

{'X-token': {token}, 'Content-type': 'application/json'}
{
  "args": {}, 
  "data": "{\"method\": \"SOFTWARE\", \"action\": \"REBOOT\"}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept-Encoding": "identity", 
    "Connection": "close", 
    "Content-Length": "42", 
    "Content-Type": "application/json", 
    "Host": "httpbin.org", 
    "User-Agent": "Python-urllib/3.4", 
    "X-Token": "token"
  }, 
  "json": {
    "action": "REBOOT", 
    "method": "SOFTWARE"
  }, 
  "origin": "24.135.167.155", 
  "url": "http://httpbin.org/put"
}

from Delphi code

{
  "args": {}, 
  "data": "{\"method\": \"SOFTWARE\", \"action\": \"REBOOT\"}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept-Encoding": "identity", 
    "Connection": "close", 
    "Content-Length": "42", 
    "Content-Type": "application/json", 
    "Host": "httpbin.org", 
    "User-Agent": "Mozilla/3.0 (compatible; Indy Library)", 
    "X-Token": "token"
  }, 
  "json": {
    "action": "REBOOT", 
    "method": "SOFTWARE"
  }, 
  "origin": "176.67.200.136", 
  "url": "http://httpbin.org/put"
}

Thanks in advance

Bojan

like image 299
bojan gavrilovic Avatar asked Jul 14 '17 10:07

bojan gavrilovic


1 Answers

Your Delphi code is NOT sending the JSON data the same way the Python code is. There are several logic and coding mistakes in your code.

The correct code should look more like this instead:

function TWFServerSetState.ExecuteCommand(const ServerID, Action, Method: string): string;
var
  HTTP: TIdHTTP;
  Url: string;
  InputStream: TStringStream;
  str: string;
begin
  Result := '';
  HTTP := TIdHTTP.Create;
  try
    HTTP.Request.CustomHeaders.AddValue('X-TOKEN', Token);
    HTTP.Request.ContentType := 'application/json';
    Url := GetAddress + '/servers/' + ServerID + '/status/action';
    str := '{"method": "' + Method + '", "action": "' + Action + '"}';
    InputStream := TStringStream.Create(str, TEncoding.UTF8);
    try
      try
        Result := HTTP.Put(Url, InputStream);
      except
        on e: EIdHTTPProtocolException do
          Result := 'Error ' + IntToStr(e.ErrorCode) + ':' + e.Message;
      end;
    finally
      InputStream.Free;
    end;
  finally
    HTTP.Free;
  end;
end;

Then you can call it like this:

var
  id, action, method: string;
begin
  id := '{YOUR_SERVER_ID}'; // e.g.: "5340033E7FBBC308BC329414A0DF3C20"
  action := 'REBOOT';
  method := 'SOFTWARE';
  ExecuteCommand(id, action, method);
end;
like image 72
Remy Lebeau Avatar answered Nov 13 '22 12:11

Remy Lebeau