RTC Forums
April 29, 2024, 11:31:23 AM *
Welcome, Guest. Please login or register.

Login with username, password and session length
 
   Home   Help Login Register  
Pages: [1] 2
  Print  
Author Topic: POST to a 3rd party website  (Read 7813 times)
HalcyonLogic
Newbie
*
Posts: 45


« on: January 28, 2014, 01:15:21 AM »

I know this has been explained on this forum, but I still can't seem to wrap my head around it.

How can I POST to a 3rd party web service?

I know I should be using a TRtcHttpClient for this but what if I don't know the Port #?

Let's say what I want to do is the following request:
www.a3rdPartywebsite.com/ASeviceName?Param1=A&Param2=B&Param3=C

So, using RTC, I would do something like:

  with RtcDataRequest1.Request, Params do
  begin
      Method := 'POST';
      Host := 'www.a3rdPartywebsite.com';
      FileName := 'Huh';
      Clear;
      AsString['Param1'] := URL_Encode( MyParam1 );
      AsString['Param2'] := URL_Encode( MyParam2 );
      AsString['Param3'] := URL_Encode( MyParam3 );
  end;
  RtcDataRequest1.Post();


Is that all?
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #1 on: January 28, 2014, 01:20:02 AM »

  with RtcDataRequest1.Request do
    begin
      Method := 'POST';
      Host := 'www.a3rdPartywebsite.com';
      FileName := '/AServiceName';
      Query['Param1'] := URL_Encode( MyParam1 );
      Query['Param2'] := URL_Encode( MyParam2 );
      Query['Param3'] := URL_Encode( MyParam3 );
    end;
  RtcDataRequest1.Post();

You can also assign the complete FileName with all Query parameters by using the Request.URI property, like this:

  with RtcDataRequest1.Request do
    begin
      Method := 'POST';
      Host := 'www.a3rdPartywebsite.com';
      URI := '/AServiceName?Param1=A&Param2=B&Param3=C';
    end;
  RtcDataRequest1.Post();

Btw ... You also need to set the ServerAddr and ServerPort on the TRtcHttpClient component. It is not enough to set the Host property on the Request object. Check the QuickStart\ClientFormPost Project for an example on posting to the Website.

Best Regards,
Danijel Tkalcec
Logged
HalcyonLogic
Newbie
*
Posts: 45


« Reply #2 on: January 28, 2014, 01:28:08 AM »

Thanks Danijel, but what if I don't know the port # and the owner of the web service doesn't provide it?

All I have to work with (all I know) is the URL, service name and the parameters:
www.a3rdPartywebsite.com/ASeviceName?Param1=A&Param2=B&Param3=C

No port.
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #3 on: January 28, 2014, 01:45:19 AM »

HTTP:// means Port 80
HTTPS:// means Port 443 and requires SSL

That is ... if there is no port explicitly declared in the URL.

Best Regards,
Danijel Tkalcec
Logged
HalcyonLogic
Newbie
*
Posts: 45


« Reply #4 on: January 28, 2014, 01:51:42 AM »

One more thing, how can I check the reply from the called web service?


Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #5 on: January 28, 2014, 02:12:48 AM »

TRtcDataRequest component has the OnDataReceived event.

Check the example Project I've posted about above, its everything in there.

Best Regards,
Danijel Tkalcec
Logged
HalcyonLogic
Newbie
*
Posts: 45


« Reply #6 on: January 28, 2014, 03:12:53 AM »

Danijel,

