Delphi - Google Firebase - HTTP

2019-09-20 13:48发布

问题:

I'm trying to send a POST request at Firebase via HTTP, either in code or with the REST Debugger, but it returns an error:

HTTP/1.1 401 The request was missing an Authentification Key (FCM Token). Please, refer to section "Authentification" of the FCM documentation, at https=//firebase.google.com/docs

Using the Postman extension from Chrome, it works.

This is the code:

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  IdHTTP, IdIOHandler, IdIOHandlerStream,
  IdIOHandlerSocket, IdIOHandlerStack, IdSSL, IdSSLOpenSSL, IdSSLOpenSSLHeaders_Static,
  FMX.Controls.Presentation, FMX.StdCtrls, FMX.ScrollBox, FMX.Memo,
  IdGlobal, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
  IdServerIOHandler, IdCoderMIME;
begin
  try
    IdIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
    IdIOHandler.ReadTimeout := IdTimeoutInfinite;
    IdIOHandler.ConnectTimeout := IdTimeoutInfinite;
    IdHTTP := TIdHTTP.Create(nil);
    try
      idHttp.Request.Clear;
      idHttp.Request.CustomHeaders.Clear;
      idHttp.Request.ContentType := 'application/json';
      idhttp.Request.Charset := 'UTF-8';
      IdHTTP.IOHandler := IdIOHandler;
      IdHTTP.ReadTimeout := IdTimeoutInfinite;
      IdHTTP.Request.Connection := 'Keep-Alive';
      IdIOHandler.SSLOptions.Method := sslvSSLv23;
      IdHTTP.Request.Method := 'POST';
      IdHTTP.Request.CustomHeaders.Values['Authorization:key'] := 'AAAAYsnMbsY:APA91bEjYZK-xxxxxxx......';
      jsonString := '{"to" : "APA91bFJSdGW_yrX7p_TNKZ4k0OpdXTQM6xdd7BUsslk6zSvZlBmoAnfvyX-nBm4DYY-xxxxx......",' +
                    '"data" : {' +
                    '"Nick" : "Teste de Push",' +
                    '"body" : "Corpo do push",' +
                    '"Room" : "Apenas um teste"' +
                    '},}';
      JsonToSend := TStringStream.Create(jsonString);
      try
        response := IdHTTP.Post('https://fcm.googleapis.com/fcm/send', JsonToSend);
        response := response.Replace(Char(#10), '');
      except
        on E:EIdHTTPProtocolException do
        memo1.Lines.Insert(0, e.ErrorMessage);
      end;
      memo1.Lines.Insert(0, response);
    finally
      IdHTTP.Free;
    end;
  finally
    IdIOHandler.Free;
  end;
end;

回答1:

Your Delphi code is not assigning the Authentication request header correctly. You need to change this:

IdHTTP.Request.CustomHeaders.Values['Authorization:key'] := 'AAAAYsnMbsY:APA91bEjYZK-xxxxxxx......';

To this instead:

IdHTTP.Request.CustomHeaders.Values['Authorization'] := 'key=AAAAYsnMbsY:APA91bEjYZK-xxxxxxx......';

You should set the IdHTTP.Request.BasicAuthentication property to false as well.

Aside from that, since you are setting the Request.Charset property to UTF-8, you should construct the TStringStream to match:

JsonToSend := TStringStream.Create(jsonString, TEncoding.UTF8);

With that said, try the following code:

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  FMX.Controls.Presentation, FMX.StdCtrls, FMX.ScrollBox, FMX.Memo,
  IdGlobal, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
  IdHTTP, IdIOHandler, IdIOHandlerSocket, IdIOHandlerStack, IdSSL, IdSSLOpenSSL
  {$IFDEF IOS}
  , IdSSLOpenSSLHeaders_Static
  {$ENDIF}
  ;

...

begin
  IdHTTP := TIdHTTP.Create(nil);
  try
    IdIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP);
    IdIOHandler.SSLOptions.Method := sslvSSLv23;
    IdHTTP.IOHandler := IdIOHandler;

    IdHTTP.Request.ContentType := 'application/json';
    IdHTTP.Request.Charset := 'UTF-8';
    IdHTTP.Request.CustomHeaders.Values['Authorization'] := 'key=AAAAYsnMbsY:APA91bEjYZK-xxxxxxx......';

    jsonString := '{"to" : "APA91bFJSdGW_yrX7p_TNKZ4k0OpdXTQM6xdd7BUsslk6zSvZlBmoAnfvyX-nBm4DYY-xxxxx......",' +
                   '"data" : {' +
                   '"Nick" : "Teste de Push",' +
                   '"body" : "Corpo do push",' +
                   '"Room" : "Apenas um teste"' +
                   '},}';
    JsonToSend := TStringStream.Create(jsonString, TEncoding.UTF8);
    try
      response := IdHTTP.Post('https://fcm.googleapis.com/fcm/send', JsonToSend);
      response := response.Replace(#10, '');
    except
      on E: EIdHTTPProtocolException do
        response := e.ErrorMessage;
    end;
    Memo1.Lines.Insert(0, response);
  finally
    IdHTTP.Free;
  end;
end;