Curl, How to send list of strings using GET request? - rest

I want to send ['1', '2', '3'] as a GET request.
I thought GET request are used when you are retrieving data opposed to POST (when you are modifying/creating data)
Failing to google how to send list of strings with GET does make me wonder, if it's better to use POST here?

Once you intend to perform a GET request, you could send data in the query string using one of the following approaches:
curl -G http://example.org -d "query=1,2,3"
curl -G http://example.org -d "query=1&query=2&query=3"
Let me highlight that payloads in GET requests are not recommended. Quoting the RFC 7231:
A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.
Also bear in mind that GET requests shouldn't be used to modify resources: they are intended to be used for information retrieval only, without side effects. Having said that, GET is both safe and idempotent. You can see more details on these concepts in this answer.
If the data must be sent in the payload (and you intend to modify the resource) then stick to POST. Assuming your payload is a JSON document, you would have something like:
curl -X POST http://example.org \
-H "Content-Type: application/json" \
-d '["1", "2", "3"]'

If you want to send it in the body with curl you can call your service like this:
curl -X GET --data "['1', '2', '3']" "https://example.com/test.php"
For example in PHP you can read it from the read-only stream php://input
<?php
$get_body = file_get_contents('php://input');
A better way would be to assign the array to a parameter e.g. x:
curl -X GET "https://example.com/test.php?x[]=1&x[]=2&x[]=3"
In PHP you'll receive these values as an array in $_GET['x']:
<?php
print_r($_GET['x']);
Output:
Array
(
[0] => 1
[1] => 2
[2] => 3
)

Related

Dream factory call REST API and character parameter

Currently, I have a problem with Dream Factory REST API call, when a space is present into the API URL call.
I have a get request with a sort parameter that must to be send for SOLR server. This space I don’t know how it is converted, but it seems to arrive into not appropriate mananer.
curl -X GET
‘http://localhosts:81/api/v2/test/list/test?rows=10&sort=random_test%20desc’
-H ‘X-DreamFactory-Api-Key: e115f92d18ba58e9a29389’
-H ‘X-DreamFactory-Session-Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1’
SOLR need to have this sort parameter and the direction of the sort. So we provide the column to sort, space and the direction. When I execute this curl using Dream Factory api, then the space or the %20 character seems to be converted into other thing.
Is there someone knowing, if this is a Dream factory problem, or whether it is possible to make the call in another manner?
Finaly the solution that I found is to change the curl call in order to make POST request and to put the parameters with spaces into the -d parameter.
Here is the call working for our case :
curl -X POST \
'http://localhost:81/api/v2/test/list/test?rows=10' \
-H 'X-DreamFactory-Api-Key: e115f92d18ba58e9a2' \
-H 'X-DreamFactory-Session-Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJz' \
-d 'sort=random_test+DESC&fq=NAME:*ov*+OR+NAME:*a*'

How to use Matlab webread with 2 http headers

I need to do this GET call with matlab:
curl -X GET \
-H "X-Parse-Application-Id: my_AppKEY" \
-H "X-Parse-REST-API-Key: my_APIKEY" \
https://api.parse.com/1/classes/GameScore
(this is a basic request to parse.com)
In matlab 2014b I have the function webread which becomes a weboptions struct.
I think the correct way of setting a header for the request is like this:
myHeaders1 = weboptions('KeyName', 'X-Parse-Application-Id', 'KeyValue' , 'my_KEY')
The thing is... I can only set 1 header using this syntax. How can I set 2 or more headers to be used in webread?
You can either call curl from within Matlab if you load right library files or instead you can use urlread2

Matlab: using webwrite to send image through a simple REST API

I was trying to do image classification through a web at service at and
I had no problem to use curl to retrieve token:
curl -i -X POST -H "Authorization:MY Key" -F "image_request[image]=#/path/to/myimage" -F "image_request[locale]=en-US" https://api.cloudsightapi.com/image_requests
However, it is not successful when I tried webwrite, it returned "HTTP 400" error.
option=weboptions('KeyName','Authorization','KeyValue','mykey')
fid = fopen('/path/to/myimage');
img = fread(fid,Inf,'*uint8');
fclose(fid);
response=webwrite('https://api.cloudsightapi.com/image_requests',...
'image_request[image]',img,...
'image_request[locale]','en-US',option);
I guess it because the function webwrite in this format doesn't support "multipart/form-data" and I need change the media type. Then I tried to send data as an JSON object
option=weboptions('KeyName','Authorization','KeyValue','mykey','MediaType','application/json')
data=struct('image_request[image]',im,'image_request[locale]','en-US');
response=webwrite('https://api.cloudsightapi.com/image_requests',data,option)
But the field name in Matlab struct does not allow "[".
Any suggestion?

