Http GET and DELETE multiple entity requests at once (PHP) - php

As the title says - is it valid?
What do i mean
If i call an endpoint with GET
is it then valid to do
http://some.thing/more?id[]=12&id[]=4&id[]=65
to let the server return multiple entities at once?
I could not see any note about in the rfc docs. Also - looking at the status codes to return - it seems not build that way.
So i guess a GET or DELETE or HEAD request is for one entity only?
EDIT: language is PHP btw
EDIT2: this is what i want to avoid: https://stackoverflow.com/a/18141127/3411766
I dont want to use the body.

You can make valid HTTP requests but go against the design of HTTP. I'm focusing in my answer on correct HTTP design.
First, when you do a GET requests, you always receive a representation of a resource. Even if a URL represents something like a 'collection of resources', there is no strict definition of this in HTTP. That list of resources can still represent multiple 'entities' coming from your data-model.
So a call to /users can return multiple user-entities.
Similarly, a DELETE to users could mean that you are deleting the entire /users collection and everything in it.
One issue that I see, and don't have a great answer on is that you're using the the query string to delete multiple resources. I think this is fine for GET / HEAD, but I question whether it's correct for DELETE as well. It definitely feels a bit 'weird' to me because I feel that a DELETE on /users?foo=bar should delete /users and commonly it will due to how most frameworks work. Should it? I'm actually not sure. REST is not strictly a standard so we can't go and find answers there, so all I got is that it 'feels wrong'. I realize that you're not strictly asking for REST, so from a strict HTTP perspective it's definitely ok.
However, you could structure your urls to not look like:
/users?id[]=12&id[]=4&id[]=65
but instead something like this:
/users/12,4,65
I've seen others do this, and it feels a bit less wrong to me. But this is mostly conjecture.
Regardless if you do a DELETE on multiple entities like that, the request should either succeed or do nothing at all. Partial success is not accepted, so you can just use the usual 200/204 response codes to indicate a successful delete.

Related

Should I use Put, Patch and Delete? I'm reading some stuff which makes me wonder if it's conventional to use them

Up until now I've used only GET and POST to do just about anything, however, it was brought to my attention that it would be better if I used Put, Patch and Delete as well. I've gone over them and realized how they would help me. For example my routes would look better as I'll have this:
Route::get('/image/{id}', 'PagesController#specificImage')->name('specificImage');
Route::delete('/image/{id}', 'ArtworkController#deleteImage')->name('deleteImage');
instead of this:
Route::get('/image/{id}', 'PagesController#specificImage')->name('specificImage');
Route::get('/deleteImage/{id}', 'ArtworkController#deleteImage')->name('deleteImage');
However, I've read some stuff which make me have doubts.
I've read that Apache ( which I'm using ) doesn't allow PUT and DELETE unless you make some changes to the htaccess file. I assume the reason for that is number 2.
I've read that PUT and DELETE are not secure.
I've read that HTML forms only allow GET and POST. I do know that you can bypass that using hidden input fields which have the method you want to use in their value but I still have to ask myself why is it forbidden to use PUT and DELETE by default.
What you should or shouldn't use comes down to your preferences in the end. The usage of HTTP methods can be considered quite opinionated. Also, there are quite some questions and resources out there.
But let me try to answer your questions to the best of my knowledge.
Request methods are specified in RFC 7231, section 4: Request methods
The request method token is the primary source of request
semantics; it indicates the purpose for which the client has made
this request and what is expected by the client as a successful
result.
As you've stated, you can neglect them and bind the purpose to the URL. It is up to your server side implementation whether you evaluate the request method and act upon it, but as you stated
For example my routes would look better as I'll have this
Regarding your (probably) most important question:
I've read that PUT and DELETE are not secure.
I can't verify that claim. The request method is just a simple header token of an HTTP request and doesn't change the behavior of request, nor does it affect the responder, if he doesn't evaluate it.
From my personal experience, a lot of small companies and developers don't use http methods, but only get and post, as they are the only methods supported by a default html form. This means, that if you want to send a PUT or DELETE, you have to take additional measures via javascript.
I've read that Apache ( which I'm using ) doesn't allow PUT and DELETE unless you make some changes to the htaccess file. I assume the reason for that is number 2.
In some apache default installations, PUT and DELETE need to be allowed explicitly. See this question for example. As to why it's not default, I can only assume that in many cases it isn't used anyway und reduces the amount of processed, but undesired requests.
Now regarding
I've read that HTML forms only allow GET and POST. I do know that you can bypass that using hidden input fields which have the method you want to use in their value but I still have to ask myself why is it forbidden to use PUT and DELETE by default.
HTML forms only support GET and POST. To bypass this, you can't use hidden input fields, which would just populate the request body, but have to use javascript and set the request method explicitly.
I've found this really good answer regarding the reason why HTML don't support PUT and DELETE.
Two takeaways:
caching is an issue as POST and GET should be cachable, but PUT and DELETE should not
nobody bothered specifying it comprehensively.
Long story, short
Usage of PUT and DELETE can help you in writing clean code and web interfaces. The help you by putting more semantic to requests.
Whether you use them or not is up to you. There are probably more websites ignoring them than using them, but with increasing size, the benefit will increase.

