Lazarus

Programming => Networking and Web Programming => Topic started by: michoux on July 15, 2019, 03:26:14 pm

Title: Curl post
Post by: michoux on July 15, 2019, 03:26:14 pm
Hello all.

I am searching for lazarus solution to post a file content to php web.
With curl I do following:
curl -X POST --data-binary @path/to/my-file.txt http://example.com/

Is there a lazarus option for this?

Thanks
Title: Re: Curl post
Post by: engkin on July 15, 2019, 05:53:25 pm
Try:
Code: Pascal  [Select][+][-]
  1. uses fphttpclient
  2. ..
  3.   TFPHTTPClient.SimplePost('http://example.com/', 'path/to/my-file.txt');

Some servers need a User-Agent, others might redirect you from, say, http to https. For more control try:
Code: Pascal  [Select][+][-]
  1. uses fphttpclient
  2. ..
  3.   with TFPHTTPClient.Create(nil) do
  4.   try
  5.     AllowRedirect := True;
  6.     AddHeader('User-Agent','curl/7.37.0');
  7.     Post('http://example.com/', 'path/to/my-file.txt');
  8.   finally
  9.     Free;
  10.   end;
Title: Re: Curl post
Post by: michoux on August 12, 2019, 03:22:31 pm
As I know the post or simple post will post a file which is already on the server.
I am posting a local file from my PC
Title: Re: Curl post
Post by: michoux on August 12, 2019, 07:50:18 pm
curl command works great but I want to get rid of windows black window that alway show when running curl.exe
Title: Re: Curl post
Post by: bytebites on August 12, 2019, 08:07:44 pm
As I know the post or simple post will post a file which is already on the server.

Not true aka false.
Title: Re: Curl post
Post by: michoux on August 14, 2019, 08:29:21 am
Here is how my scripts on server works.
I can call it this way with file
http://mysite.com/send.php?xml=file.xml

Or I simply call curl with syntax from above
curl -X POST --data-binary @path/to/my-file.txt http://mysite.com/send.php

I have tried simplepost but it only accepts files from server, so I need  to first upload file from local PC to server in same location as my php scripts resides and then call
http://mysite.com/send.php?xml=./file.xml



Here is my php which I call

*****************************
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);

include_once('xml.php');   

$filename = utyGetString($_GET, 'xml', 'php://input');
$xmlData = file_get_contents($filename);

if (strlen($xmlData) > 0)
{
   $xml = new MyXML();
   echo $xml->ReadXML($xmlData);
}
else
{
   echo MyXML::WriteErrorXML('XML Data Empty');
}
?>
*********************************
Title: Re: Curl post
Post by: Leledumbo on August 14, 2019, 11:18:08 am
Here is how my scripts on server works.
I can call it this way with file
http://mysite.com/send.php?xml=file.xml

Or I simply call curl with syntax from above
curl -X POST --data-binary @path/to/my-file.txt http://mysite.com/send.php
Those two are not the same, the former issues a GET request with parameter named xml containing a string file.xml, the second one issues a POST request with the content of path/to/my-file.txt as raw request body.
TFPHTTPClient.SimplePost does the same as the latter.
Here is my php which I call

*****************************
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);

include_once('xml.php');   

$filename = utyGetString($_GET, 'xml', 'php://input');
$xmlData = file_get_contents($filename);
So you indeed only receive the filename from the request instead of the file content. Thus, the file that the code will read must already exist in the server. It's the server side that's incorrectly coded if you want to be able to send file from anywhere else other than the server.
Title: Re: Curl post
Post by: michoux on August 14, 2019, 11:42:27 am
Thanks for the feedback.

But with curl I can post a local file.
curl -X POST --data-binary @path/to/my-file.txt http://mysite.com/send.php

I was looking for something similar as curl.

Regards Michoux
Title: Re: Curl post
Post by: Leledumbo on August 14, 2019, 01:29:12 pm
Thanks for the feedback.

But with curl I can post a local file.
curl -X POST --data-binary @path/to/my-file.txt http://mysite.com/send.php

I was looking for something similar as curl.

Regards Michoux
No, you did not, try on real server separated from your developing computer. Read the documentation of file_get_contents, the first parameter is filename, which can also be a URL, but not something from a post request body. Your code explicitly states that it reads from $_GET, not $_POST, so you're reading only the filename, and because you're running the server on the same computer, it gives a false assumption that you successfully send the file from local.
Title: Re: Curl post
Post by: rvk on August 14, 2019, 01:42:02 pm
No, you did not, try on real server separated from your developing computer. Read the documentation of file_get_contents, the first parameter is filename, which can also be a URL, but not something from a post request body. Your code explicitly states that it reads from $_GET, not $_POST, so you're reading only the filename, and because you're running the server on the same computer, it gives a false assumption that you successfully send the file from local.
Actually... I see a function utyGetString() which uses php://input.

