【问题标题】:converting Python to Delphi code将 Python 转换为 Delphi 代码
【发布时间】:2017-07-14 10:14:44
【问题描述】:

下一个python代码

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

我已经转换成帕斯卡码

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;

但是,Python代码的执行结果是OK的。 Delphi代码执行返回

“HTTP/1.1 406 不可接受”

有什么建议我在转换中出错了吗?

根据 mjn 的建议,我删除了 Mime 编码并更改了两个代码中的测试 URL。 httpbin服务器上python代码的请求是:

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

来自 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"
}

提前致谢

博扬

【问题讨论】:

  • 看来您需要添加一个 Accept: 标头。
  • 做一些调试。比较两个请求。它们有何不同。
  • 你不觉得这有点难以置信
  • 使用 Fiddler2 之类的工具捕获真实的 HTTP 请求和响应并进行比较。
  • 想想吧。如果请求相同,则服务器将作出相同的响应。计算机就是这样工作的。我假设您没有检查请求并且不知道如何调试它。

标签: python http delphi indy


【解决方案1】:

您的 Delphi 代码发送 JSON 数据的方式与 Python 代码不同。您的代码中有几个逻辑和编码错误。

正确的代码应该看起来更像这样:

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;

那么你可以这样称呼它:

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

【讨论】:

  • 感谢您的回答。我把参数名写的不一样,因为这个类是孩子的类之一,它们都有不同的参数名。真正唯一的问题在于 HTTP.Request.CustomHeaders.AddValue('content-type', 'application/json'); HTTP.Request.ContentType := 'application/json';因为服务器看到这个像'application/json','application/json'并且不接受这个ContentType。 httpbin.org/put 只写了一次 ContentType = 'application/json' ,但真正的服务器并没有这样看。其他被“采纳”是正确的。
  • @bojangavrilovic 好吧,当 Python 代码没有对 JSON 数据进行 base64 编码时,您将 Content-Encoding 标头设置为无效值。这些加起来就是一个非常畸形的请求。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-08
  • 2015-11-27
  • 2016-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多