【问题标题】:Getting 400 response when using Delphi to get Microsoft Translation使用 Delphi 获取 Microsoft 翻译时得到 400 响应
【发布时间】:2015-08-19 21:14:24
【问题描述】:

我已经在 Azure 上注册了我的应用程序,收到了一个秘密,并在我的 Delphi 2010 中使用 TIdHTTP 成功获得了访问令牌:

paramsList := TStringList.Create;
paramsList.Add('grant_type=client_credentials');
paramsList.Add('client_id=<ClientID>');
paramsList.Add('client_secret=<ClientSecret>');
paramsList.Add('scope=http://api.microsofttranslator.com');
try
  Result := idHTTP.Post(uri, lParamList);
finally
  FreeAndNill(idHTTP);
  FreeAndNill(paramsList);
end;

然后我使用复制提取响应的标记部分。现在,当我尝试获取实际翻译时,我收到了错误请求错误。这是我尝试的方法:

idHTTP.Request.CustomHeaders.AddValue('Authorization', headers);
try
   stringResult := idHTT.Get('http://api.microsofttranslator.com/v2/Http.svc/Translate?text=Gracias%20a%20l%20vida&from=es&to=en');
finally
   FreeAndNil(idHTTP);
end;

我也未能通过帖子获得回复:

paramList := TStiringList.Create;
paramList.Add('Authorization= Bearer ' + Token);
try
  idHTTP.Post(uri, paramList);
finally
...

还是一样的响应 - 400,有什么想法吗?

【问题讨论】:

  • 您正在添加自定义 Authorization 标头,但您没有显示创建标头值的代码,您确定您做得正确吗?在你的第二个例子中(顺便说一句,Authorization 是 HTTP 标头而不是提交的表单字段),你有 'Authorization= Bearer ' + Token 应该是 'Authorization=Bearer ' + Token 而不是,IOW 你在 @ 前面有一个额外的空间987654328@。在为headers 赋值时,您是否在CustomHeaders 示例中犯了同样的错误?
  • 嗨,Ramy,感谢您回复我。你说第二个例子不行,因为它不是提交的表单域,那应该怎么提交呢?我从对我有用的 PHP 和 C# 示例中复制了键 + 值,上面写着“Authorization: Bearer http...”
  • 就像我说的,Authorization 是一个 HTTP 标头。您的 CustomHeaders 示例处理该场景,不要将其放在已发布的 TStringList 中。但是您没有回答我的问题 - 您的 headers 变量是否包含与您的 TStringList 数据相同的错误空格?
  • 您还应该将TIdHTTP.Request.BasicAuthentication 属性设置为False,以确保TIdHTTP 不会尝试发送自己的Authorization 标头。
  • 你好@RemyLebeau,谢谢。标头值的开头没有空格。但是,我发送它是因为我收到了它,http 解码,其中包含所有花哨的 %2f。那样行吗?至于BasicAuthentication,谢谢,默认设置为false。

标签: delphi azure delphi-2010 bad-request microsoft-translator


【解决方案1】:

首先,事实:在 Microsoft Translator 请求访问令牌时,您使用 Post,当使用访问令牌访问 API 时,您使用 Get(感谢 @RemyLebeau) .现在是代码。上面用于接收访问令牌的代码有效。所以获取翻译的代码也很简单:

lHTTP.Request.CustomHeaders.FoldLines := false; // avoid split by white space
lHTTP.Request.CustomHeaders.AddValue('Authorization', 'Bearer ' + AuthKey);
myStream =  TStringStream.Create;
try
  lHTTP.Get(uri, stream);
  stream.Position := 0;
  Result := stream.ReadString(stream.size);
finally
  FreeAndNil(lHTTP);
  FreeAndNil(stream);
end;