What if I need my POST to include basic-authentication
(i.e.

https://ABCDEFGH:12345@a3rdPartyWebsite.com

Do I include the username/password combo (ABCDEFGH:12345) as part of the URI or do I include them as parameters?

A little confused on this as I have not got it to work yet.

Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #7 on: January 28, 2014, 03:23:30 AM »

Basic User Authentication is not part of the URI. It is sent in HTTP header values. Please check HTTP RFC about basic authentication.

Best Regards,
Danijel Tkalcec
Logged
HalcyonLogic
Newbie
*
Posts: 45


« Reply #8 on: February 04, 2014, 08:33:46 PM »

Danijel, please throw me a bone here.

I am trying to POST to a 3rd party web service, and specifically POST additional parameters as follow (but the web service always replies that I am missing the specified parameters):

<DELPHI>
    RtcDataRequest1.Request.ContentType:='application/x-www-form-urlencoded'; // important!!!

    RtcDataRequest1.Request.Method := 'POST';
    RtcDataRequest1.Request.Host := 'www.website.com';
    RtcDataRequest1.Request.FileName := '/AService';

    RtcDataRequest1.Request.Params.Clear;
   RtcDataRequest1.Request.Params.AsString[ 'From' ] := URL_Encode( 'AFRomParameter' );
    RtcDataRequest1.Request.Params.AsString[ 'To' ]   := URL_Encode( 'AToParameter' );
    RtcDataRequest1.Request.Params.AsString[ 'Body' ] := URL_Encode( ABody );


    // I also tried using the URI, but got the same thing
    //RtcDataRequest1.Request.URI := URI;

    // I also tried using the Request.Query, but got the same thing
    // RtcDataRequest1.Request.Query[ 'From' ] := URL_Encode( 'AFromParam' );
    // RtcDataRequest1.Request.Query[ 'To' ]   := URL_Encode( 'AToParam' );
    // RtcDataRequest1.Request.Query[ 'Body' ] := URL_Encode( ABody );
//
    try
      RtcHttpClient1.Connect;
      RtcDataRequest1.Post();
    except
      on E: Exception do
      begin
        Raise;
      end;
    end;
<DELPHI>

As you can see I am posting the needed parameters, aren't I doing this right? What am I missing?

Please don't tell me to have a look at the demos, I have done that already and am stuck.

As always, please and thank you are in order.
Richard
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #9 on: February 04, 2014, 09:12:54 PM »

Using the Request.Params property only prepares a possible request content body, but does NOT send any content out. If you are posting to a website, you also need to implement then OnBeginRequest event and use the Write method to post your content out. It is not enough to just prepare it.

Did you look at the QuickStart\ClientFormPost example Project? All the code you need is there. The example only has 2 short events and a lot of comments. There is no better way I can exlain this to you. Pleaase, pay close attention to the OnBeginRequest and OnDataReceived event implementations. In the OnBeginRequest event, there is a Cli.Write(Cli.Request.Params.Text) call, which I am missing in your example above. That Write call has to be inside the OnBeginRequest event. You can not move it outside, because the "Write" methos ONLY works from inside RTC events.

This is the source code of that example project:

Code:
procedure TForm1.Button1Click(Sender: TObject);
  begin
  RtcDataRequest1.Request.Method:='POST'; // Use the "HTTP POST" method
  RtcDataRequest1.Request.FileName:='/x/index.php'; // Set the "FileName" to receive the request
  RtcDataRequest1.Request.Host:=RtcHttpClient1.ServerAddr; // Set the "Host" HTTP header
  RtcDataRequest1.Post(); // Post the request to the request queue
  end;

// The "OnBeginRequest" event is called after "RtcDataRequest1.Post" ...
procedure TForm1.RtcDataRequest1BeginRequest(Sender: TRtcConnection);
  var
    Cli:TRtcDataClient absolute Sender;
  begin
  Cli.Request.ContentType:='application/x-www-form-urlencoded'; // important!!!
  // Set all POST variables (in our case, "username" and "pwd")
  Cli.Request.Params.Value['username']:=URL_Encode('TestUser');
  Cli.Request.Params.Value['pwd']:=URL_Encode('XYZ123ABC');
  // Use the "Write" method to send "Params.Text" ("FORM-URLENCODED" values) to the Server
  Cli.Write(Cli.Request.Params.Text);
  end;

// The "OnDataReceived" event is called once the request was sent to the Server
// and we start receiving a response. Here, we will simply print the response out.
procedure TForm1.RtcDataRequest1DataReceived(Sender: TRtcConnection);
  var
    Cli:TRtcDataClient absolute Sender;
    mycontent:RtcString;
  begin
  // We want to wait for the whole response ...
  if Cli.Response.Done then
    begin
    // Since we have the whole response,
    // we can use a single "Read" call to get the complete content body
    mycontent:=Cli.Read;

    Memo1.Lines.Text:=IntToStr(Cli.Response.StatusCode)+' '+Cli.Response.StatusText+ #13#10
                     + mycontent;
    end;
  end;

Best Regards,
Danijel Tkalcec
Logged
HalcyonLogic
Newbie
*
Posts: 45


« Reply #10 on: February 04, 2014, 09:32:08 PM »

Ok, so I did implement a BeginRequest event and set the value of my parameters:

Code:
procedure TDM.RtcDataRequest1BeginRequest(Sender: TRtcConnection);
var
  Cli:TRtcDataClient absolute Sender;
begin
  Cli.Request.ContentType:='application/x-www-form-urlencoded'; // important!!!

  // Set all POST variables/patrameters
  Cli.Request.Params.Value[ 'From' ] := URL_Encode( 'AFromParam' );
  Cli.Request.Params.Value[ 'To' ]   := URL_Encode( 'AToParam' );
  Cli.Request.Params.Value[ 'Body' ] := URL_Encode( 'A Body' );

  TRtcDataClient( Sender ).WriteHeader;

  // Use the "Write" method to send "Params.Text" ("FORM-URLENCODED" values) to the Server
  Cli.Write( Cli.Request.Params.Text );
end;

Still get a response from the 3rd party service about the fact that I did not specify the "From" parameter though which, as you can see above, is clearly set/specified.

Like I said, I did have a look at the demos, but I can't get this simple thing to work. Pulling my hair out (and running low).

Richard
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #11 on: February 04, 2014, 09:41:49 PM »

You are very persistent in making changes to the code, so it does not work.

Why did you add a call to "WriteHeader" before the call to Write?
Logged
HalcyonLogic
Newbie
*
Posts: 45


« Reply #12 on: February 04, 2014, 09:46:26 PM »

Well you mentioned at the beginning of this post, that authentication must be done in the header,

"...Basic User Authentication is not part of the URI. It is sent in HTTP header values..."

So seeing a WriteHeader procedure though it would be a good idea.

 
Logged
HalcyonLogic
Newbie
*
Posts: 45


« Reply #13 on: February 04, 2014, 09:50:55 PM »

Removing the WriteHeader line does the trick.

So if it is not needed, when should we use WriteHeader?
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #14 on: February 04, 2014, 10:17:13 PM »

WriteHeader is used when you prepare the complete header manually, which needs to include the Request.ContentLength parameter and you want to send the content body out in smaller chunks. For example, when sending files. On the other hand, if you are sending the complete content body inside a single RTC event and you want RTC to calculate the content length based on the total content you wrote by the end of the event, you will only use the Write or WriteEx method, but not WriteHeader.

Best Regards,
Danijel Tkalcec
Logged
Pages: [1] 2
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Valid XHTML 1.0! Valid CSS!
Page created in 0.03 seconds with 16 queries.