Unable to accept songs submitted to moderated group via SoundCloud API

I'm getting 404 when hitting url like this, (offc. with variables changed to proper values):
PUT https://api.soundcloud.com/groups/<group_id>/pending_tracks/<track_id>
Calling DELETE on that same URL works as expected, it rejects submission from group.
Requesting simple GET .../pending_tracks (no track-id at the end) works fine for me.
The tools I have used so far to test this are:
official PHP library (by mptre),
manually constructed cURL request,
cURL binary on windows
I couldn't find any info in SoundCloud API docs (or on the internet) how this API method should or could be used. Any chance someone could help me with how it is supposed to be accessed properly, these are the questions:
what is the correct url
if there should be any, what is expected as the query data
if there a query body and what is the format.
More details:
Calling PUT /groups/44/pending_tracks/99119291 returns 404, so I've figured
out, the track ID must be supplied some other way.
By digging trough the PHP wrapper and gathering pieces of info scattered
around the internet, I've found out that some PUT requests are complemented
with CURLOPT_POSTFIELDS and other have XML in their body. So far I went with
postfields approach.
My curl binary config looks like this:
--url https://api.soundcloud.com/groups/44/pending_tracks
--cacert cacert.pem
--user-agent PHP-SoundCloud
--header "Accept: application/json"
--header "Authorization: OAuth XXXXXXXXXXXXXXXXXXXXXXXXXXXX"
--request PUT
--data <!--read on please-->
The data section was tested with following strings, each time supplying as
a value track-id like this track[id]=99119291:
track
track[]
track[id]
track-id
track_id
trackid
approve
approved
approve[]
approve[tracks][]
approved[tracks][]
tracks[approve][]
tracks[approved][]
approve[tracks][][id]
approved[tracks][][id]
tracks[approve][][id]
tracks[approved][][id]
tracks[]
tracks[][id]
tracks[][track][id]
tracks[][track][][id]
group[][id]
group[approve][]
group[approve][id]
group[approve][][id]
group[approved][]
group[approved][id]
group[approved][][id]
group[track][approve]
group[track][approve][]
group[track][approved][]
group[track][approve][id]
group[track][approve][][id]
group[track][approved][][id]
group[track][id]
group[tracks][id]
group[track][][id]
group[tracks][][id]
group[tracks][]
groups[][id]
groups[approve][id]
groups[approve][][id]
groups[approved][id]
groups[approved][][id]
groups[track][approve]
groups[track][approve][]
groups[track][approved][]
groups[track][approve][id]
groups[track][approve][][id]
groups[track][approved][][id]
groups[track][id]
groups[tracks][id]
groups[track][][id]
groups[tracks][][id]
Needless to say, none of those worked, each time result was the same as if I was accessing API endpoint with a simple GET request.
I'm really tired of blindly poking the SoundCloud API.
I'm sorry for you pain with the API, I fully agree it deserves a lot more and better documentation.
Anyway, while it's unclear to me why it got implemented like this, you should be able to approve tracks by sending a PUT request to api.soundcloud.com/groups/:group_id/tracks/:track_id. I hope that helps.

Restful way for deleting a bunch of items

