I would like to use cURL to not only send data parameters in HTTP POST but to also upload files with specific form name. How should I go about doing that ?
HTTP Post parameters:
userid = 12345
filecomment = This is an image file
HTTP File upload:
File location = /home/user1/Desktop/test.jpg
Form name for file = image (correspond to the $_FILES['image'] at the PHP side)
I figured part of the cURL command as follows:
curl -d "userid=1&filecomment=This is an image file" --data-binary #"/home/user1/Desktop/test.jpg" localhost/uploader.php
The problem I am getting is as follows:
Notice: Undefined index: image in /var/www/uploader.php
The problem is I am using $_FILES['image'] to pick up files in the PHP script.
How do I adjust my cURL commands accordingly ?
You need to use the -F option:
-F/--form <name=content> Specify HTTP multipart POST data (H)
Try this:
curl \
-F "userid=1" \
-F "filecomment=This is an image file" \
-F "image=#/home/user1/Desktop/test.jpg" \
localhost/uploader.php
Catching the user id as path variable (recommended):
curl -i -X POST -H "Content-Type: multipart/form-data"
-F "data=#test.mp3" http://mysuperserver/media/1234/upload/
Catching the user id as part of the form:
curl -i -X POST -H "Content-Type: multipart/form-data"
-F "data=#test.mp3;userid=1234" http://mysuperserver/media/upload/
or:
curl -i -X POST -H "Content-Type: multipart/form-data"
-F "data=#test.mp3" -F "userid=1234" http://mysuperserver/media/upload/
Here is my solution, I have been reading a lot of posts and they were really helpful. Finally I wrote some code for small files, with cURL and PHP that I think its really useful.
public function postFile()
{
$file_url = "test.txt"; //here is the file route, in this case is on same directory but you can set URL too like "http://examplewebsite.com/test.txt"
$eol = "\r\n"; //default line-break for mime type
$BOUNDARY = md5(time()); //random boundaryid, is a separator for each param on my post curl function
$BODY=""; //init my curl body
$BODY.= '--'.$BOUNDARY. $eol; //start param header
$BODY .= 'Content-Disposition: form-data; name="sometext"' . $eol . $eol; // last Content with 2 $eol, in this case is only 1 content.
$BODY .= "Some Data" . $eol;//param data in this case is a simple post data and 1 $eol for the end of the data
$BODY.= '--'.$BOUNDARY. $eol; // start 2nd param,
$BODY.= 'Content-Disposition: form-data; name="somefile"; filename="test.txt"'. $eol ; //first Content data for post file, remember you only put 1 when you are going to add more Contents, and 2 on the last, to close the Content Instance
$BODY.= 'Content-Type: application/octet-stream' . $eol; //Same before row
$BODY.= 'Content-Transfer-Encoding: base64' . $eol . $eol; // we put the last Content and 2 $eol,
$BODY.= chunk_split(base64_encode(file_get_contents($file_url))) . $eol; // we write the Base64 File Content and the $eol to finish the data,
$BODY.= '--'.$BOUNDARY .'--' . $eol. $eol; // we close the param and the post width "--" and 2 $eol at the end of our boundary header.
$ch = curl_init(); //init curl
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'X_PARAM_TOKEN : 71e2cb8b-42b7-4bf0-b2e8-53fbd2f578f9' //custom header for my api validation you can get it from $_SERVER["HTTP_X_PARAM_TOKEN"] variable
,"Content-Type: multipart/form-data; boundary=".$BOUNDARY) //setting our mime type for make it work on $_FILE variable
);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/1.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0'); //setting our user agent
curl_setopt($ch, CURLOPT_URL, "api.endpoint.post"); //setting our api post url
curl_setopt($ch, CURLOPT_COOKIEJAR, $BOUNDARY.'.txt'); //saving cookies just in case we want
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); // call return content
curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 1); navigate the endpoint
curl_setopt($ch, CURLOPT_POST, true); //set as post
curl_setopt($ch, CURLOPT_POSTFIELDS, $BODY); // set our $BODY
$response = curl_exec($ch); // start curl navigation
print_r($response); //print response
}
With this we should be get on the "api.endpoint.post" the following vars posted. You can easily test with this script, and you should be receive this debugs on the function postFile() at the last row.
print_r($response); //print response
public function getPostFile()
{
echo "\n\n_SERVER\n";
echo "<pre>";
print_r($_SERVER['HTTP_X_PARAM_TOKEN']);
echo "/<pre>";
echo "_POST\n";
echo "<pre>";
print_r($_POST['sometext']);
echo "/<pre>";
echo "_FILES\n";
echo "<pre>";
print_r($_FILEST['somefile']);
echo "/<pre>";
}
It should work well, they may be better solutions but this works and is really helpful to understand how the Boundary and multipart/from-data mime works on PHP and cURL library.
if you are uploading binary file such as csv, use below format to upload file
curl -X POST \
'http://localhost:8080/workers' \
-H 'authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6ImFjY2VzcyIsInR5cGUiOiJhY2Nlc3MifQ.eyJ1c2VySWQiOjEsImFjY291bnRJZCI6MSwiaWF0IjoxNTExMzMwMzg5LCJleHAiOjE1MTM5MjIzODksImF1ZCI6Imh0dHBzOi8veW91cmRvbWFpbi5jb20iLCJpc3MiOiJmZWF0aGVycyIsInN1YiI6ImFub255bW91cyJ9.HWk7qJ0uK6SEi8qSeeB6-TGslDlZOTpG51U6kVi8nYc' \
-H 'content-type: application/x-www-form-urlencoded' \
--data-binary '#/home/limitless/Downloads/iRoute Masters - Workers.csv'
After a lot of tries this command worked for me:
curl -v -F filename=image.jpg -F upload=#image.jpg http://localhost:8080/api/upload
The issue that lead me here turned out to be a basic user error - I wasn't including the # sign in the path of the file and so curl was posting the path/name of the file rather than the contents. The Content-Length value was therefore 8 rather than the 479 I expected to see given the legnth of my test file.
The Content-Length header will be automatically calculated when curl reads and posts the file.
curl -i -H "Content-Type: application/xml" --data "#test.xml" -v -X POST https://<url>/<uri/
...
< Content-Length: 479
...
Posting this here to assist other newbies in future.
As an alternative to curl, you can use HTTPie, it'a CLI, cURL-like tool for humans.
Installation instructions: https://github.com/jakubroztocil/httpie#installation
Then, run:
http -f POST http://localhost:4040/api/users username=johnsnow photo#images/avatar.jpg
HTTP/1.1 200 OK
Access-Control-Expose-Headers: X-Frontend
Cache-control: no-store
Connection: keep-alive
Content-Encoding: gzip
Content-Length: 89
Content-Type: text/html; charset=windows-1251
Date: Tue, 26 Jun 2018 11:11:55 GMT
Pragma: no-cache
Server: Apache
Vary: Accept-Encoding
X-Frontend: front623311
...
I got it worked with this command curl -F 'filename=#/home/yourhomedirextory/file.txt' http://yourserver/upload
cat test.txt
file test.txt content.
curl -v -F "hello=word" -F "file=#test.txt" https://httpbin.org/post
> POST /post HTTP/2
> Host: httpbin.org
> user-agent: curl/7.68.0
> accept: */*
> content-length: 307
> content-type: multipart/form-data; boundary=------------------------78a9f655d8c87a53
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
* We are completely uploaded and fine
< HTTP/2 200
< date: Mon, 15 Nov 2021 06:18:47 GMT
< content-type: application/json
< content-length: 510
< server: gunicorn/19.9.0
< access-control-allow-origin: *
< access-control-allow-credentials: true
<
{
"args": {},
"data": "",
"files": {
"file": "file test.txt content.\n"
},
"form": {
"hello": "word"
},
"headers": {
"Accept": "*/*",
"Content-Length": "307",
"Content-Type": "multipart/form-data; boundary=------------------------78a9f655d8c87a53",
"Host": "httpbin.org",
"User-Agent": "curl/7.68.0",
"X-Amzn-Trace-Id": "Root=1-6191fbc7-6c68fead194d943d07148860"
},
"json": null,
"origin": "43.129.xx.xxx",
"url": "https://httpbin.org/post"
}
Here is how to correctly escape arbitrary filenames of uploaded files with bash:
#!/bin/bash
set -eu
f="$1"
f=${f//\\/\\\\}
f=${f//\"/\\\"}
f=${f//;/\\;}
curl --silent --form "uploaded=#\"$f\"" "$2"
save all sent files to folder:
php file on host. u.php:
<?php
$uploaddir = 'C:/VALID_DIR/';
echo '<pre>';
foreach ($_FILES as $key => $file) {
if(!isset($file) || !isset($file['name'])) continue;
$uploadfile = $uploaddir . basename($file['name']);
if (move_uploaded_file($file['tmp_name'], $uploadfile)) {
echo "$key file > $uploadfile .\n";
} else {
echo " Error $key file.\n";
}
}
print_r($_FILES);
print "</pre>";?>
Usage from client:
curl -v -F filename=ff.xml -F upload=#ff.xml https://myhost.com/u.php
This is worked for me.
My VM crashed it has only internet connection.
I recovered some files this way.
Related
I want to setup a small file of cURL requests so I can quickly test my Laravel app's API quickly.
Unfortunately, I'm stuck at logging in :D.
This is what I have so far:
curl -H "Accept: application/json" -d #./curl/user.json http://localhost:8000/login -o ./curl/response.json -v
I have a user.json file that has my login info:
{
"email": "boss#example.com",
"password": "password",
}
And I would like to output the data into my response.json file.
Nothing is working though. I have a poor understanding of a couple of these technologies. Anyone able to hold my hand through this?
With the -v tag, I'm getting:
connect to ::1 port 8000 failed: Connection refused
* Trying 127.0.0.1:8000...
* Connected to localhost (127.0.0.1) port 8000 (#0)
> POST /login HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.77.0
> Accept: application/json
> Content-Length: 81
> Content-Type: application/x-www-form-urlencoded
>
} [81 bytes data]
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Host: localhost:8000
< Date: Mon, 17 Jan 2022 01:47:53 GMT
< Connection: close
< X-Powered-By: PHP/7.4.27
< Cache-Control: no-cache, private
< Date: Mon, 17 Jan 2022 01:47:53 GMT
< Content-Type: application/json
< Set-Cookie: laravel_session=eyJpdiI6IkpoUkhoQnNWdEVhYUdGU2wzckg5c3c9PSIsInZhbHVlIjoidGwrUHpBcDV4Z2lXNWdObmQrdER2OUp0aEIveXhpdFNREmovedSomeSTufffForSecurityPurposesmNyb3oiLCJtYWMiOiIyZTY2Yzk1MWY3MDA3M2I3NDkzMmQzMTUwMjcyNDFmMTU3MTU
0MzRmZjAzNDBjZmZmZTgwMjg1MjMzOThkZmU5IiwidGFnIjoiIn0%3D; expires=Mon, 17-Jan-2022 03:47:53 GMT; Max-Age=7200; path=/; httponly; samesite=lax
<
Any idea how I can login to a Larvel app using cURL? The goal is to make it work like Postman, but in the terminal!
I want to setup a small file of cURL requests so I can quickly test my Laravel app's API quickly.
Any idea how I can login to a Larvel app using cURL? The goal is to make it work like Postman, but in the terminal!
Login using Laravel's default authentication page and API authentication are two different things. I can't explain to you about API authentication in depth, as it would be quite lengthy.
Laravel has two packages that you can use for this case, Passport and Sanctum.
Sanctum is automatically installed when you install Laravel.
Since middleware on web is different from API, you should focus on route routes/api.php. You can create a token generation route (same as login). For example :
Route::post('/token', function (Request $request) {
// You can replace it with your login logic
$user = User::first();
$token = $user->createToken('Your Awesome Token Name');
return ['token' => $token->plainTextToken];
});
Return :
{
"token": "1|jLw1HhWJhSVQq81VFZwhxYB93GKMl5JRCrtuYQ36"
}
Then, the generated token you can use to access other API routes.
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
Calling via cURL :
curl -i http://your-awesome-app.test/api/user -H "Authorization: Bearer <TOKEN>"
Change <TOKEN> :
curl -i http://your-awesome-app.test/api/user -H "Authorization: Bearer 1|jLw1HhWJhSVQq81VFZwhxYB93GKMl5JRCrtuYQ36"
Viola!!!
{
"id":1,
"name":"Your Awesome User",
"email":"your.awesome#user.test",
"email_verified_at":"2022-01-17T03:03:58.000000Z",
"created_at":"2022-01-17T03:03:58.000000Z",
"updated_at":"2022-01-17T03:03:58.000000Z"
}
I need to consume the linode api, in the description it says I have to send the data using curl like this
curl -H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-X POST -d '{
"label": "asdfasdf"
"ssh_key": "asdfasdf"
}' \
https://api.linode.com/v4/profile/sshkeys
I tried using
http = Faraday::Connection.new 'https://api.linode.com/v4/profile/sshkeys'
http.authorization :Bearer, token
http.post('', { 'label' => 'adfadf', ..}.to_json)
But every request it says label and ssh_key required. I don´t know how to send this particular request
anyone?
You need to specify the content-type as json in the header, if you're sending a json data.
http.post(
'',
{ 'label' => 'adfadf', ..}.to_json,
{ 'Content-Type' => 'application/json' }
)
Reference: https://lostisland.github.io/faraday/usage/
I have for many Days i could not make http post request for the following site
http://www.imei.sy/imei
I don't know the principle behind that. I tried to make the request using GuzzleHttp, and curl.
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "http://www.imei.sy/imei",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "UTF-8",
CURLOPT_MAXREDIRS => 20,
CURLOPT_TIMEOUT => 60,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => array("_token:evsLRDom2AShHsioY5OyEB7cDU45opx8J0VLgqd2",//TgghCi5gkU6HODTyDwAWq0mvEyHC3ys8dXGskta1",
"imei:000000000000000"),
CURLOPT_HTTPHEADER => array(
"cache-control: no-cache",
"content-type: application/x-www-form-urlencoded",
"postman-token: 6a987964-86b8-25db-71a5-7c47822ec59c"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
i can not reproduce the issue, when i run the code you provided, it executes the following POST request:
POST /imei HTTP/1.1
Host: www.imei.sy
Accept: */*
Accept-Encoding: UTF-8
cache-control: no-cache
postman-token: 6a987964-86b8-25db-71a5-7c47822ec59c
Content-Length: 295
Content-Type: application/x-www-form-urlencoded; boundary=------------------------4b99e3fabc390822
--------------------------4b99e3fabc390822
Content-Disposition: attachment; name="0"
_token:evsLRDom2AShHsioY5OyEB7cDU45opx8J0VLgqd2
--------------------------4b99e3fabc390822
Content-Disposition: attachment; name="1"
imei:000000000000000
--------------------------4b99e3fabc390822--
this is definitely a POST request in the multipart/form-data-format. (even tho the Content-Type header incorrectly claims that it's in the application/x-www-form-urlencoded-format, which makes servers unable to parse it properly.. but it's still a POST request nonetheless, it's just a severely malformed one.)
however note that code definitely won't be checking any IMEI code, because prior to checking a code, you must get a cookie and a CSRF token, the token won't work without the cookie and the cookie won't work without the token, but the token change for every cookie, and you can't hardcode it, but that's exactly what your code is trying to do,
your code won't work because:
it never creates a cookie session (required to check an IMEI)
it attempts to hardcode a CSRF token instead of fetching a dynamic token. (the CSRF token is tied to the cookie session.. which your code never creates in the first place.)
.. to check an IMEI here, first you have to enable cookie handling in curl, that can be done with CURLOPT_COOKIEFILE, also UTF-8 is not a valid transfer-encoding and makes no sense, instead do:
curl_setopt_array($ch,array(
// emptystring COOKIEFILE tells curl enable cookie-handling and save cookies in-ram
CURLOPT_COOKIEFILE=>'',
// emptystring encoding tells curl to automatically handle compression with all built-in compression algorithms (usually "gzip" and "deflate"), it makes compressible transfers faster
CURLOPT_ENCODING=>'',
CURLOPT_RETURNTRANSFER=>1,
));
next you have to fetch the page with a normal GET request, this will give curl the cookie needed to check an IMEI, and give curl the CSRF token needed to check an imei,
curl_setopt_array($ch,array(
CURLOPT_URL=>'http://www.imei.sy/imei',
CURLOPT_HTTPGET=>1
));
$html=curl_exec($ch);
if(empty($html)){
try{
throw new \RuntimeException("curl_exec() failed! ".curl_errno($ch).": ".curl_error($ch) );
}finally{
curl_close($ch);
}
}
after you got the cookie (which is handled automatically by curl), and the CSRF token in the HTML, you need to extract the token from the HTML, that can be done with DOMDocument and DOMXPath,
$domd=#DOMDocument::loadHTML($html);
$xp=new DOMXPath($domd);
$token=$xp->query("//input[#name='_token']")->item(0)->getAttribute("value");
and finally, now that you have both the session cookie and the CSRF token, you can do the IMEI lookup request,
curl_setopt_array($ch,array(
CURLOPT_POST=>1,
CURLOPT_POSTFIELDS=>http_build_query(array(
'_token'=>$token,
'imei'=>'999999999999999'
))
));
$html=curl_exec($ch);
if(empty($html)){
try{
throw new \RuntimeException("curl_exec() failed! ".curl_errno($ch).": ".curl_error($ch) );
}finally{
curl_close($ch);
}
}
curl_close($ch);
and to get the response from the HTML, one can again use DOMDocument,
$message=(#DOMDocument::loadHTML($html))->getElementById("sts")->textContent;
var_dump($message);
which yields:
$ php wtf2.php
string(100) " مُعرف الجهاز المُدخل غير صالح، الرجاء التحقق من الرقم "
because 999999999999999 was not a valid IMEI code.
I would like to use cURL to not only send data parameters in HTTP POST but to also upload files with specific form name. How should I go about doing that ?
HTTP Post parameters:
userid = 12345
filecomment = This is an image file
HTTP File upload:
File location = /home/user1/Desktop/test.jpg
Form name for file = image (correspond to the $_FILES['image'] at the PHP side)
I figured part of the cURL command as follows:
curl -d "userid=1&filecomment=This is an image file" --data-binary #"/home/user1/Desktop/test.jpg" localhost/uploader.php
The problem I am getting is as follows:
Notice: Undefined index: image in /var/www/uploader.php
The problem is I am using $_FILES['image'] to pick up files in the PHP script.
How do I adjust my cURL commands accordingly ?
You need to use the -F option:
-F/--form <name=content> Specify HTTP multipart POST data (H)
Try this:
curl \
-F "userid=1" \
-F "filecomment=This is an image file" \
-F "image=#/home/user1/Desktop/test.jpg" \
localhost/uploader.php
Catching the user id as path variable (recommended):
curl -i -X POST -H "Content-Type: multipart/form-data"
-F "data=#test.mp3" http://mysuperserver/media/1234/upload/
Catching the user id as part of the form:
curl -i -X POST -H "Content-Type: multipart/form-data"
-F "data=#test.mp3;userid=1234" http://mysuperserver/media/upload/
or:
curl -i -X POST -H "Content-Type: multipart/form-data"
-F "data=#test.mp3" -F "userid=1234" http://mysuperserver/media/upload/
Here is my solution, I have been reading a lot of posts and they were really helpful. Finally I wrote some code for small files, with cURL and PHP that I think its really useful.
public function postFile()
{
$file_url = "test.txt"; //here is the file route, in this case is on same directory but you can set URL too like "http://examplewebsite.com/test.txt"
$eol = "\r\n"; //default line-break for mime type
$BOUNDARY = md5(time()); //random boundaryid, is a separator for each param on my post curl function
$BODY=""; //init my curl body
$BODY.= '--'.$BOUNDARY. $eol; //start param header
$BODY .= 'Content-Disposition: form-data; name="sometext"' . $eol . $eol; // last Content with 2 $eol, in this case is only 1 content.
$BODY .= "Some Data" . $eol;//param data in this case is a simple post data and 1 $eol for the end of the data
$BODY.= '--'.$BOUNDARY. $eol; // start 2nd param,
$BODY.= 'Content-Disposition: form-data; name="somefile"; filename="test.txt"'. $eol ; //first Content data for post file, remember you only put 1 when you are going to add more Contents, and 2 on the last, to close the Content Instance
$BODY.= 'Content-Type: application/octet-stream' . $eol; //Same before row
$BODY.= 'Content-Transfer-Encoding: base64' . $eol . $eol; // we put the last Content and 2 $eol,
$BODY.= chunk_split(base64_encode(file_get_contents($file_url))) . $eol; // we write the Base64 File Content and the $eol to finish the data,
$BODY.= '--'.$BOUNDARY .'--' . $eol. $eol; // we close the param and the post width "--" and 2 $eol at the end of our boundary header.
$ch = curl_init(); //init curl
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'X_PARAM_TOKEN : 71e2cb8b-42b7-4bf0-b2e8-53fbd2f578f9' //custom header for my api validation you can get it from $_SERVER["HTTP_X_PARAM_TOKEN"] variable
,"Content-Type: multipart/form-data; boundary=".$BOUNDARY) //setting our mime type for make it work on $_FILE variable
);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/1.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0'); //setting our user agent
curl_setopt($ch, CURLOPT_URL, "api.endpoint.post"); //setting our api post url
curl_setopt($ch, CURLOPT_COOKIEJAR, $BOUNDARY.'.txt'); //saving cookies just in case we want
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); // call return content
curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 1); navigate the endpoint
curl_setopt($ch, CURLOPT_POST, true); //set as post
curl_setopt($ch, CURLOPT_POSTFIELDS, $BODY); // set our $BODY
$response = curl_exec($ch); // start curl navigation
print_r($response); //print response
}
With this we should be get on the "api.endpoint.post" the following vars posted. You can easily test with this script, and you should be receive this debugs on the function postFile() at the last row.
print_r($response); //print response
public function getPostFile()
{
echo "\n\n_SERVER\n";
echo "<pre>";
print_r($_SERVER['HTTP_X_PARAM_TOKEN']);
echo "/<pre>";
echo "_POST\n";
echo "<pre>";
print_r($_POST['sometext']);
echo "/<pre>";
echo "_FILES\n";
echo "<pre>";
print_r($_FILEST['somefile']);
echo "/<pre>";
}
It should work well, they may be better solutions but this works and is really helpful to understand how the Boundary and multipart/from-data mime works on PHP and cURL library.
if you are uploading binary file such as csv, use below format to upload file
curl -X POST \
'http://localhost:8080/workers' \
-H 'authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6ImFjY2VzcyIsInR5cGUiOiJhY2Nlc3MifQ.eyJ1c2VySWQiOjEsImFjY291bnRJZCI6MSwiaWF0IjoxNTExMzMwMzg5LCJleHAiOjE1MTM5MjIzODksImF1ZCI6Imh0dHBzOi8veW91cmRvbWFpbi5jb20iLCJpc3MiOiJmZWF0aGVycyIsInN1YiI6ImFub255bW91cyJ9.HWk7qJ0uK6SEi8qSeeB6-TGslDlZOTpG51U6kVi8nYc' \
-H 'content-type: application/x-www-form-urlencoded' \
--data-binary '#/home/limitless/Downloads/iRoute Masters - Workers.csv'
After a lot of tries this command worked for me:
curl -v -F filename=image.jpg -F upload=#image.jpg http://localhost:8080/api/upload
The issue that lead me here turned out to be a basic user error - I wasn't including the # sign in the path of the file and so curl was posting the path/name of the file rather than the contents. The Content-Length value was therefore 8 rather than the 479 I expected to see given the legnth of my test file.
The Content-Length header will be automatically calculated when curl reads and posts the file.
curl -i -H "Content-Type: application/xml" --data "#test.xml" -v -X POST https://<url>/<uri/
...
< Content-Length: 479
...
Posting this here to assist other newbies in future.
As an alternative to curl, you can use HTTPie, it'a CLI, cURL-like tool for humans.
Installation instructions: https://github.com/jakubroztocil/httpie#installation
Then, run:
http -f POST http://localhost:4040/api/users username=johnsnow photo#images/avatar.jpg
HTTP/1.1 200 OK
Access-Control-Expose-Headers: X-Frontend
Cache-control: no-store
Connection: keep-alive
Content-Encoding: gzip
Content-Length: 89
Content-Type: text/html; charset=windows-1251
Date: Tue, 26 Jun 2018 11:11:55 GMT
Pragma: no-cache
Server: Apache
Vary: Accept-Encoding
X-Frontend: front623311
...
I got it worked with this command curl -F 'filename=#/home/yourhomedirextory/file.txt' http://yourserver/upload
cat test.txt
file test.txt content.
curl -v -F "hello=word" -F "file=#test.txt" https://httpbin.org/post
> POST /post HTTP/2
> Host: httpbin.org
> user-agent: curl/7.68.0
> accept: */*
> content-length: 307
> content-type: multipart/form-data; boundary=------------------------78a9f655d8c87a53
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
* We are completely uploaded and fine
< HTTP/2 200
< date: Mon, 15 Nov 2021 06:18:47 GMT
< content-type: application/json
< content-length: 510
< server: gunicorn/19.9.0
< access-control-allow-origin: *
< access-control-allow-credentials: true
<
{
"args": {},
"data": "",
"files": {
"file": "file test.txt content.\n"
},
"form": {
"hello": "word"
},
"headers": {
"Accept": "*/*",
"Content-Length": "307",
"Content-Type": "multipart/form-data; boundary=------------------------78a9f655d8c87a53",
"Host": "httpbin.org",
"User-Agent": "curl/7.68.0",
"X-Amzn-Trace-Id": "Root=1-6191fbc7-6c68fead194d943d07148860"
},
"json": null,
"origin": "43.129.xx.xxx",
"url": "https://httpbin.org/post"
}
Here is how to correctly escape arbitrary filenames of uploaded files with bash:
#!/bin/bash
set -eu
f="$1"
f=${f//\\/\\\\}
f=${f//\"/\\\"}
f=${f//;/\\;}
curl --silent --form "uploaded=#\"$f\"" "$2"
save all sent files to folder:
php file on host. u.php:
<?php
$uploaddir = 'C:/VALID_DIR/';
echo '<pre>';
foreach ($_FILES as $key => $file) {
if(!isset($file) || !isset($file['name'])) continue;
$uploadfile = $uploaddir . basename($file['name']);
if (move_uploaded_file($file['tmp_name'], $uploadfile)) {
echo "$key file > $uploadfile .\n";
} else {
echo " Error $key file.\n";
}
}
print_r($_FILES);
print "</pre>";?>
Usage from client:
curl -v -F filename=ff.xml -F upload=#ff.xml https://myhost.com/u.php
This is worked for me.
My VM crashed it has only internet connection.
I recovered some files this way.
I'm trying to pipe support emails from my production mail server (Plesk 12 and Postfix) to send them to another VPS hosting my helpdesk installation, I have chosen ostickets helpdesk for many reasons (Open source,PHP/MySQL...)
So, the idea is to trigger email reception on some adresses such as contact#company.com, support#company.com... then resend them to ostickets via its API in order to create a new ticket there.
I tried this way
http://blog.absolutedisaster.co.uk/osticket-plesk-9-postfix-pipe-mail-to-a-progr/
It explains how to create a pipe to trigger email, lunch php script ...etc
Because of some permission issues, I kept all this configuration and change just the last thing : php script
So I've replaced this php script by a simple bash script doing the same thing : send a request to API to create a new ticket via CURL.
Now In my production mail server the pipe is recognized and the email is trigged successfully :
The same in the other side, osticket API is receiving the request:
The problem is that the http response is 400 as you can see, which means ans error code #66 in ostickets (malformed email).
So, I think the problem is in my bash script :
exec curl --header 'X-API-Key: API_KEY_HERE' --user-agent 'osTicket API Client v1.7' --data - 'http://support.company.com/api/tickets.email'
the original PHP script I have replaced by this is :
#!/usr/bin/php -q
<?php
# Configuration: Enter the url and key. That is it.
# url => URL to api/tickets.email e.g http://yourdomain.com/support/api/tickets.email
# key => API's Key (see admin panel on how to generate a key)
#
$config = array(
'url'=>'http://support.company.com/api/tickets.email',
'key'=>'API_KEY_HERE'
);
#pre-checks
function_exists('file_get_contents') or die('upgrade php >=4.3');
function_exists('curl_version') or die('CURL support required');
#read stdin (piped email)
$data=file_get_contents('php://stdin') or die('Error reading stdin. No message');
#set timeout
set_time_limit(10);
#curl post
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $config['url']);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_USERAGENT, 'osTicket API Client v1.7');
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Expect:', 'X-API-Key: '.$config['key']));
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$result=curl_exec($ch);
curl_close($ch);
//Use postfix exit codes...expected by MTA.
$code = 75;
if(preg_match('/HTTP\/.* ([0-9]+) .*/', $result, $status)) {
switch($status[1]) {
case 201: //Success
$code = 0;
break;
case 400:
$code = 66;
break;
case 401: /* permission denied */
case 403:
$code = 77;
break;
case 415:
case 416:
case 417:
case 501:
$code = 65;
break;
case 503:
$code = 69;
break;
case 500: //Server error.
default: //Temp (unknown) failure - retry
$code = 75;
}
}
exit($code);
?>
What is missing in my bash script ? (especially the stdin input)
thank you so much,
UPDATE
The problem was indeed in the bash script, here is the solution I came up with:
#!/bin/bash
data=`cat -`
exec curl --header 'X-API-Key: API_KEY_HERE' --user-agent 'osTicket API Client v1.7' --data "$data" 'http://support.company.com/api/tickets.email'
The problem was indeed in the bash script, here is the solution I came up with:
#!/bin/bash
data=`cat -`
exec curl --header 'X-API-Key: API_KEY_HERE' --user-agent 'osTicket API Client v1.7' --data "$data" 'http://support.company.com/api/tickets.email'