Which is the proper way of creating REST web services? - web-services

I have the following state machine and I want this:
create a new order
add items into it (listing is optional)
confirm order by calling finish
pay for it
send it
And this flow is controlled via a REST web service and I'm not sure which method follows the REST principles better.
I came up with two possibilities (numbers below correspond with numbers above):
the first one - operation is specified by the path
1.
POST /create HTTP/1.1
2.
POST /addItem HTTP/1.1
<data>
<itemId>123</itemId>
</data>
GET /listItems HTTP/1.1
3.
POST /finish HTTP/1.1
4.
POST /pay HTTP/1.1
<data>
<price>123</price>
</data>
5.
POST /send HTTP/1.1
the second one - operation is specified in the body
1.
POST / HTTP/1.1
<data>
<operation>create.new.order</operation>
</data>
- returns resId
2.
PUT /{resId} HTTP/1.1
<data>
<itemId>123</itemId>
</data>
GET /items HTTP/1.1
3.
PUT /{resId} HTTP/1.1
<data>
<operation>finish.order</operation>
</data>
4.
PUT /{resId} HTTP/1.1
<data>
<price>123</price>
<operation>pay.order</operation>
</data>
5.
PUT /{resId} HTTP/1.1
<data>
<operation>send.order</operation>
</data>
The second solution seems better but I don't know if I can specify an operation in the request's body - is it ok or not?
Also I'm not sure if I should use PUT or POST at 3 and 5 in the second solution because I don't really update the resourse, I just change the state machine's state.
If none of these is correct how should I do it?

How about:
POST /orders
From that you get back a 201 Created response, along with a Content-Location header which specifies the URL of the just-created order, something like /orders/2876276
ok, then to add an item to an existing order:
POST /orders/2876276
The message can include url-encoded form data, specifying whatever you'd like to add to the order.
Then,
GET /orders/2876276
...gets some representation of the order. You could do content-type negotiation to figure out whether to format it as json, xml, or whatever. The response message would provide all the information about the order that you wish to share with the requester. Date received, status, order items, and so on.
I don't know what FINISH is exactly, but from my naive view it is just a special kind of update to the order item, so that is just another POST with special form data. After a POST with finish, the response to a GET will include a special indicator stating that the order is "complete."
To handle the payment, you may just use another POST on the same order. If your design calls for tracking accounts receivable, then you may have another object entirely. In other words if there is not one payment per order, but if a customer gets billed monthly or on some other rhythm, then you would have another object category like /accounts/39839. But in the simple case you could just use the order object to track payment state.
So, POST to an order URL to provide credit-card or paypal information to obtain payment. Subsequently, a GET will retrieve a representation that includes the order has been paid for.
The "Send" is not an HTTP request, I would think. Send is something YOU do to fulfill the order after receiving payment. Perhaps some system in your shop can post to /orders/872872872 to mark it sent. Subsequently, a GET will retrieve a representation that includes the order has been shipped, with maybe a tracking number.
I would be careful about using PUT. PUT indicates a insertion of an entire object into a repository, and implicit replacement if the object already exists. But your model doesn't call for that. The order manager manages the order, and exposes a limited set of operations (create, add item, etc) on each order. Insertion of an entire order is not one of those operations. Therefore PUT seems like the wrong thing in your scenario.
PUT would be right if you were inserting a document into a repository. For example imagine an auction where you offer an item for sale. You might use POST to create the auction item, then receive /items/29829 as the URL for the item. Then a PUT might be used to add an image to the item being auctioned - you might PUT to /items/29829/mainImage or something like that. PUT implies you know the URL of the thing to which you are PUT-ting.
you asked:
I don't know if I can specify an operation in the request's body - is it ok or not?
HTTP has only a limiited set of verbs. Your "order" object has a variety of states. You need to map the HTTP verbs to the state transitions. It makes sense to use POST to the order object for each state transition or state change. You might think of this as specifying "an operation" in the request body, but to me it is specifying the details of the request in the request body. This is precisely what the request body is for.
For more background, check out How to get a cup of coffee.