prestashop create and update resources via url webservice api

I (unfortunately) have to write a client application as front end to a prestashop powered web site. I'd need to perform all CRUD operations on resources via url webservice and I'm stuck on create and update. I was very surprise to find out how few examples are available on the web since prestashop is supposed to be a widely used cms. However, till now I came to:
GET http://www.myshop.com/api/myresource/id
to get xml for resource with given id or
GET http://www.myshop.com/api/myresource/?display=full&filter[field]=[value]
to filter results. I'm writing this just because I had to struggle with google to achieve this information, this filters stuff might help somebody in the future.
DELETE http://www.myshop.com/api/myresource/id
to delete a resource (I suppose filters work here too, but didn't try so far)
now, does somebody know how create and update resources? I tried
POST/PUT http://www.myshop.com/api/myresource/
giving couples of field - value in http request parameters with no luck, I'm getting internal server error. No, I have no direct access to the server so I don't know what error is thrown and I hope it can be solved without bother website maintainers, I'd like to save my ammunitions.
The only useful resource I found on the web is this one, I also looked among other question on SO and suggested links in those question was of no help.
If you edit your config/config.inc.php and add the following you will be able to see the errors in the Response (error) (1by1 which is very frustrating when you are trying to work out why create fails). Remember to comment out the line when you are done.
/*DEBUGGING ON*/
ini_set('display_errors', 'on');
You also need to make sure that you prepend the data in your POST/PUT operation with xml=<prestashop>......</prestashop> (I am using C# for my Client so this may not be required with PHP)
if you are using the ?schema=synopsis to get your blank one, make sure you go through any elements in the XML that are in there as placeholders and remove them.. Your (products) for example will be broken but kind of work if you don't.
I also added to my code that in the initial pass of the XML it completely walks the tree, looking for anything with the attribute not_filterable and removes those nodes (once again not much documentation available to know if this is the right thing to do).
EDIT: 1 other thing of note in and of the Language based elements, make sure you are using CDATA for the elements.
I have just succeeded with Generating my Products via performing this so I hope it's of help. I am yet to perform an Update of an existing.
UPDATE: I have since updated to 1.5.4.1 of Prestashop and started updating resource Products in my case
Update Resource
URI: http://site/api/products/1
Use Method = "PUT"
content type = "text/xml"
Make sure that you remove any elements that have 'not_filterable' attribute set. (I don't understand why, but it doesn't work if you don't)
Delete Resource
URI: http://site/api/products/1
Use Method = "DELETE"
content type = "application/x-www-form-urlencoded"
I found that you don't need any body so you can set ContentLength to 0 it seems. and probaly don't really need content type to be set either, but it works.
I found the answer in source code, prestashop/webservice/dispatcher.php, there was no need to set fields/values as http parameters but rather pass a whole xml, containing at least all required fields, if using a post to create a new record, or just the fields you want to be updated if requesting a put, so
http://www.myshop.com/api/myresource/?xml=myXmlString
If you look at the documentation, you can ask for a blank xml file with all fields the each ressource. You have to do :
http://mystore.com/api/[resource name]?schema=blank
Then if you need more informations about the fields (as some are mandatory), just do :
http://mystore.com/api/[resource name]?schema=synopsis

Correct headers for PHP RESTful Application?

Goal: A RESTful API
Question: Is the method I have below a true RESTful API or is it missing something like I was told?
This is a 3 part question..
Let's assume I have a PHP project that has an API that returns data in either XML or JSON formats, you would access the API like this below...
server.com/article/123 | Returns ID 123 using GET
server.com/article/new | Creates a new article using POST
server.com/article/123/edit | Edits an article with the ID 123 using POST
server.com/article/123/delete | Deletes article with ID 123 using POST
1)
I always read also that PUT should be used for editing objects, below I put the word POST as the user would send a POST to tht URI for the delete action, should I be using PUT in php by using something like this instead?
$_PUT  = array();  
if($_SERVER['REQUEST_METHOD'] == 'PUT') {  
    parse_str(file_get_contents('php://input'), $_PUT);  
}
2)
I was told in a question I wrote on SO a while back that this is similar to a RESTful API but that it is not, the answer I got was this...
In short, your service is not RESTful, but it is close. Rather than specify actions (edit, delete, ...) in URL segments, you will want to make use of HTTP verbs (GET, PUT, POST, DELETE).
Either the guy did not know what he was talking about or I just DO NOT GET IT, after reading countless articles on the subject, and comparing with every API I can find, how is my example above NOT RESTful?
I would like to make a RESTful API, please help me correct my example above if needed?
3)
Also assuming I plan returning a JSON response to the user with something like this...
<?php
header('HTTP/1.1 200 OK');
header('Content-type: application/json');
$data = // my code that returns the appropriate data;
echo json_encode($data);
?>
Is that the correct way of returning the result to a user or am I missing something?
Many articles and questions talk about the concept but don't get into the actual code like my examples.
To address part 2 of your question, a more RESTful URL and method structure would be as follows:
server.com/articles/123 – GET: return the article
server.com/articles/123 – PUT: replace the article with the one in the request body
server.com/articles/123 – DELETE: delete the article
server.com/articles/ – POST: create a new article
The idea here is that the URL represents the resource itself (in this case, the article) and the verb, where practical, indicates what you want to do to it. The best example I can think of in the wild of a true RESTful API is the latest version of the GitHub API: as far as I have seen, they use HTTP methods, response codes and custom MIME types appropriately.
In answer to part 3 of your question, that is certainly a valid way to do it, but if you were to use a custom MIME type such as application/vnd.myawesomesite.article+json, that would make it easier to interpret at the client’s end, as the client could use the MIME type to determine how to parse the result: for instance, the client could dispatch to different deserialisers and classes depending on the MIME type presented. Again, the folks at GitHub give some examples in their API docs.
You should be able to use $_POST on a PUT request, as long as the request includes a the proper Content-Type header. It's a generic superglobal that should always be filled when there is a HTTP body sent and the correct Content-Type header is used. In fact, it could even appear on a broken GET request.
Your URLs could be more RESTful. For example, server.com/article/123 could house not only GET, but also POST (edit) and DELETE (delete). There's no need to use separate URLs if you're already using different request methods.
RESTful primarily describes the way of communicating between the client and the server, not how it does that. I haven't seen the 201 header used much in the past - usually a 200 OK is good enough. Of course, nothing should stop you from using the 201 code.
#protip: wrap all your data in a result object, like {'success':true,'result':<the result>,'resulttype':'article'}. Developers using your API (if you publish one) will find this helpful. For you this means that you can add extra information to the response easily.
Very interesting article on FourSquare's REST API

