6

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

15
  • 1
    It seems you need to add an Accept: header. Commented Jul 14, 2017 at 10:21
  • 2
    Do some debugging. Compare the two requests. How do they differ. Commented Jul 14, 2017 at 10:50
  • 1
    That seems a little implausible don't you think Commented Jul 14, 2017 at 10:57
  • 2
    Capture the real HTTP requests and responses with a tool like Fiddler2 and compare them. Commented Jul 14, 2017 at 15:37
  • 2
    Think about it. If the request is identical, the server will respond identically. That's how computers work. I posit that you haven't checked the request and don't know how to debug this. Commented Jul 14, 2017 at 17:18

1 Answer 1

3

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;
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your answer. I have written the parameter names differently, because this class is one of the children's classes, and they all have different parameter names. Really only problem was in HTTP.Request.CustomHeaders.AddValue('content-type', 'application/json'); HTTP.Request.ContentType := 'application/json'; because server saw this like 'application/json', 'application/json' and wasn't to accept this ContentType. httpbin.org/put wrote ContentType = 'application/json' only once, but the really server did not see it that way. Other was "addopted" correct.
@bojangavrilovic well, that, and you were base64 encoding the JSON data when the Python code didn't, and you were setting the Content-Encoding header to an invalid value. Those all added up to a very malformed request.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.