prestashop create and update resources via url webservice api - php

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

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.

Http GET and DELETE multiple entity requests at once (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.

REST Resource vs Services

I have created some code to make calls to an external API (that I did not create). However, it has been described as 'Service-centric', while REST APIs are 'Resource-centric'.
What exactly needs changed to turn this into a service based call? I don't understand what the difference is. I understand I need to use HTTP verbs but I thought I was doing that already with cURL. Is this possible with cURL?
The API I have been passed contains a bunch of resource URLs as an example;
GET http://api.privateservice.com/Person?ID=123
POST http://api.privateservice.com/Person/SaveDetails/123
Think of resources as nouns, ie objects or records in your database. Think of actions as verbs, ie function calls.
The first example is indeed resource-centric. It's GETting a resource of type Person identified by 123.
The second example is not resource-centric because it's essentially a function call. REST and HTTP already establish conventions for saving a resource. In this case you simply need to PUT to the resource's URL, ie the same URL you retrieved with GET.
So upload the JSON (or whatever format) using:
PUT http://api.privateservice.com/Person?ID=123
If you are only passing in a few attributes, not the whole resource, there's another standard for that, PATCH:
PATCH http://api.privateservice.com/Person?ID=123
BTW It's a bit cleaner to use http://api.privateservice.com/people/123 as the URL.

HTTP file post - where to begin

I am ordering products from a supplier using cURL. I have a choice of receiving the orders by email, fairly straight forward, or via HTTP. I want to use the HTTP delivery method to get the files delivered into a directory on my webserver. I have asked the supplier to tell me more about the requirements for the HTTP and they are unable to give detail. This suggests that it is something that can be setup entirely at my side, or they are not being forthcoming with information i will need. I have asked them for examples of what other people have provided for the HTTP parameter and they have given me some examples. Apparently most people have specified a URL to file level and not just directory level. E.g. http://www.domain.co.uk/directory/listenLandmark.asmx or .aspx or .ashx. there are also some .php which is good as that is what i want to use. Howeever, some have just given a directory level parameter.
I guess that if I use a php file, I will be able to handle the files delivered rather than just have to check manually to see if there is anything there.
Can somebody tell me what I need to do to get this started please. The supplier is getting a 500 server error when trying to send/post file to me. I have tried changing the permissions on a directory to allow public read and write and execute, but this has changed nothing and is presumably very bad practice anyway (??).
If somebody can give me a quick push in the right direction i would appreciate it (or is it the case that i need more information from the supplier before i can begin).
I'm not sure based on your description, but if you line of thought is that the url on your site they are making the http call to is where you want them to store files or anything like that, that almost certainly isn't the intended way for it to work.
That being said... I have no idea what service you are using, or exactly how they intend on it working. But based on what you are describing it sounds like they are using a webhook or interfacing in a similar way. I'm guessing they are either making a http post call with all of the data for the files they need to send you, or they are making a http call with a list of URLs you can download the files from.
Since they can't provide you with any documentation (this is a giant red flag by the way), if I were you I would first find out what URL on your site they are trying to hit. Once you find that out, then I would add a bunch of logging to see what headers, post data, and any query string they are sending. Once you have that data you should have a much better idea of how they are trying to interact with your site, and be able to make a game plan of how you will use that data to do whatever you need to do.
I hope that helps
Edit: (adding some example logging code)
You could do something like this to log your headers, get & post data, and any file upload.
<?php
$data = array("headers" => headers_list(), "post" => $_POST, "get" => $_GET, "file" => $_FILES);
$file = "/path/to/write/file.log.txt";
file_put_contents($file, json_encode($data));
?>
Then it json encodes all the data (you could convert it all to a string in a different way if you like), and logs it to whatever file you want it to. If you set $file = "debug.txt" it will just log to the same directory as the php file, or you can tell it to go to a specific directory if you like. Then you just have to analyze the data and see what/where they are sending the data.

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).

Categories