In wiki article for REST
it is indicated that if you use http://example.com/resources DELETE, that means you are deleting the entire collection.
If you use http://example.com/resources/7HOU57Y DELETE, that means you are deleting that element.
I am doing a WEBSITE, note NOT WEB SERVICE.
I have a list that has 1 checkbox for each item on the list. Once i select multiple items for deletion, i will allow users to press a button called DELETE SELECTION. If user presses the button, a js dialog box will popup asking user to confirm the deletion. if user confirms, all the items are deleted.
So how should i cater for deleting multiple items in a RESTFUL way?
NOTE, currently for DELETE in a webpage, what i do is i use FORM tag with POST as action but include a _method with the value DELETE since this is what was indicated by others in SO on how to do RESTful delete for webpage.
One option is to create a delete "transaction". So you POST to something like http://example.com/resources/deletes a new resource consisting of a list of resources to be deleted. Then in your application you just do the delete. When you do the post you should return a location of your created transaction e.g., http://example.com/resources/deletes/DF4XY7. A GET on this could return the status of the transaction (complete or in progress) and/or a list of resources to be deleted.
I think rojoca's answer is the best so far. A slight variation might be, to do away with the javascript confirm on the same page, and instead, create the selection and redirect to it, showing a confirm message on that page. In other words:
From:
http://example.com/resources/
do a
POST with a selection of the ID's to:
http://example.com/resources/selections
which, if successful, should respond with:
HTTP/1.1 201 created, and a Location header to:
http://example.com/resources/selections/DF4XY7
On this page you will then see a (javascript) confirm box, which if you confirm will do a request of:
DELETE http://example.com/resources/selections/DF4XY7
which, if successful, should respond with:
HTTP/1.1 200 Ok (or whatever is appropriate for a successful delete)
Here's what Amazon did with their S3 REST API.
Individual delete request:
DELETE /ObjectName HTTP/1.1
Host: BucketName.s3.amazonaws.com
Date: date
Content-Length: length
Authorization: authorization string (see Authenticating Requests (AWS Signature Version 4))
Multi-Object Delete request:
POST /?delete HTTP/1.1
Host: bucketname.s3.amazonaws.com
Authorization: authorization string
Content-Length: Size
Content-MD5: MD5
<?xml version="1.0" encoding="UTF-8"?>
<Delete>
<Quiet>true</Quiet>
<Object>
<Key>Key</Key>
<VersionId>VersionId</VersionId>
</Object>
<Object>
<Key>Key</Key>
</Object>
...
</Delete>
But Facebook Graph API, Parse Server REST API and Google Drive REST API go even further by enabling you to "batch" individual operations in one request.
Here's an example from Parse Server.
Individual delete request:
curl -X DELETE \
-H "X-Parse-Application-Id: ${APPLICATION_ID}" \
-H "X-Parse-REST-API-Key: ${REST_API_KEY}" \
https://api.parse.com/1/classes/GameScore/Ed1nuqPvcm
Batch request:
curl -X POST \
-H "X-Parse-Application-Id: ${APPLICATION_ID}" \
-H "X-Parse-REST-API-Key: ${REST_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"requests": [
{
"method": "POST",
"path": "/1/classes/GameScore",
"body": {
"score": 1337,
"playerName": "Sean Plott"
}
},
{
"method": "POST",
"path": "/1/classes/GameScore",
"body": {
"score": 1338,
"playerName": "ZeroCool"
}
}
]
}' \
https://api.parse.com/1/batch
Interestingly, i think the same method applies as to PATCHing multiple entities, and requires thinking about what we mean with our URL, parameters and REST method.
return all 'foo' elements:
[GET] api/foo
return 'foo' elements with filtering for specific ids:
[GET] api/foo?ids=3,5,9
Wherein the sense is the URL and the filter determine "what elements we are dealing with?", and the REST method (in this case "GET") says "what to do with those elements?"
Hence PATCH multiple records to mark them as read
[PATCH] api/foo?ids=3,5,9
..with the data foo[read]=1
Finally to delete multiple records, this endpoint is most logical:
[DELETE] api/foo?ids=3,5,9
Please understand I don't believe there are any "rules" on this - to me it just "makes sense"
I would say DELETE http://example.com/resources/id1,id2,id3,id4 or DELETE http://example.com/resources/id1+id2+id3+id4. As "REST is an architecture (...) [not] protocol" to quote this wikipedia article there is, I believe, no single one way of doing this.
I am aware that above is not possible without JS with HTML but I get the feeling that REST was:
Created without thinking of minor details like transactions. Who would need to operate on more then single item? This is somehow justified in HTTP protocol as it was not intended to serve through it anything else other then static webpages.
Not necessary well adjusting into current models - even of pure HTML.
As Decent Dabbler answer and rojocas answer says, the most canonical is using virtual resources to delete a selection of resources, but I think that is incorrect from a REST perspective, because executing a DELETE http://example.com/resources/selections/DF4XY7 should remove the selection resource itself, not the selected resources.
Taking the Maciej Piechotka anwser or the fezfox answer, I only have an objection: There's a more canonical way of pass an array of ids, and is using the array operator:
DELETE /api/resources?ids[]=1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d&ids[]=7e8f9a0b-1c2d-3e4f-5a6b-7c8d9e0f1a2b
In this way you are attacking to the Delete Collection endpoint but filtering the deletion with a querystring in the right way.
I had the same situation to delete multiple items. This is what I ended up doing. I used DELETE operation and the ids of items which were to be deleted were part of HTTP header.
As there is no 'proper' way to do this, what I have done in the past is:
send DELETE to http://example.com/something with xml or json encoded data in the body.
when you receive the request, check for DELETE, if true, then read the body for the ones to be deleted.