Definition for php://input
Quote
php://input is a read-only stream that allows you to read raw data from the request body. In the case of POST requests, it is preferable to use php://input instead of $HTTP_RAW_POST_DATA as it does not depend on special php.ini directives. Moreover, for those cases where $HTTP_RAW_POST_DATA is not populated by default, it is a potentially less memory intensive alternative to activating always_populate_raw_post_data. php://input is not available with enctype="multipart/form-data".

Although I've never seen it like this.

What is utyGetString() ??
(maybe that one creates a temporary file with the content of php://input returning the name of that temp-file)
Title: Re: Curl post
Post by: michoux on August 14, 2019, 02:56:08 pm
I am NOT running my web server on localhost but on "real" server and curl works ok for me.

Regards Michoux
Title: Re: Curl post
Post by: rvk on August 14, 2019, 03:05:39 pm
As I know the post or simple post will post a file which is already on the server.
I am posting a local file from my PC
You could use something like FileFormPost.
But that sends form info too.

Title: Re: Curl post
Post by: rvk on August 14, 2019, 03:16:35 pm
I'm not sure if there is already some function but something like this could/should post it without form-data.

Code: Pascal  [Select][+][-]
  1. var
  2.   F: TFileStream;
  3.   Response: TStringStream;
  4.   HTTP: TFPHTTPClient;
  5. begin
  6.   F := TFileStream.Create('c:\temp\test.txt', fmOpenRead or fmShareDenyWrite);
  7.   Response := TStringStream.Create;
  8.   HTTP := TFPHTTPClient.Create(nil);
  9.   try
  10.     HTTP.RequestBody := F;
  11.     HTTP.Post('http://domain/ttt.php', Response);
  12.     ShowMessage(Response.DataString);
  13.   finally
  14.     F.Free;
  15.     HTTP.Free;
  16.     Response.Free;
  17.   end;
  18. end;

Code: PHP  [Select][+][-]
  1. <?php
  2. ini_set('display_errors', 1);
  3. # $filename = utyGetString($_GET, 'xml', 'php://input'); ?????????????????
  4. $xmlData = file_get_contents('php://input');
  5. echo $xmlData;
  6. ?>

This php will just read the input and echo it back for the program to display.

Edit: Had this first implemented as helper procedure but that might complicate it too much.
Title: Re: Curl post
Post by: michoux on August 14, 2019, 04:21:29 pm
rvk - Thanks a lot, this. woooooorks :)

Just need to correct
TFileStream.Create;
to
TFileStream.Create('');

Sorry for my not-knowledge - I use to program in Pascal/Delphi 20 years ago :)

Thanks again to all for this help ..

Regards Michoux
Title: Re: Curl post
Post by: rvk on August 14, 2019, 04:46:35 pm
Just need to correct TFileStream.Create; to TFileStream.Create('');
You mean TStringStream.Create('') ??
The definition of TStringStream.Create is this:
Code: Pascal  [Select][+][-]
  1.   TStringStream = class(TBytesStream)
  2.   public
  3.     constructor Create(const AString: string = ''); overload;
The = '' after AString: string means that the AString is optional. And if left out the '' will be used. So .Create(''); isn't strictly necessary. .Create; works fine too.

It seems there isn't much need for posting a file raw in the body (otherwise there would have been a function for it).
Normally the SimpleFileFormPost() is used and then a "fieldname" is provided (could be anything).
In PHP you could then access $_FILES to retrieve the files and content (in that case the content is already written to a temp-file).

But posting it as raw body and using php://input is also possible. The only downside is that you can't provide a filename (which is possible with the form-date and $_FILES).

No problems about your knowledge. We're glad to help.
Title: Re: Curl post
Post by: michoux on August 14, 2019, 09:49:58 pm
Hi,

Sorry
Response := TStringStream.Create;
to
Response := TStringStream.Create('');

Response := TStringStream.Create; did not work for me, got an error ...

I did not develop the php sources and I am not really allowed to change them, just use them as they are :)))
This is app to load live data from sport events in real time.

I am coding connector between timing software and this web app to transfer data in xml format ...

DB is sqlite and I have some problems with DB lock, but I will ask this in other forum ...

Thanks again for help :)

Regards Michoux
Title: Re: Curl post
Post by: rvk on August 14, 2019, 10:02:05 pm
Response := TStringStream.Create; did not work for me, got an error ...
Ah, ok. Maybe you have an older Lazarus/FPC installation. I'm not sure at what point the AString became optional (because for me it is, in the trunk-version).
TinyPortal © 2005-2018