Passing variable over to a new HTTP Request

As the title says, is there another way to pass a variable from "current" page over to "next" (new HTTP request) page without using sessions/cookies/$_GET?
Well, I guess $_POST could be an option too, but the thing here is, that I want to pass this variable from already executed $_POST back to off-the-post environment page, but inbetween I'm having a redirect, to disallow reposting the same form.
In other words, basicly, I'm trying to "make" a seamless PRG, but sessions/cookies/$_GET is not an option.
And yes, I'm working with classes (hence the oop tag). Therefore maybe some kind of magic functions, or output control?
This has to work within PHP environment, no JavaScript or other non server side language.
I also have a bad feeling that it's impossible, but hopefully I'm wrong, and there is a solution.
Thanks in advance!
update no. 1
Basicly, I want to create a PRG with response.
Inside this $_POST I'm adding data to database. I want this response to hold information whether this database query has been successful or not. Kind of make this $_POST process almost invisible to the user. And yes, display a response with the result later on.
All of this happens in one method:
if($_POST){
// insertion
}else{
// display no-post environment, if response exists (therefore posted) display response too
}
Something like that...
Sessions is not an option because this is meant to be some kind of API.
update no. 2
Huh, let me rephrase the question a little. Well, it seems that I don't actually need to pass the variable over. What I want to do, is to have 2 different results after POST so on next page load I could know whether the actions in POST has been successful or not. So, what other options are out there without using sessions/cookies/$_GET to get this result?
Currently there is:
temporary database usage: a good option, but I'd like to see different options;
Since you're already using a database it seems like the easiest way to handle this would be to update some kind of temporary table with the information you want based on the post call, then on the page you're doing a header redirect to, read the information in that table. With the constraints you've placed on this (no GET, SESSION, Cookie or Javascript) you're not going to be able to maintain a variable when you redirect from one page to the next.
So leverage that database and take the work off of PHP. Initially I was going to suggest utilizing cURL but I don't think that will help here (though you may want to look it up if you're unfamiliar with it, as it might be what you're looking for)
HTTP is a stateless protocol; thus, there's not going to be an easy, built-in way to add state. That said, I think sessions are the best way to accomplish what you want to do. If what you're doing isn't in the browser, maybe try some sort of session key setup (like the Facebook platform uses).