Related

Headers is treated as Data in spreadsheet query through JS

I am trying to read data from Spreadsheet using google visualization query. i am sending axios request to my spreadsheet. after getting response the output shows 1st column as data itself instead of headers. I am sending axios request to url.
** let url = https://docs.google.com/spreadsheets/d/${id}/gviz/tq?tqx=out:csv&tq=${encodedQuery}&gid=${gid} **
What do I need to change to get all the headers as it should be or all as the data also works fine. is there something wrong with the spreadsheet. I have deleted my sheet and recreated but the problem persists
After going through 7 hrs of mental blowing up I have solution for the question for i have posted. The reson behind the error was simply bad (empty) assignments in the sheets. Generally if the first item in the sheet is empty then this becomes bad assignment in array and the query fails to detect the comman type of data. So it takes the headers as data. To avoid this always populate the first set of data in the sheet to make sure the query can detect the type of data and treat headers as headers and not data.

How does Web Source operation's URL Pattern get it's argument when it's assigned a parameter?

when you AutoREST-Enable a table through object browser> click table> REST tab, you will get a RESTful URI. If you then build a web source using that RESTful URI, you will get five operations - GET with a dot as URL pattern and GET, PUT, POST and DELETE operations with URL pattern has the value of :deptno. When you build a report with form on that web source you will find that all database operations work well, you can insert, update and delete through the form, and you can run the report to get all rows in the table. I need to know how the process work in the background? How the automatic row processing process knows which operation and handler to use? I know that Interactive Reports for example looks for the operation that have "Fetch Rows" it's database operation. So, I assumed that the Form's automatic row processing looks up for the Web source's operation with the database operation that relates to the process to be executed. For example, (correct me if I'm wrong) when clicking CREATE button, it denotes that an Insert process will happen, so, it will search for the web source's operation with the database operation "insert row", then it will find the handler that relates to the HTTP method attribute's value "POST". And the same goes for UPDATE and DELETE. I want to know if I am getting it right and I need to know how the URL Pattern gets it's argument for :deptno?
your understanding of the form region picking the Web Source Operation is correct. Within the Form Region, the name of the clicked button (:REQUEST) actually determines the DML operation (CREATE = Insert, SAVE = Update, DELETE = delete).
A :deptno URL parameter must also be created within the Parameters section of the REST data source. Once that is in place, you'll see the form region node in the Page Designer Tree having a Parameters node - there you can map the Web Source Module parameter to a page item, an application item or something else.
As already mentioned, the primary key values are special in a Web Source Module. In your case, the :deptno placeholder (as part of the URL) corresponds to the DEPTNO data profile column.
For the DML handlers (PUT, POST, DELETE) you don't need to define these as Web Source Module parameters, but the URL placeholders must match the column names in the data profile. This is by design - Web Source Modules are implemented to work this way.

Facebook graph api get posts after a certain post id

I am using facebook graph api where I periodically call: https://graph.facebook.com/cnn/posts?access_token=accesstoken
I don't want to get repeat posts the second time I make the call so I would like to filter the call to get anything after either a certain post Id or after a created_time. Is this possible?
I have tried using date_range= but it did not work plus it only allowed me to search by date but not time.
Use timebased paging: https://developers.facebook.com/docs/graph-api/using-graph-api/#paging
The correct parameter would be since and until. Just store the timestamp of the last post and use it in your next call.

Information of re-shared status