【讨论】:

    【解决方案2】:

    这是一个工作示例 签出://http://oauthdevconsole.cloudapp.net/PartialOAuth

    unit MSTranslationv2;
    
    interface
    
    uses
      Classes, SysUtils,
      IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
      IdHTTP, IdIOHandler, IdIOHandlerSocket, IdIOHandlerStack, IdSSL,
      IdSSLOpenSSL;
    
    type
        TMSTranslator = class(TComponent)
        IdHTTP: TIdHTTP;
        IdSSLIOHandlerSocketOpenSSL: TIdSSLIOHandlerSocketOpenSSL;
      private
        fSourceLanguage: string;
        fClientID: string;
        fClientSecret: string;
        fTargetLanguage: string;
        AuthKey : string;
    
        { Private declarations }
        function GetAuthorizationKey: string;
        procedure SetClientID(const Value: string);
        procedure SetClientSecret(const Value: string);
      public
        { Public declarations }
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
    
        function Translate(Text: string): string;
    
        property ClientID: string read fClientID write SetClientID;
        property ClientSecret: string read fClientSecret write SetClientSecret;
        property SourceLanguage: string read fSourceLanguage write fSourceLanguage;
        property TargetLanguage: string read fTargetLanguage write fTargetLanguage;
      end;
    
    //http://oauthdevconsole.cloudapp.net/PartialOAuth
    implementation
    
    uses
      HTTPApp, DBXJSON, ComObj, Variants;
    
    { TMSTranslator }
    
    constructor TMSTranslator.Create(AOwner: TComponent);
    begin
      inherited;
    
      IdHTTP := TIdHTTP.Create(nil);
      IdSSLIOHandlerSocketOpenSSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
    
      IdHTTP.Request.ContentType := 'application/x-www-form-urlencoded';
      idHTTP.HandleRedirects := True;
      IdHTTP.Request.CustomHeaders.FoldLines := false; // avoid split by white space
      IdHTTP.IOHandler := IdSSLIOHandlerSocketOpenSSL;
    end;
    
    destructor TMSTranslator.Destroy;
    begin
      IdHTTP.Free;
      IdSSLIOHandlerSocketOpenSSL.Free;
    
      inherited;
    end;
    
    procedure TMSTranslator.SetClientID(const Value: string);
    begin
      if fClientID <> Value then
        AuthKey:= '';
    
      fClientID := Value;
    end;
    
    procedure TMSTranslator.SetClientSecret(const Value: string);
    begin
      if fClientSecret <> Value then
        AuthKey := '';
    
      fClientSecret := Value;
    end;
    
    function TMSTranslator.GetAuthorizationKey: string;
    var
      StringList : TStringList;
      StringStream: TStringStream;
      LJsonObj : TJSONObject;
      LJsonValue : TJSONValue;
    begin
      if AuthKey = '' then begin
    
        if fClientID = '' then
          raise Exception.Create('Property fClientID needs to be assigned.');
    
        if fClientSecret = '' then
          raise Exception.Create('Property fClientSecret needs to be assigned.');
    
        StringList := TStringList.Create;
        StringStream := TStringStream.Create('', TEncoding.UTF8);
        try
          StringList.Add('grant_type=client_credentials');
          StringList.Add('&client_id='+ HTTPEncode(fClientID) );
          StringList.Add('&client_secret='+ HTTPEncode(fClientSecret));
          StringList.Add('&scope='+ HTTPEncode('http://api.microsofttranslator.com'));
          StringStream.WriteString(StringList.text);
    
          IdHTTP.Request.CustomHeaders.Clear;
          result := idHTTP.Post('https://datamarket.accesscontrol.windows.net/v2/OAuth2-13', StringStream);
    
          LJsonObj := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(result),0) as TJSONObject;
          try
            LJsonValue :=LJsonObj.Get('access_token').JsonValue;
            result := LJsonValue.Value;
          finally
            LJsonObj.Free;
          end;
    
        finally
          StringList.free;
          StringStream.free;
        end;
      end else
        result := AuthKey;
    end;
    
    function TMSTranslator.Translate(Text: string): string;
    var
      XmlDoc: OleVariant;
      Node: OleVariant;
      StringStream : TStringStream;
      Url: string;
    const
      Msxml2_DOMDocument = 'Msxml2.DOMDocument.6.0';
    begin
      AuthKey := GetAuthorizationKey;
    
      if Text <> '' then begin
        if fSourceLanguage = '' then
          raise Exception.Create('Property fSourceLanguage needs to be assigned.');
    
        if fTargetLanguage = '' then
          raise Exception.Create('Property fTargetLanguage needs to be assigned.');
    
        Url := format('http://api.microsofttranslator.com/v2/Http.svc/Translate?text=%s&from=%s&to=%s', [HTTPEncode(Text), fSourceLanguage, fTargetLanguage]);
    
        IdHTTP.Request.CustomHeaders.Clear;
        IdHTTP.Request.CustomHeaders.AddValue('Authorization', 'Bearer ' + AuthKey);
        StringStream := TStringStream.Create('', TEncoding.UTF8);
        try
          IdHTTP.Get(Url, StringStream);
          StringStream.Position := 0;
          Result := StringStream.ReadString(StringStream.size);
    
          XmlDoc:= CreateOleObject(Msxml2_DOMDocument);
          try
            XmlDoc.Async := False;
            XmlDoc.LoadXML(Result);
            if (XmlDoc.parseError.errorCode <> 0) then
              raise Exception.CreateFmt('Error in Xml data: %s',[XmlDoc.parseError]);
            Node:= XmlDoc.documentElement;
            if not VarIsClear(Node) then begin
              Result:= XmlDoc.Text;
              if pos('TranslateApiExceptionMethod', result) >0 then
                Result := '';
            end;
          finally
            XmlDoc := Unassigned;
          end;
      end else
        result := '';
    end;
    
    ====================
    
    var
      MSTranslator: TMSTranslator;
    begin
      MSTranslator := TMSTranslator.Create(nil);
      try
        MSTranslator.ClientID := 'YourClientIDHere';
        MSTranslator.ClientSecret := 'YourClientSecretHere';
        MSTranslator.SourceLanguage := 'en';
        MSTranslator.TargetLanguage := 'th';
        ShowMessage(MSTranslator.Translate('Hello'));
      finally
        MSTranslator.free;
      end;
    end;
    

    【讨论】:

      猜你喜欢
      • 2018-01-02
      • 2019-07-28
      • 2021-12-19
      • 2010-11-16
      • 1970-01-01
      • 1970-01-01
      • 2017-10-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多