When the use of GET method is justified?

When the use of GET method is justified? Is it OK to always use POST? Is it right that GET is transferred fast then POST?
The GET verb is used in Requests that are idempotent, e.g. when they lead to the same result (and have no observable side-effects on the returned resource). So, you use them for retrieval of a resource only.
The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI. If the Request-URI refers to a data-producing process, it is the produced data which shall be returned as the entity in the response and not the source text of the process, unless that text happens to be the output of the process.
and also
1.3 Quick Checklist for Choosing HTTP GET or POST
Use GET if:
The interaction is more like a question (i.e., it is a safe operation such as a query, read operation, or lookup).
Use POST if:
The interaction is more like an order, or
The interaction changes the state of the resource in a way that the user would perceive (e.g., a subscription to a service), or
The user be held accountable for the results of the interaction.
However, before the final decision to use HTTP GET or POST, please also consider considerations for sensitive data and practical considerations.
See
http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html and
http://www.w3.org/2001/tag/doc/whenToUseGet-20040321
That second link explains the difference pretty well.
Note that there is not just GET and POST in the HTTP protocol, but a couple of other verbs, like PUT, HEAD, DELETE, etc as well. Those play a large role in RESTful applications.
Short answer:
Use GET requests when it makes sense for the user to be able bookmark the request, share the request, and come back to over and over again. It makes sense to be able to bookmark the result of a Google query, for example.
Longer answer:
Use GET requests when the user is simply fetching/viewing a resource, and doesn't have any significant side-effects on your website's data or on future requests. If the request is creating, modifying, or deleting something, it should be a POST. If the user is logging in to a website, that has effects on future requests, so it should be a POST, not a GET.
Note: Users can still change POST variables.
It's easier to for the user to change query string (GET) values, but it's not too difficult for the user to change POST values. Your website's security should take this into account! Using POST for security isn't really a valid reason, except for the fact that POST variables aren't part of the URL and aren't bookmarked, while GET variables are. This prevents users from accidentally sharing things like passwords when sharing links.
You use post for larger amounts of data, or data that you don't want to appear within the url. For instance, you don't want the url to delete a page, or create one, to appear in someones history. Neither do you want to save passwords in this way.
For search strings and such, you can easily use get. It allows users to copy a specific url, like a specific search reasult, or a link to the 5th page in a paginated list.
So, either are ok for their own purposes. The only thing you should remember is the maximum size of 8Kb for an url, including the get parameters.
GET is better for things that should be able to be bookmarked, and simple queries with few, short parameters.
POST is better for sensitive fields that the user shouldn't see, for large binary transfers, and for transfers with many fields or very long fields.
Generally, GET is preferred for search pages (like on google) and something which is not sensitive like username or password should not be shown in urls.
Consider Security Too:
You should be very selective when using GET for example if you end up coding like this:
$page = $_GET['page'];
include $page . '.php';
A bad guy can visit a url like:
http://www.yourdomain.com?page=../../../etc.pwd
Or if you do:
$id = $_GET['id'];
mysql_query('delete from table where id = $id');
A bad guy can delete all your records from db just by visiting:
http://www.yourdomain.com?id=5
http://www.yourdomain.com?id=10
There do exists solution to those mistakes however but still you should be selective when choosing between POST and GET.

Categories