2017-07-14 79 views
6

Następny kodu Pythonakonwersji Python kodu Delphi

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)) 

Mam konwertowane do kodu pascal

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; 

ale wyniku wykonania kodu Pythona jest OK. Wykonanie kodu Delphi zwraca

"HTTP/1.1 406 Not Acceptable"

Wszelkie sugestie, gdzie zrobiłem błąd w konwersji?

Na podstawie sugestii mjn usunąłem kodowanie Mime i zmieniono adres URL do testu w obu kodach. Zapytanie z kodu Pythona na serwerze httpbin jest:

{'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" 
} 

z kodu Delphi

{ 
    "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" 
} 

Dzięki z góry

Bojan

+1

Wydaje trzeba dodać Accept: nagłówek. –

+1

Zrób trochę debugowania. Porównaj dwie prośby. Jak się różnią. –

+0

@ David: Zrobiłem to i nie widziałem żadnej różnicy –

Odpowiedz

2

Kod Delphi nie wysyła danych JSON takie same sposób, w jaki jest kod Pythona. W twoim kodzie jest kilka błędów logicznych i kodowania.

Poprawny kod powinien wyglądać mniej więcej tak zamiast:

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; 

Następnie można nazwać tak:

var 
    id, action, method: string; 
begin 
    id := '{YOUR_SERVER_ID}'; // e.g.: "5340033E7FBBC308BC329414A0DF3C20" 
    action := 'REBOOT'; 
    method := 'SOFTWARE'; 
    ExecuteCommand(id, action, method); 
end; 
+0

Dzięki za odpowiedź.Napisałem nazwy parametrów w inny sposób, ponieważ ta klasa jest jedną z klas dla dzieci i wszystkie mają różne nazwy parametrów. Naprawdę jedynym problemem był HTTP.Request.CustomHeaders.AddValue ("content-type", "application/json"); HTTP.Request.ContentType: = 'application/json'; ponieważ serwer widział to jako "application/json", "application/json" i nie akceptował tego ContentType. httpbin.org/put napisał ContentType = 'application/json' tylko raz, ale naprawdę serwer tego nie widział. Inne "poprawne" były poprawne. –

+0

@bojangavrilovic dobrze, że, i byłeś base64 kodujący dane JSON, gdy kod Pythona nie, a ty ustawiałeś nagłówek 'Content-Encoding' na niepoprawną wartość. Te wszystkie dodane do bardzo źle sformułowanego żądania. –