So, I have a create method on Apigility to create a resoure which is basically a
POST /resources
{
<fields go here>
}
... and I was wondering how can I also have the option to create a list of these resources.
From what I can see these are my options:
replaceList: PUT /resources
patchList: PATCH /resources
but I'm not sure which kind of payload I should send. Should I send an array of resources or an object with an array of resources?
If you create a DbConnected Service, see this code https://github.com/zfcampus/zf-apigility/blob/master/src/DbConnectedResource.php.
This methods are not implemented by default.
If you create a code connected service, you can send any payload. The data will be parsed as a array to you make what you want.
I don't know the behavior of validation on these requests.
If you send a array of entities, the Apigility 1.0.4 will validate each entity (see this link), maybe you have to write especific validators to each HTTP METHOD, or relax the general validator (see this link).
This link has some suggest to your payload https://apigility.org/documentation/api-primer/halprimer.
In your case I would use a array.
Related
I am creating a REST API for the Order screen. I have methods:
GET /api/orders
GET /api/orders/{orderId}
I have some buttons on the Order page and I created few endpoints for that:
PATCH /api/order/buttons/mark-as-read
PATCH /api/order/buttons/change-status
Now I need to add the delete button. But I don't understand how to do that. I have 2 options:
DELETE /api/orders/{orderId} - but I should send 2 additional parameters in this request
PATCH /api/order/buttons/delete - I can send my DTO in the body, but it is not a REST approach.
I want to understand which type of request is used for the delete button in the REST context?
PATCH /api/order/buttons/mark-as-read
PATCH /api/order/buttons/change-status
These are a bit strange. PATCH is a method with remote authoring semantics; it implies that you are making a change to the resource identified by the effective target URI.
But that doesn't seem to be the case here; if you are expecting to apply the changes to the document identified by /api/orders/{orderId}, then that should be the target URI, not some other resource.
PATCH /api/orders/1
Content-Type: text/plain
Please mark this order as read.
PATCH /api/orders/1
Content-Type: text/plain
Please change the status of this order to FULFILLED
Of course, we don't normally use "text/plain" and statements that require a human being to interpret, but instead use a patch document format (example: application/json-patch+json) that a machine can be taught to interpret.
I want to understand which type of request is used for the delete button in the REST context?
If the semantics of "delete" belong to the Orders domain (for instance, if it is a button that signals a desire to cancel an order) then you should be using PUT or PATCH (if you are communicating by passing updated representations of the resource) or POST (if you are sending instructions that the server will interpret).
The heuristic to consider: how would you do this on a plain HTML page? Presumably you would have a "cancel my order" form, with input controls to collect information from the user, and possibly some hidden fields. When the user submits the form, the browser would use the form data and HTML's form processing rules to create an application/x-www-form-urlencoded representation of the information, and would then POST that information to the resource identified by the form action.
The form action could be anything; you could use /api/orders/1/cancel, analogous to your mark-as-read and change-status design; but if you can use the identifier of the order (which is to say, the resource that you are changing), then you get the advantages of standardized cache invalidation for free.
It's normal for a single message handler, which has a single responsibility in the transfer of documents over a network domain, ex POST /api/orders/{orderId}, to interpret the payload and select one of multiple handlers (change-status, mark-as-read, cancel) in your domain.
you offer to use something like this: PATCH /api/orders/{orderId} and OrderUpdatesDto as JSON string in the request body?
Sort of.
There are three dials here: which effective request URI to use, which payload to use, which method to use.
Because I would want to take advantage of cache invalidation, I'm going to look for designs that use: /api/order/{orderId} as the effective request URI, because that's the URI for the responses that I want to invalidate.
It's fine to use something like a JSON representation of an OrderUpdate message/command/DTO as the payload of the request. But that's not really a good match for remote authoring. So instead of PATCH, I would use POST
POST /api/orders/1 HTTP/1.1
Content-Type: application/prs.pavel-orderupdate+json
{...}
But you can instead decide to support a remote authoring interface, meaning that the client just edits their local copy of /api/order/1 and then tells you what changes they made.
That's the case where both PUT (send back the entire document) and PATCH (send back a bunch of edits) can make sense. If GET /api/orders/1 returns a JSON document, then I'm going to look into whether or not I can support one of the general purpose JSON patch document formats; JSON Patch or JSON Merge Patch or something along those lines.
Of course, it can be really hard to get from "changes to a document" to a message that will be meaningful to a non-anemic domain. There are reasons that we might prefer supporting a task based experience, but sending a task centric DTO is not a good fit for PUT/PATCH if you also want caching to work the way I've described above.
Is it possible to design this way.
Can put method retrieve the data?
HTTP does not stop you from doing so, but why would you?
To answer your question. Yes you can.
Any of of GET,POST,PUT,DELETE methods can return a Representation (Response Object)
No framework will stop you (Most).
Should I do that?
Well, These HTTP verbs are there for a reason. In other words, they describe what they do.
In case of PUT:
Client sends Representation to update existing one. Server returns either 200 with empty body / 200 with newly updated representation
Just to add, If you don't want GET to do what you trying to do, Use POST with some sensible URL
Unfortunately not,
officially the REST methods are
POST -> Create a new resource
GET -> (Read) Gets an existing resource
PUT -> Updates a resource or changes its status
DELETE -> Deletes a resource
More info here
I think this is a classic and typical question but I didn't find its answer.
In my knowledge, the POST method is used to send data to the server with request parameter in message body to make it secure. And GET method is to retrieve data with parameters in the URL.
But what I didn't understand is how the same api may have different behavior by just changing the method.
Here is an example. I use SoapUI 5.5.0, this is the link of the api: https://reqres.in/api/users/1
when I use GET method I get this:
{
"data": {
"id": 1,
"email": "george.bluth#reqres.in",
"first_name": "George",
"last_name": "Bluth",
"avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/calebogden/128.jpg"
}
}
and by changing only the method to POST, I get this:
{
"id": "244",
"createdAt": "2020-02-27T14:30:32.100Z"
}
(the id and date changes each time)
as described in this link https://reqres.in/ that it is creating an instance and we can add parameters..
BUT, can any one explain how is it technically possible to have different behavior with different methods on the same URL.
In my knowledge, the POST method is used to send data to the server with request parameter in message body to make it secure. And GET method is to retrieve data with parameters in the URL.
That's probably getting in your way.
HTTP Requests are messages; each message starts with a request-line
method SP request-target SP HTTP-version CRLF
The request-target identifies the target resource upon which to apply the request
The method token indicates the request method to be performed on the target resource.
You can think of it being like a function call
GET(target-resource)
POST(target-resource, message-body)
Or equivalently you can think of the resources as objects that share an understanding of message semantics
target-resource.GET()
target-resource.POST(message-body)
But what I didn't understand is how the same api may have different behavior by just changing the method.
The same way that an api can exhibit different behavior by just changing the request-target.
In HTTP, the request-line is literally human readable text that the server will parse. Having parsed the request-line, the server program can then branch to whatever code it wants to use to do the work, based on the values it found in the message.
In many frameworks (Spring, Rails) the branching logic is provided by the framework code; your bespoke handlers only need to be correctly registered and the framework ensures that each request is forwarded to the correct handler.
how is it technically possible to have different behavior with
different methods on the same URL
for the technical possibility, you can look at the spring framework's answer to this.
You can have a controller that is accessible on a single url but can contacted in four says, GET, PUT, POST, DELETE. To do this, Spring provides the annotations #GetMapping, #PostMapping, #PutMapping, #DeleteMapping.
All the requests are sent to the same url and Spring works out which method to call based on the verb.
In Restful APIs, verbs have very important meaning.
GET: Retrieve data
POST: Create a new entity with the request's body
PUT: Replace an entity with the request's body
PATCH: Update some properties of an entity with the request's body. A.K.A. Partial update
In your case, changing the verb from get to post has the effect of creating a new entity with ID 1. That's why you get a response with the newly created ID and a createdAt timestamp.
I am a newbie to the apigility code-connected service & was able to create a RESTful service with fetch and fetchall class method on the mapper file.
Can someone point me a good sample for insert (POST) data via REST service ?
Thank you,
Kevin
POST is going to be used for creating a new resource typically. This means that in your request you're going to want the following headers:
Accept: application/json
Content-Type: application/json
The first tells Apigility what sort of a response it is expecting. The second says that the data you'll be providing to the API will be in json format.
Apigility uses json or json+hal by default for a return and expects json for the incoming data.
When you're creating a new resource, typically you'll be persisting it in a database and as such the id of the resource will be generated by your code or database. The rest of the resource will be provided by the caller to the API. Example:
POST /api/user
{
"username": "kevin voyce",
"firstname": "kevin",
"lastname":" "voyce"
}
If you do this, you should see a response of something like
405 - Method Not Allowed
The body of the error should indicate that the method has not been defined. The error message is coming from the create method in the resource. Inside this method, you'll see an argument called $data which at this point will consist of a PHP stdClass with fields matching the stuff you passed in via the JSON body.
This is where the fields part of configuring your API in Apigility comes in. If you set up the names of the fields and put validators on the fields, Apigility will make sure that the fields that are passed in conform to and are valid according to these validators before the call is made into your API. The same applies to not just POST, but PATCH and PUT as well. This means that within your methods you don't have to worry that the input hasn't been validated (as long as you correctly configured your validators).
Let's suppose I have an Group of users and I want to add/delete users from the group. What I am confused about is what will be the best practice to design the urls. Here are the options
OPTION # 1
POST /groups/{groupId}/users -- The request body will contain the userId
DELETE /groups/{groupId}/users/{userId} -- The userId will be in the path and the request body will be empty
OPTION # 2
DELETE /groups/{groupId}/users -- The request body will contain the userId
POST /groups/{groupId}/users/{userId} -- The userId will be in the path and the request body will be empty
I believe both the answers are correct and I am guessing there is no right or wrong answer here, just personal preference.But I would like to know what is used wide-spread. I have been using OPTION # 1 because I read in some book (the name escapes me) that the data you are POSTing shouldn't be a part of the url while using DELETE there is no such best-practice restraint.
All inputs appreciated !
The first option is the most common, but that means nothing, since misconceptions about REST are widespread. As a matter of fact, #1 isn't REST at all, it's RPC pure and simple.
Adding a member to the collection can be done either through a POST to the collection /groups/{groupId}/users, with the location of the created resource returned in the Location response header, or through a PUT request to the final location /groups/{groupId}/users/{userId}. The POST should return a 201 Created response, and the PUT either that or 200 OK, if the resource already existed and was replaced by the new one.
To delete, the correct way is to use DELETE /groups/{groupId}/users/{userId}. It's not a matter of personal preference. POST is a method you use for operations that aren't standardized by the HTTP protocol. Simple deletion is standardized through the DELETE method. Implementing it through the POST method simply means you'll have to document that functionality, instead of relying on the standard itself. You'd use POST only if you are doing something fancy during the deletion, something that already requires the functionality to be documented.
The option 1 seems to be the most common one. I don't have the feeling that the option 2 is valid at all!