I am working with Facebook graph api for few days. I am trying to extract user's status and the information of reshared if any. I can easily find status of a user using fields=id,name,statuses query. But I could not find any information about re-sharing. I found a field of status sharedposts. But could not understand what it actually does. Can anyone enlighten me about how can I collect information about resharing (who reshared,when reshared,resharing location). I used user_status access token.
The sharedposts field applies to a status id. For example, the status id 10151794781777494 is from a status update by the TheKrazyCouponLady which has been shared 4 times. This query:
/10151794781777494?fields=sharedposts
Will return all the information about the users that have shared it. If you want to limit the returned fields to the name and id of the sharer, and the time and location it was shared, you could do this:
/10151794781777494?fields=sharedposts.fields(from,created_time,place)
Although I expect there won't be any location data most of the time.
To find the status id in the first place, you could just query the statuses field for a particular user. Again, using TheKrazyCouponLady (uid 255919387493) as an example:
/255919387493?fields=statuses
To get just the ids:
/255919387493?fields=statuses.fields(id)
As an alternative to that, you may want to consider querying the user's posts instead. The advantage to using posts, is that you can get back the share count for each post in that query.
/255919387493?fields=posts.fields(id,shares)
If the share count on a post is zero, then there is obviously no need to run another query to retrieve the users that have shared that post.
The downside of using posts is that the post id is slightly different from a status id. You'll see ids that look like this:
255919387493_10151794781777494
The first half of that string is the user id of the post owner. The second half is the actual status id. If you want to query the sharedposts field for the post, you first have to extract the second half (the status id) and use that for the query.
Having said that, it occurs to me that you could actually retrieve all the information you need in one go if you chain the statuses query and the sharedposts query together. For example, something like this:
/255919387493?fields=statuses.fields(id,message,sharedposts.fields(from,created_time,place))
That will return the status id and message text for each status from that user, and the user details, create time and location for each person that shared each of those statuses.
Even with paging, though, that is likely to be a fairly slow query, so I'm not sure if that's such a good idea. It's worth considering though.
According new version of API 2.1 and documentation from here
https://developers.facebook.com/docs/graph-api/reference/v2.1/post
there is a new edge called "sharedposts"
As described here https://developers.facebook.com/docs/graph-api/reference/v2.1/object/sharedposts
This reference describes the /sharedposts edge that is common to
multiple Graph API nodes. The structure and operations are the same
for each node.
This edge represents any posts where the original object was shared on
Facebook.
If the post type is photo sharedposts will return empty as the object is different to the postID
/317380948302131_847979698575584 => Object : 847979378575616
/317380948302131_847979698575584/sharedposts?fields=from,via
ObjectID will work as expected
/847979378575616//sharedposts?fields=from,via
The only problem if the object is a shared_post it will show all shares from the original post object too and no via node is present .
Just struggle around some time why the APi only sometimes return sharedposts

REST and Filtering records

I currently have a .NET method that looks like this - GetUsers(Filter filter) and this is invoked from the client by sending a SOAP request. As you can probably guess, it takes a bunch of filters and returns a list of users that match those filters. The filters aren't too complicated, they're basically just a set of from date, to date, age, sex etc. and the set of filters I have at any point is static.
I was wondering what the RESTful way of doing this was. I'm guessing I'll have a Users resource. Will it be something like GET /Users?fromDate=11-1-2011&toDate=11-2-2011&age=&sex=M ? Is there a way to pass it a Filter without having to convert it into individual attributes?
I'm consuming this service from a mobile client, so I think the overhead of an extra request that actually creates a filter: POST filters is bad UX. Even if we do this, what does POST filters even mean? Is that supposed to create a filter record in the database? How would the server keep track of the filter that was just created if my sequence of requests is as follows?
POST /filters -- returns a filter
{
"from-date" : "11-1-2011",
"to-date" : "11-2-2011",
"age" : "",
"sex" : "M"
}
GET /Users?filter=filter_id
Apologies if the request came off as being a little confused. I am.
Thanks,
Teja
We are doing it just like you had it
GET /Users?fromDate=11-1-2011&toDate=11-2-2011&age=&sex=M
We have 9 querystring values.
I don't see any problem with that
The way I handle it is I do a POST with the body containing the parameters and then I return a redirect to a GET. What the GET URL looks like is completely up to the server. If you want to convert the filter into separate query params you can, or if you want to persist a filter and then add a query param that points to the saved filter that's ok too. The advantage is that you can change your mind at any time and the client doesn't care.
Also, because you are doing a GET you can take advantage of caching which should more than make up for doing the extra retquest.