An API I'm trying to program to requires multipart/form-data content with the HTTP GET verb. From the command line I can make this work like this:
curl -X GET -H "Accept: application/json" -F grant_type=consumer_credentials -F consumer_key=$key -F consumer_secret=$secret https://example.com/api/AccessToken
which seems like a contradiction in terms to me, but it actually works, and from what I see tracing it actually uses GET. I've tried a bunch of things to get this working using PHP's cURL library, but I just can't seem to get it to not use POST, which their servers kick out with an error.
Update to clarify the question: how can I get php's cURL library to do the same thing as that command line?
which seems like a contradiction in terms to me, but it actually
works, and from what I see tracing it actually uses GET
Not exactly. curl uses a feature of the HTTP/1.1. It inserts additional field to the header Expect: 100-continue, on which, if supported by server, server should response by HTTP/1.1 100 Continue, which tells the client to continue with its request. This interim response is used to inform the client that the initial part of the request has been received and has not yet been rejected by the server. The client SHOULD continue by sending the remainder of the request or, if the request has already been completed, ignore this response. The server MUST send a final response after the request has been completed.
Since they are insisting on HTTP GET, then just encode the form elements into query parameters on the URL you are GETing and use cURL's standard get options instead of posting multipart/formdata.
-X will only change the method keyword, everything else will remain acting the same which in this case (with the -F options) means like multipart formpost.
-F is multipart formpost and you really cannot convert that to a query part in the URL suitable for a typical GET so this was probably not a good idea to start with.
I would guess that you actually want to use -d to specify the data to post, and then you use -G to convert that data into a string that gets appended to the URL so that the operation turns out to a nice and clean GET.
Related
Here are two GET requests. The first one using CURL in php works, but the second one generated by an HTML form receives an error from the response server.
The first (working) is a GET request using CURL
1.
curl 'https://api.authy.com/protected/json/phones/verification/start' \
-d api_key=my_key\
-d via=sms \
-d phone_number=my_number\
-d country_code=my_code
The second (not working) is a GET request URL like one generated from an html form <form method='get'>
2.
https://api.authy.com/protected/json/phones/verification/start?api_key=my_key&via=sms&phone_number=my_number&country_code=my_code
The error message from the response server when using the second one is:
{"message":"Requested URL was not found. Please check http://docs.authy.com/ to see the valid URLs","success":false,"errors":{"message":"Requested URL was not found. Please check http://docs.authy.com/ to see the valid URLs"},"error_code":"60000"}
Question
What is the difference between second GET request compared to the CURL GET request? They look to me like they are identical.
According to the documentation at https://www.twilio.com/docs/verify/api/verification, you should use a POST request to use that API, and that is what the -d option of cURL does.
In your second call, you send a GET request, and according to the documentation and the error message, that is not successful
Let me preface this by stating that I'm a complete novice when it comes to php, but I have a need to create a php script for a particular curl request to monitor the state of a service.
The curl command is:
curl --insecure --digest 'https://admin:password#localhost:9993/management' --header "Content-Type: application/json" -d '{"operation":"read-attribute","name":"server-state","json.pretty":1}'
And it returns this output:
"outcome" : "success",
"result" : "running"
I've searched around, found some examples and hacked together a few different scripts but none of them give me the desired result (entirely my fault). I seem to have the authentication side working but I'm failing miserably at sending the array and returning a result. Essentially, I'm interested in getting the "running" field back (or whatever other value it might return) which I can use in out monitoring system. The closest I've got is for the server to throw a java ioexception at me because of an invalid character.
Any assistance will be greatly appreciated.
Thanks,
Mark J.
Never mind. I needed to json_encode my data string. All working now.
I am using the following cURL request to localhost which runs fine:
curl -u admin:e4d4face52f2e3dc22b43b2145ed7c58ce66e26b384d73592c -d "{\"jsonrpc\": \"2.0\", \"method\": \"feed.list\", \"id\": 1}" http://localhost/minifluxR/jsonrpc.php
But when I send the same request using Postman instead of cURL, I am getting:
{"jsonrpc":"2.0","id":null,"error":{"code":-32700,"message":"Parse error"}}
In Postman I used a GET request and sent the following as headers:
url:http://localhost/minifluxR/jsonrpc.php
username:admin
api_token:e4d4face52f2e3dc22b43b2145ed7c58ce66e26b384d73592c
method: feed.list
The following is the PHP function I am trying to trigger:
$server = new Server;
$server->authentication(array(
\Model\Config\get('username') => \Model\Config\get('api_token')
));
// Get all feeds
$server->register('feed.list', function () {
return Model\Feed\get_all();
});
Please help me to correct these errors.
When using cURL, the -u option (or --user) is used to supply the credentials for HTTP Basic authentication. This sets the Authorization header to contain the necessary data to authenticate with the server.
These steps apply to Postman's packaged app. For steps for the legacy app, view this of revision this answer.
To use HTTP Basic authentication as you were in your cURL command, click the Authorization tab and enter your credentials. Clicking Update Request will add the necessary Authorization header for you.
To submit the JSON data in the same way that you did with cURL, use a POST request, select raw under the Body tab, and enter your data like so:
To debug this I used Fiddler - a free web debugging proxy.
I used cURL's --proxy option to make it send its requests through Fiddler like so:
curl \
--proxy http://localhost:8888 \
-u foo:bar \
-d "{\"jsonrpc\": \"2.0\", \"method\": \"feed.list\", \"id\": 1}" \
http://localhost
Now that the request goes through Fiddler, I can select it from the session list, and use the "raw" inspector to see the raw request:
This shows me that the cURL is making a POST request with HTTP Basic authentication and application/x-www-form-urlencoded content. This type of data normally consists of keys and values, such as foo=bar&hoge=fuga. However, this cURL request is submitting a key without a value. A call to var_dump($_POST) will yield the following:
With a = at the end of the data (like so: {"jsonrpc": "2.0", "method": "feed.list", "id": 1}=) the var_dump will yield the following:
However, it seems that JsonRPC will use file_get_contents('php://input') in your case. This returns the data that was submitted with the request, including a =, if the data ends with it. Because it will try to parse the input data as a JSON string, it will fail if the string ends with a =, because that would be invalid JSON.
Using the FoxyProxy extension for Chrome, I created a proxy configuration for Fiddler (127.0.0.1:8888), which allowed me to easily debug the data being sent by Postman's POST request. Using x-www-form-urlencoded with a key of foo with no value, the data sent was actually foo=, which would result in your JSON string being invalid.
However, using "raw" input will allow for the specified data to be sent without a = being added to the end of it, thus ensuring the data is valid JSON.
Curl is using HTTP Basic authentication by default. Your headers set in Postman are something different. Try using Basic Auth in Postman. It is in top panel, you fill in username and password and authorization header will be generated.
I am quite experienced in PHP but I've always had troubles with connection between servers like "post". I have a FLAC audio file that I need to post to Google's Speech Recognition API server. I don't know neither how to "listen" to its response. I would like a script like that, assuming that this kind of function exists :
<?php
$fileId = $_GET['fileId'];
$filepath = $fileId . ".flac";
recognize($filepath);
function recognize($pathToFile) {
//It's the following function that I'm looking for
$response = $pathToFile->post("http://www.google.com/speech-api/v1/.....&client=chromium");
//The $response would be the short JSON that Google feed back.
echo $response;
}
?>
EDIT
I've followed a tutorial to create a Shell Script that posts my FLAC file using Wget --post. I would like to post like this, but in PHP. Also, at the end of the command, there is this > answer.ret line, so that Google's answer would be written to this file. I was wondering if there was an alternate method to it in PHP.
Here's the command line :
wget -q -U "Mozilla/5.0" --post-file audio1.flac --header="Content-Type: audio/x-flac; rate=16000" -O - "http://www.google.com/speech-api/v1/recognize?lang=fr-fr&client=chromium" > trancription1.ret
EDIT 2
I figured out how to do it, with #hakre 's answer and baked up a little Gist for curious people. Here it is: https://gist.github.com/chlkbumper/4969389. Don't forget that the FLAC file must be a 16k bitrate FLAC
A POST request is just a standard HTTP request, just with the POST method specified. The rest of the HTTP Request and HTTP Response is pretty much the same.
You get the response of a request in form of a HTTP Response btw.. It is absolutely normaltiv defined in RFC 2616 - just relate to this document and it explains everything.
A function in PHP to send HTTP requests is file_get_contents, it returns the requests response. This is done via the HTTP stream wrapper that offers some options you need to send a POST request (default is GET). See HTTP context options.
Another popular PHP extension for sending HTTP requests are the Curl bindings.
I am attempting to utilize the USPS API to do some address verification/validation.
I'm sending this XML to http://testing.shippingapis.com/ShippingAPITest.dll:
<AddressValidateRequest%20USERID="xxxxx"><Address ID="0"><Address1></Address1><Address2>6406 Ivy Lane</Address2><City>Greenbelt</City><State>MD</State><Zip5></Zip5><Zip4></Zip4></Address></AddressValidateRequest>
This is the same XML that is shown in their documentation for test requests. However, I always get an HTML (instead of XML) response that is a 501 Not Implmented error. Anyone familiar with this API know what might be going on? I'm using curl (in php) to make the request
UPDATE: When I make the request by typing the url into a browser with get params, it seems to work fine, but i get the error mentioned above using php/curl or just curl from the command line.
UPDATE: If I use file_get_contents with the url, I get a 400 bad request error - but if i urlencode, it works great - solution accepted.
Not familiar with the API, but:
Do you need the %20 after AddressValidateRequest? Does it work when that is replaced by a space?
Also, do you need to use CURL? Could you just use fopen() or file_get_contents() and then use the GET parameters which you mention work OK?