Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Internet (https://www.clubdelphi.com/foros/forumdisplay.php?f=3)
-   -   Invocar un api rest con headers (https://www.clubdelphi.com/foros/showthread.php?t=93844)

IVAND 03-04-2019 04:09:49

Invocar un api rest con headers
 
Estimados amigos

Tengo una inquietud y es la conexion a un web service q se debe pasar un request , pero no logro hacerlo o no entiendo muy bien como configurar el componete IdHTTP1 para tal fin , aqui se ha hablado de varias formas de incovar este tema pero no logro hacerlo con estos headers


Contando con ustedes quedo a sus ordenes


URL

https://inprise.integral.ec/api/cons...=1308325354001

Nota : Estoy usando un sistema de ejemplo de nuesto amigo neptali
el error self.Fhttp.ResponseCode es -1



X-MANTISAPI-CODE eeXahKo8 -> headers

he intentado varias formas ejmplo
HeaderStr = 'X-MANTISAPI-CODE: eeXahKo8';
IdHttp1.Request.CustomHeaders.Values[HeaderStr];

sale eror IOHandler value is not valid
self.Fhttp.ResponseCode da como resultado -1

El ejemplo que utilizo es el de nuestro amigo neftali

IVAND 03-04-2019 05:03:41

creo q el problema es porque no se como enviar estos argumentos

self.Fhttp.Request.CustomHeaders.Add('key=X-MANTISAPI-CODE'+'value='+'eeXahKo8') ;

dec 03-04-2019 12:39:47

Hola a todos,

Lo siguiente parece funcionar como se espera:

Código Delphi [-]
IdHTTP1.Request.CustomHeaders.AddValue('X-MANTISAPI-CODE', 'eeXahKo8');

IVAND 05-04-2019 00:20:07

Hola Dec

Gracias por tu respuesta y disculpa pero recien puedo entrar a revisar los correos

Mira uso indy 10.2.5 y delphi 2009 , esa propiedad que me indicas no aparece en mi version solo aparecen add y no funciona con esos dos parametros :eek:.

dec 05-04-2019 11:04:26

Hola a todos,

Yo creo que uso Indy 10... pero es cierto que probé en Delphi 2007 (lo que tenía más a mano). Mira a ver si esto otro sirve, puesto que aquí parece funcionar también:

Código Delphi [-]
IdHTTP1.Request.CustomHeaders.Values['X-MANTISAPI-CODE'] := 'eeXahKo8';

IVAND 06-04-2019 02:14:58

Gracias Dev , por tu amable dedicacion ,

Mira logre consumir el servicio de esta manera como es uan pagina https

agrege esto

Código Delphi [-]
procedure TForm1.btn1Click(Sender: TObject);
var
Urls:string ;
LHandler: TIdSSLIOHandlerSocketOpenSSL;
begin
  LHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  IdHTTP1.Request.CustomHeaders.Values['X-MANTISAPI-CODE'] := 'eeXahKo8';
  IdHTTP1.IOHandler:=LHandler;
  memo1.Lines.Add(IdHTTP1.Get('https://inprise.integral.ec/api/consulta-identificacion/?identificacion=1308325354001'));
end;

Recibo ya la informacion , pero de una manera muy rara , como si fuera una pagina web que se embebe en un navegador , los datos que debe emviar son

Código PHP:

to `json`">json</a>
                        </li>
                      
                        <li>
                          <a class="
js-tooltip format-option" href="/api/consulta-identificacion/?format=api&amp;identificacion=1308325354001" rel="nofollow" title="Make a GET request on the Consulta Datos Identificacion resource with the format set to `api`">api</a>
                        </li>
                      
                    </ul>
                  </div>
                
              </fieldset>
            </form>
          

          
            <form class="
button-form" action="/api/consulta-identificacion/?identificacion=1308325354001" data-method="OPTIONS">
              <button class="
btn btn-primary js-tooltip" title="Make an OPTIONS request on the Consulta Datos Identificacion resource">OPTIONS</button>
            </form>
          

          

          
          </div>

            <div class="
content-main" role="main"  aria-label="main content">
              <div class="
page-header">
                <h1>Consulta Datos Identificacion</h1>
              </div>
              <div style="
float:left">
                
                  <p></p>
                
              </div>

              

              <div class="
request-info" style="clearboth" aria-label="request info">
                <pre class="
prettyprint"><b>GET</b> /api/consulta-identificacion/?identificacion=1308325354001</pre>
              </div>

              <div class="
response-info" aria-label="response info">
                <pre class="
prettyprint"><span class="meta nocode"><b>HTTP 200 OK</b>
<b>Allow:</b> <span class="
lit">OPTIONS, GET</span>
<b>Content-Type:</b> <span class="
lit">application/json</span>
<b>Vary:</b> <span class="
lit">Accept</span>

</span>{
    &quot;tipo_contribuyente&quot;: &quot;PERSONAS NATURALES&quot;,
    &quot;actividad_economica&quot;: &quot;VENTA AL POR MAYOR DE MATERIALES DE CONSTRUCCIÓN: PIEDRA, ARENA, GRAVA, CEMENTO, ETCÉTERA.&quot;,
    &quot;clase_contribuyente&quot;: &quot;OTROS&quot;,
    &quot;estado_contribuyente&quot;: &quot;ACTIVO&quot;,
    &quot;nombres_completos&quot;: &quot;ANCHUNDIA DELGADO JOSE RAFAEL&quot;,
    &quot;direccion&quot;: &quot;MANABI/PORTOVIEJO/12 DE MARZO/RAMOS IDUARTE S/N TERCERA Y CUARTA TRANSVERSAL&quot;,
    &quot;nombre_comercial&quot;: &quot;DEPOSITO ANCHUNDIA&quot;,
    &quot;obligado&quot;: &quot;S&quot;
}</pre>
              </div>
            </div>

            
              

              
            
          
        </div><!-- /.content -->
      </div><!-- /.container -->
    </div><!-- ./wrapper -->

    

    
      <script>
        window.drf = {
          csrfHeaderName: "
X-CSRFTOKEN",
          csrfCookieName: "
csrftoken"
        };
      </script>
      <script src="
/static/rest_framework/js/jquery-1.12.4.min.4f252523d4af.js"></script>
      <script src="
/static/rest_framework/js/ajax-form.0ea6e6052ab5.js"></script>
      <script src="
/static/rest_framework/js/csrf.753b7a1f2ee7.js"></script>
      <script src="
/static/rest_framework/js/bootstrap.min.5869c96cc8f1.js"></script>
      <script src="
/static/rest_framework/js/prettify-min.709bfcc456c6.js"></script>
      <script src="
/static/rest_framework/js/default.b846d7d305c9.js"></script>
      <script>
        $(document).ready(function() {
          $('form').ajaxForm();
        });
      </script>
    

  </body>
  
</html> 

Cuando deberia enviar en JSON , este servicio esta probado en python, sera que me falta algo mas para darle formato en los indy o sera normal asi en delphi que retorne aunq en la web de neftaly un api rest devuelve un json tal cual debe ser


Nuevamente aprecio mucha tu ayuda , un abrazo

dec 06-04-2019 10:03:40

Hola a todos,

El resultado que obtienes implica que el servidor no está recibiendo la petición HTTP adecuada, puesto que además, probando en apitester.com, el servidor retorna un JSON, tal como se espera. He querido probar con Delphi y me he encontrado con el mismo problema que tú, exactamente.

He revisado la petición HTTP que realiza apitester.com, puesto que funciona como se espera, y, después de probar a cambiar el "User Agent" (sin resultado), he visto que con el "Accept" adecuado, la petición se lleva a cabo perfectamente, es decir, algo como lo siguiente funciona bien:

Código Delphi [-]
begin
  IdHTTP1.Request.Clear();
  IdHTTP1.Request.Accept := '*/*';
  IdHTTP1.Request.CustomHeaders.Values['X-MANTISAPI-CODE'] := 'eeXahKo8';
  ShowMessage(IdHTTP1.Get('https://inprise.integral.ec/api/consulta-identificacion/?identificacion=1308325354001'));
end;

mamcx 06-04-2019 15:51:29

Cita:

IdHTTP1.Request.Accept := '*/*';
Eso es el MIME TYPE. '*/*' es demasiado amplio y puede el servidor web CAMBIAR SU RESPUESTA, si quieres usar JSON el correcto es: application/json.

Ademas, ten en cuenta la simetría con:

https://webmasters.stackexchange.com...e-http-headers

dec 06-04-2019 17:23:22

Hola a todos,

Entonces, es posible que el "Accept" por defecto que use el componente "IdHttp" no sea el adecuado, y, cambiándolo por "*/*", funciona como se espera. Si funcionase también con "application/json", en efecto, tal vez sería más adecuado usar este en lugar del otro más genérico. Yo únicamente me fijé en cómo hacía la consulta el servicio que obtenía una respuesta correcta y traté de imitar la llamada HTTP. :)

IVAND 07-04-2019 00:57:29

Efectivamente de los dos metodos funciona bien , muchas gracias a los dos , un fuerte abrazo ahora solo queda parsear el resultado

Gracias

Badillo 02-01-2024 23:02:22

Necesito su ayuda con este ejemplo
 
Estoy tratando de hacer una llamada a este API, para obtener del un JSON y así validar la información. Ajusté la función según lo que entendí del ejempo que debaten acá, pero cuando hace por conectarse emite el siguiente error:

raised exception class EIdOSSLUnderlyingCryptoError with message 'Error connecting with SSL.
error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure

El código fuente de la función es:

Código Delphi [-]
function TValidateNPIForAPI.IsValidateNPIForAPI(aNumber, aNpiType, aTaxonomy :string): boolean;
var
  xResponse: TStringStream;
  xUrl, xParams: String;
  xJsonObj: TlkJSONbase;
  xCount: Integer;
  SSLHandler: TIdSSLIOHandlerSocketOpenSSL;
begin
    Result := False;
    xUrl :=  'https://npiregistry.cms.hhs.gov/api/?version=2.1';
    xResponse := TStringStream.Create('');
    xJsonObj :=  TlkJSONbase.Create;

    if aNumber <> '' then
      xParams := xParams + '&number='+HttpEncode(aNumber);

    if aNpiType <> '' then
      xParams := xParams + '&enumeration_type='+HttpEncode(aNpiType);

    if aTaxonomy <> '' then
      xParams := xParams + '&taxonomy_description='+HttpEncode(aTaxonomy);

    try
      SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
      Fhttp := TIDHttp.Create(nil);
      Fhttp.IOHandler := SSLHandler;
      Fhttp.Request.Clear();
      Fhttp.Request.Accept := '*/*';
      Fhttp.Request.CustomHeaders.Values['X-MANTISAPI-CODE'] := 'eeXahKo8';
      Fhttp.Get(xUrl + xParams, xResponse);
      TlkJSONbase(xJsonObj) := TlkJSON.ParseText(xResponse.DataString);
      xCount := StrToInt(xJsonObj.Field['result_count'].Value);
      Result := (xCount > 0);
    finally
      xResponse.Free;
      xJsonObj.Free;
      Result := False;
    end;
end;

Como ejemplo en los parámetros pueden utilizar aNumber = '1871147520' y aNpiType = 'NPI-1'.

Gracias por su ayuda.

pablog2k 03-01-2024 09:13:10

probablemente te esté pasando que no estás enviando con TLS 1.2 ,que últimamente muchas APIS lo exigen.
Deberás usar los indy mas o menos actualizados, y con el componente TidSSLIOHandlerSocketOpenSSL decirle en sus SSLOptions que la SSLVersion es TLSv1_2

Badillo 03-01-2024 14:52:01

Cita:

Empezado por pablog2k (Mensaje 553794)
probablemente te esté pasando que no estás enviando con TLS 1.2 ,que últimamente muchas APIS lo exigen.
Deberás usar los indy mas o menos actualizados, y con el componente TidSSLIOHandlerSocketOpenSSL decirle en sus SSLOptions que la SSLVersion es TLSv1_2

Gracias, por la idea Pablog2k, probaré y comento.

Badillo 03-01-2024 14:59:57

Probé de esta otra forma y mismo error.
 
Saludos.

Probé de está otra forma, incluyendo lo que me comenta pablog2k y como resultado obtengo el mismo error:

Código Delphi [-]
function TValidateNPIForAPI.ValidateNPIForAPI(aNumber, aNpiType,
  aTaxonomy: string): boolean;
var
  AHTTP: TIdHTTP;
  SSL: TIdSSLIOHandlerSocketOpenSSL;
  xResponse: TStringStream;
  xUrl, xParams: String;
  xJsonObj: TlkJSONbase;
  xCount: Integer;
begin
  Result := False;
  xUrl :=  'https://npiregistry.cms.hhs.gov/api/?version=2.1';
  xResponse := TStringStream.Create('');
  xJsonObj :=  TlkJSONbase.Create;

  if aNumber <> '' then
    xParams := xParams + '&number='+HttpEncode(aNumber);

  if aNpiType <> '' then
    xParams := xParams + '&enumeration_type='+HttpEncode(aNpiType);

  if aTaxonomy <> '' then
    xParams := xParams + '&taxonomy_description='+HttpEncode(aTaxonomy);

  try
    AHTTP:= TIdHTTP.Create(nil);
    SSL:= TIdSSLIOHandlerSocketOpenSSL.Create(nil);

    AHTTP.IOHandler:= SSL;
    AHTTP.AllowCookies:= True;
    AHTTP.HTTPOptions:= [hoForceEncodeParams];

    AHTTP.Request.BasicAuthentication:= True;

    AHTTP.Request.Accept:= 'application/json';
    AHTTP.Request.AcceptCharSet := 'utf-8';
    AHTTP.Request.ContentType:= 'application/json';
    AHTTP.Request.UserAgent:= 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0';
    AHTTP.Request.CharSet:= 'utf-8';

    SSL.SSLOptions.Method:= sslvSSLv23;
    SSL.SSLOptions.Mode:= sslmUnassigned;
    SSL.SSLOptions.VerifyMode:= [];
    SSL.SSLOptions.VerifyDepth:= 0;
    SSL.SSLOptions.SSLVersions := [sslvTLSv1_2, sslvTLSv1_1, sslvSSLv23, sslvTLSv1];

    xParams := AHTTP.Get(xUrl + xParams);
    TlkJSONbase(xJsonObj) := TlkJSON.ParseText(xResponse.DataString);
    xCount := StrToInt(xJsonObj.Field['result_count'].Value);
    Result := (xCount > 0);
  finally
    xResponse.Free;
    xJsonObj.Free;
    SSL.Free;
    AHTTP.Free;
    Result := False;
  end;
end;

Gracias.

pablog2k 03-01-2024 15:32:25

pero tienes que forzar a que envíe por tls 1.2
cambia esto

SSL.SSLOptions.Method:= sslvTLSv1_2;
SSL.SSLOptions.Mode:= sslmUnassigned; (yo suelo poner sslmBoth y me funciona)
SSL.SSLOptions.VerifyMode:= [];
SSL.SSLOptions.VerifyDepth:= 0;
SSL.SSLOptions.SSLVersions := [sslvTLSv1_2];

Badillo 03-01-2024 18:00:48

Comparto una vía de solución.
 
Saludos,

Compartiré la vía con la que solucioné el problema de la llamada a la API.

Código Delphi [-]
unit MdNPI;

interface

uses
  System.SysUtils, System.Variants, System.Classes, System.UITypes,
  System.AnsiStrings, System.IOUtils, uLkJSON;

type

  TNPI = class(TObject)
  private
    { Private declarations }
    FBaseURL: string;
    FParams: string;
    FResponse: string;
    FResponseJson: TlkJSONbase;

    function CallAPI(aUrl: string): string;
  public
    { Public declarations }
    property BaseURL: string read FBaseURL write FBaseURL;
    property ResponseJson: TlkJSONbase read FResponseJson;

    constructor Create;
    function ValidateNPIForAPI(aNumber, aNpiType, aTaxonomy :string): boolean;
  end;

implementation

uses
  System.Character, Vcl.AxCtrls, Winapi.ActiveX, WinHttp_TLB, IdURI;

{ TNPI }

constructor TNPI.Create;
begin
  FBaseURL :=  'https://npiregistry.cms.hhs.gov/api/?version=2.1';
  FParams := '';
  FResponse := '';
  FResponseJson := TlkJSONbase.Create;
end;

function TNPI.CallAPI(aUrl: string): string;
var
  Http: IWinHttpRequest;
  HttpStringStream: TStringStream;
  HttpStream: IStream;
  OleStream: TOleStream;
begin
  Http := CoWinHttpRequest.Create;
  Http.Open('GET', aUrl, False);
  Http.Send(EmptyParam);

  if Http.Status = 200 then
  begin
    HttpStream := IUnknown(Http.ResponseStream) as IStream;
    OleStream  := TOleStream.Create(HttpStream);
    try
      HttpStringStream := TStringStream.Create('');
      try
        OleStream.Position:= 0;
        HttpStringStream.CopyFrom(OleStream, OleStream.Size);

        Result := HttpStringStream.DataString;
      finally
        HttpStringStream.Free;
      end;
    finally
      OleStream.Free;
    end;
  end;
end;

function TNPI.ValidateNPIForAPI(aNumber, aNpiType,
  aTaxonomy: string): boolean;
var
  xCount: Integer;
  xUrl: string;
begin
  try
    xCount := 0;

    if aNumber <> '' then
      FParams := FParams + '&number='+aNumber;

    if aNpiType <> '' then
      FParams := FParams + '&enumeration_type='+aNpiType;

    if aTaxonomy <> '' then
      FParams := FParams + '&taxonomy_description='+aTaxonomy;

    xUrl := TIdURI.URLEncode(FBaseURL + FParams);
    FResponse := CallAPI(xUrl);
    TlkJSONbase(FResponseJson) := TlkJSON.ParseText(FResponse);

    xCount := StrToInt(FResponseJson.Field['result_count'].Value);
  except
    on e: Exception do
      begin
        xCount := 0;
      end;
  end;

  Result := (xCount > 0);

end;

end.

Gracias.

Greender 09-04-2024 13:15:03

Para invocar un API REST con headers, primero debes asegurarte de tener la URL del API y los headers necesarios


La franja horaria es GMT +2. Ahora son las 01:39:38.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi