Request post

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
hassur
Üye
Mesajlar: 31
Kayıt: 27 Şub 2015 10:17

Request post

Mesaj gönderen hassur »

Arkadaşlar merhaba. Aşağıdaki kod ile http post işlemi yapılıyor. Peki bunu delphide nasıl yapabiliriz.

public string getAccessToken(string url, string userName, string password, string firmNr)
{
try
{
HttpWebRequest req = WebRequest.Create(new Uri(url)) as HttpWebRequest;
req.Method = "POST";
req.ContentType = "application/json";
req.Accept = "application/json";
req.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(clientId + ":" + clientSecret)));
byte[] formData = UTF8Encoding.UTF8.GetBytes("grant_type=password"
+ "&username=" + userName
+ "&firmno=" + firmNr
+ "&password=" + password);
req.ContentLength = formData.Length;
using (Stream post = req.GetRequestStream())
{
post.Write(formData, 0, formData.Length);
}
string result = null;
using (HttpWebResponse resp = req.GetResponse() as HttpWebResponse)
{
StreamReader reader = new StreamReader(resp.GetResponseStream());
result = reader.ReadToEnd();
}
dynamic j = JsonConvert.DeserializeObject(result);
accessToken = j.access_token;
}
catch (Exception){}

return accessToken;
}
ertank
Kıdemli Üye
Mesajlar: 1650
Kayıt: 12 Eyl 2015 12:45

Re: Request post

Mesaj gönderen ertank »

Merhaba,

Kullandığınız Delphi sürümünü bildirmemişsiniz. Aşağıdaki ve linklerdeki örnekler Delphi 10.1 Update 2 ve Indy sürüm 10 için verilmiştir.

Gönderdiğiniz örnek bir REST Web Servis üzerinden Json formatında bilgi iletişimi yapıyor. REST Web Servisleri parametreleri farklı şekillerde talep edebiliyor. Sizin kullandığınız Custom Header ve Byte değerleri parametre kabul ediyor.

Bu işlemi sonucuna erdirebilmeniz için öncelikle Web Servis ile ilgili gelen cevabın Json yapısını bilmeniz gerekli. Her ne kadar giden cevap bilgileri kod içinden öğrenilebilir olsa da gelen cevap formatı hakkında bir bilgi yok.

İşlemin nasıl yapılacağına dair fikir verebilecek küçük bir örnek aşağıdaki linkte mevcut.
viewtopic.php?f=2&t=36460#p196681

Bu cevap içindeki 2 numaralı madde sizin yapmak istediğiniz işlemi tarif etmeye çalışıyor. Ancak sizin işleminiz biraz daha detaylı. Örnek üzerine ek olarak sizin sizin "Custom Header" eklemeniz ve parametre bilgisini istenilen şekilde oluşturmanız gerekiyor.

Kod: Tümünü seç

uses
  Soap.EncdDecd,       // EncodeBase64()
  System.NetEncoding,  // EncodeBase64 "inline" olabilmesi için
  IdBaseComponent,     // TIdHttp bileşeni
  IdComponent,         // TIdHttp bileşeni
  IdTCPConnection,     // TIdHttp bileşeni
  IdTCPClient,         // TIdHttp bileşeni
  IdHTTP,              // TIdHttp bileşeni
  IdMultipartFormData; // TIdMultipartFormData bileşeni

procedure TForm1.Button1Click(Sender: TObject);
var
  // Kod içinde düzenlenmesi gerekli
  ClientId, ClientSecret, UserName, FirmNo, Password: string;

  // prosedür içinde kullanılan "local" değişken/bileşenler
  TempString, HeaderStr: string;
  Response: string;
  FormData: TIdMultiPartFormDataStream;
  Http: TIdHTTP;
  Bytes: TBytes;
begin
  // Aşağıdaki değişkenlerin değerleri doğru şekilde doldurulmalı
  ClientId     := 'id';
  ClientSecret := 'secret';
  UserName     := 'username';
  Password     := 'password';
  FirmNo       := 'firmno';

  // Custom Header bilgisi hazırlanıyor.
  TempString := ClientId + ':' + ClientSecret;
  Bytes := TEncoding.UTF8.GetBytes(TempString);
  HeaderStr := 'Basic ' + string(EncodeBase64(Pointer(Bytes), Length(Bytes)));

  // Parametre olarak gönderilecek FormData bilgisi hazırlanıyor.
  FormData := TIdMultiPartFormDataStream.Create();
  try
    FormData.AddFormField('grant_type','password');
    FormData.AddFormField('username', UserName);
    FormData.AddFormField('firmno', FirmNo);
    FormData.AddFormField('password', Password);

    // POST işlemi ile bilgi talep ediliyor
    Screen.Cursor := crHourGlass;
    Http := TIdHTTP.Create(nil);
    try
      Http.Request.ContentType := 'application/json';
      Http.Request.CharSet     := 'utf-8';
      // Uzun bir header 76 karakterde bir yeni satır karakteri ile bölünmesin
      Http.Request.CustomHeaders.UnfoldLines := True;
      Http.Request.CustomHeaders.Values['Authorization'] := HeaderStr;
      try
        // Sorgulama yapan bileşen, aşağıdaki url doğru şekilde düzenlenmeli
        Response := Http.Post('url', FormData);
      except
        on E: Exception do
        begin
          ShowMessage('*** İletişim hatası: ' + E.Message);
        end;
      end;
    finally
      Http.Free();
    end;
  finally
    FormData.Free();
  end;


  // Bu noktada Response değişkeni içinde yüksek ihtimalle bir Json bilgisi olacak
  // Bu Json bilgisinin kullanılabilmesi için de-serialize edilmesi gerekecek
end;
Bir sonraki adım olan gelen bilgilerin kullanılması noktasında Json De-Serialization yapmanız gerekecek. Şahsen Json Serialization/Deserialization işlemleri için mORMot projesinin kütüphanelerini tercih ediyorum. Oldukça performanslı çalışıyorlar. Ancak dış kütüphane kullanabilmek mümkün olsa bile zaman alan bir öğrenme süreci var.
https://synopse.info/fossil/wiki/Synopse+OpenSource

Yukarıdaki örnek düz bir json ise Respose değişkenini mORMot kütüphanesi ile de-serialize etmek için:

Kod: Tümünü seç

  TResult = packed record
    Response: Boolean;
  end;

uses
  SynCommons;
  
// DE-SERIALIZATION EXAMPLE
var
  JsonString: string;
  Result: TResult;
begin
  JsonString := // Gelen Json cevabı
  if RecordLoadJSON(Result, RawUTF8(JsonString), TypeInfo(TResult)) then
  begin
    ShowMessage(BoolToStr(Result.Response, True));
  end
  else
  begin
    ShowMessage('Json çözümlenemedi');
    Exit();
  end;
end;
Gelen json bilgisi çok boyutlu (dynamic array) ise bunu biraz daha farklı şekilde yapmak gerekir:

Kod: Tümünü seç

  TResult = packed record
    Response: Boolean;
  end;
  TResults: TArray<TResult>;

uses
  SynCommons;
  
// ARRAY DE-SERIALIZATION EXAMPLE
var
  JsonString: string;
  Results: TResults;
begin
  JsonString := // Gelen Json cevabı
  DynArrayLoadJSON(Results, Pointer(JsonString), TypeInfo(TResults)) then
  begin
    if High(Results) > 0 then
    begin
      for i := 0 to High(Results) do
        ShowMessage(i.ToString() + ':' + BoolToStr(Results[i].Response, True));
    end;
  end
  else
  begin
    ShowMessage('Json çözümlenemedi');
    Exit();
  end;
end;
hassur
Üye
Mesajlar: 31
Kayıt: 27 Şub 2015 10:17

Re: Request post

Mesaj gönderen hassur »

Merhaba üstad çok teşekkür ederim. Ancak daha önceki denemelerimde de hep aynı hata dönmekte oysa c# da değer dönüyor. Bu post işlem aslında bir acces token alma.

Resim
hassur
Üye
Mesajlar: 31
Kayıt: 27 Şub 2015 10:17

Re: Request post

Mesaj gönderen hassur »

Bu arada delphi xe10.1 upd2 kullanıyorum.
ertank
Kıdemli Üye
Mesajlar: 1650
Kayıt: 12 Eyl 2015 12:45

Re: Request post

Mesaj gönderen ertank »

Hata mesajından anladığım url ile ilgili bir sorununuz olduğu yönünde. Url bilgisini paylaşmadığınız için test ederek kod gönderme şansım olmadı tabi.
hassur
Üye
Mesajlar: 31
Kayıt: 27 Şub 2015 10:17

Re: Request post

Mesaj gönderen hassur »

url local de çalışan bir servis olduğu için muhtemelen sizin test etmeniz biraz zor olcak. aynı url ile c# tarafındaki koddan acces token dönüyor.
ertank
Kıdemli Üye
Mesajlar: 1650
Kayıt: 12 Eyl 2015 12:45

Re: Request post

Mesaj gönderen ertank »

Bu durumda biraz deneme yanılma yapmak gerekecek.

Test Kodu:

Kod: Tümünü seç

procedure TForm1.Button1Click(Sender: TObject);
var
  // Kod içinde düzenlenmesi gerekli
  ClientId, ClientSecret, UserName, FirmNo, Password: string;

  // prosedür içinde kullanılan "local" değişken/bileşenler
  TempString: string;
  HeaderStr: string;
  Response: string;
  FormData: TStringStream;
  Http: TIdHTTP;
  HeaderUtf8: RawByteString;
begin
  // Aşağıdaki değişkenle doğru şekilde doldurulmalı
  ClientId     := 'id';
  ClientSecret := 'secret';
  UserName     := 'username';
  Password     := 'password';
  FirmNo       := 'firmno';

  // Custom Header bilgisi hazırlanıyor.
  HeaderUtf8 := Utf8Encode(ClientId + ':' + ClientSecret);
  HeaderStr := 'Basic ' + string(EncodeBase64(Pointer(HeaderUtf8), Length(HeaderUtf8)));

  // Parametre olarak gönderilecek FormData bilgisi hazırlanıyor.
  TempString := 'grant_type=password';
  TempString := TempString + '&username=' + UserName;
  TempString := TempString + '&firmno='   + FirmNo;
  TempString := TempString + '&password=' + Password;
  FormData := TStringStream.Create(TempString, TEncoding.UTF8);
  try
    // POST işlemi ile bilgi talep ediliyor
    Screen.Cursor := crHourGlass;
    Http := TIdHTTP.Create(nil);
    try
      Http.Request.ContentType := 'application/json';
      Http.Request.Accept      := 'application/json';
      Http.Request.CharSet     := 'utf-8';
      // Uzun bir header 76 karakterde bir yeni satır karakteri ile bölünmesin
      Http.Request.CustomHeaders.UnfoldLines := True;
      Http.Request.CustomHeaders.Values['Authorization'] := HeaderStr;
      Http.Request.ContentLength := FormData.Size;
      Http.ConnectTimeout := 5000; // 5 saniye oldukça yeterli olması gerekli.
      try
        // Sorgulama yapan bileşen
        Response := Http.Post('http://localhost', FormData);
      except
        on E: Exception do
        begin
          ShowMessage('*** İletişim hatası: ' + E.Message);
          Screen.Cursor := crDefault;
        end;
      end;
    finally
      Http.Free();
    end;
  finally
    FormData.Free();
  end;


  // Bu noktada elinizde yüksek ihtimalle bir Json bilgisi olacak
  // Bu Json bilgisinin kullanılabilmesi için de-serialize edilmesi gerekecek
  Memo1.Text := Response;
end;
hassur
Üye
Mesajlar: 31
Kayıt: 27 Şub 2015 10:17

Re: Request post

Mesaj gönderen hassur »

parametreyi aşağıdaki şekilde gönderince çalıştı. Teşekkürler

var
IdHTTP: TIdHTTP;
RBody: TStringstream;
begin
IdHTTP := TIdHTTP.Create();
RBody := TStringstream.Create('grant_type=password&username=LOGO&firmno=317&password=');
//
ertank
Kıdemli Üye
Mesajlar: 1650
Kayıt: 12 Eyl 2015 12:45

Re: Request post

Mesaj gönderen ertank »

Parametre sanırım body kısmına yazılıyor.

Kod: Tümünü seç

Http.Request.Charset := 'utf-8';
satırına istinaden unicode verilen bilgiler otomatik utf-8'e dönüştürülüyor olabilir. Türkçe karakterler ile test mümkün ise denemenizde fayda var. İleride sorun yaşamaktansa şimdiden çözüm aramak daha doğru olacaktır.

Son olarak, çalışan kod bloğunun tamamını kullanıcı ve şifre bilgisi gizli şekilde paylaşabilir misiniz?
hassur
Üye
Mesajlar: 31
Kayıt: 27 Şub 2015 10:17

Re: Request post

Mesaj gönderen hassur »

çalışan kod aşağıdaki gibidir.

Kod: Tümünü seç

  var
  IdHTTP: TIdHTTP;
  RBody: TStringstream;
  begin
     IdHTTP := TIdHTTP.Create();
     RBody := TStringstream.Create('grant_type=password&username=LOGO&firmno=317&password=');
     IdHTTP.Request.CustomHeaders.UnfoldLines := True;
     IdHTTP.Request.Accept := 'application/json';
      IdHTTP.Request.ContentType := 'application/json';
      IdHTTP.Request.ContentEncoding := 'utf-8';
      IdHTTP.Request.BasicAuthentication := True;
      IdHTTP.Request.ContentLength:=54;
      IdHTTP.Request.Host:='10.12.0.9:32001';
     IdHTTP.Request.CustomHeaders.Add('Authorization: Basic 12334.....9');
      memo1.Text := IdHTTP.Post('http://10.12.0.9:32001/api/v1/token' , RBody);
epikbalad
Üye
Mesajlar: 51
Kayıt: 01 Nis 2014 04:32

Re: Request post

Mesaj gönderen epikbalad »

Arkadaşlar Merhaba,

Yukarıda anlatılanlar ışığında , token alma işlemi yapabiliyorum, buraya kadar çok güzel anlatım olmuş.
Merak ettiğim, token alma işlemiyle birlikte, OUTH2 sınıfında işlem nasıl yapabiliriz.

10.2 tokyo de, restdebugger kullanıyorum.

Netsis tarafında işlemler tümüyle C# tarafında yürüyor.
Ben UniGui tarafında yazılım yaparak, Webservis C# xml oluşturarak, bilgi gönderimi POST işlemlerimi yapıyorum.
Tamamen Delphi UniGui tarafında işlem yaparak zaman tasarrufu sağlamak çabam.

Yardımcı olurmusunuz !
ertank
Kıdemli Üye
Mesajlar: 1650
Kayıt: 12 Eyl 2015 12:45

Re: Request post

Mesaj gönderen ertank »

Merhaba,

Eğer bahsettiğiniz OAuth2 ise ticari kullanımı ücretsiz olan aşağıdaki kodu deneyebilirsiniz.
https://github.com/stievie/POAuth2

Ayrıca Embarcadero'nun kendi tarafından hazırlanmış bilgilendirme mevcut:
video: https://www.youtube.com/watch?v=EuEovgmVCUs
dosyalar: http://cc.embarcadero.com/Item/30113
ek kaynaklar:
1) http://docwiki.embarcadero.com/CodeExam ... emo_Sample (uygulamada Google (task) ile ilgili verilen örnek OAuth2 örneğidir)
2) https://community.embarcadero.com/blogs ... n-oauth2-0

Son olarak ilgili bir sınıf Delphi son sürümlerinde mevcuttur: http://docwiki.embarcadero.com/Librarie ... henticator
Cevapla