Using 404 for resource response that may not exist - rest

I have a RESTful service using HAL links. There is a customer resource and a preferredCard resource. A customer does not always have a preferredCard selected.
As the user must be logged in there is no need to pass customer or card id we will pull it from their identity.
PreferredCard url: GET: <root>/<version>/preferredCard
I think I have two options.
1) Add a preferredCard link on the customer and return a 404 (NotFound) if there is no preferredCard, otherwise return the preferredCard resource.
2) Don't display a link to the preferredCard on the customer if one doesn't exist.
Any thoughts on what is best here. Worried that in the first option I am returning a 4XX when the client didn't really mess up
Thanks

I think you need to handle both situations.
If you know the user has no prefered card, don't give them a link to something that isn't going to work. Maybe give them an alternate link to select one.
Equally, if that URL can exist, the user could always come back to it later, even if it has been removed. In this case, you may want to consider a custom 404 pages. The 404 error would let the user know that the resource they wanted cannot be found, but you can still provide some content, perhaps something explaining what is going on (that there is no current prefered card) and offers some useful links, in this case a link to the page where they can create/select a prefered card.

If there is no preferredCard for the customer-resource, then you may want to serve a createPreferredCard or selectPreferredCard-link instead of just hiding the link to a 404.
This would look like a clean approach to me, since you are hiding stuff that doesn't work, but offer options.

Related

REST: nested resource url when you don't want the parent ID visible

I read that the route for getting a nested resource in REST should look like this
/articles/:articleId/comments
The owner (:articleId) of the child resource will be visible.
But what if you have an owner that you don't want the client to know about?
For example, let's say I have an app where users have anonymous posts. I wouldn't want other users to see the client fetching the post by /users/123/post/321 because users could identify who wrote the post from the id and it wouldn't be anonymous.
Is the id necessary? Is it ok to instead do /users/posts/321 if all posts have a unique id?
There are no actual requirements for the URL format. It can be whatever you'd like it to be.
If it were me, I would use simply /posts/321 and leave users out of it, since a particular user isn't specified in your URL at all. I think that's the clearest way to handle it in your case.

What should be the Rest URL for the action "Move the competitor from team1 to to team2"

I am looking for a good URL, following REST principes, to "Move the competitor from team1 to to team2
My first guess is :
/teams/{oldTeamId}/{newTeamId}/competitors/{competitorId}/move
But it doesn't look much like REST.
Should I break it into 2 basics calls ?
Remove competitor from team1,
Add competitor to team2,
Should I remove some data from URL and pass it into the body ?
I don't really know what to do for this one.
Think about how you would implement this API as a web site.
You would probably have a link to a form -- it might be a form where the competitor, old team, and new team are all blank, or it might be a form where the competitor and old team are pre-populated. Your consumer updates the default information in the form as required, and submits it.
Notice the first point (raised by Roman Vottner as well) -- your consumer doesn't need to look at the URL at all. The client knows the HTML form processing rules, so it can create the correct HTTP request without knowing anything about the domain.
The second point is that, since the client is just submitting the form to wherever the HTML tells it to, you can make that anything you want.
One of the interesting properties of HTTP is cache invalidation. See RFC 7234, any non error response to an unsafe request will invalidate all cached representations of one resource.
So you can choose which resource gets invalidated by specifying its URI as the target of the form. In effect, it gives you a mechanism for ensuring that a consumer can read its own writes.
So some reasonable choices for the target might be
/teams/{oldTeamId}
if the team roster is the most important thing. Or
/competitors/{competitorId}
if the resource that describes the player is what is most important.
I don't really know what to do for this one.
Concentrate on make it easy to use. Your resource model is not your domain model is not your data model.
It will likely be useful to watch Jim Webber's talk REST: DDD In the Large to get clearer insights into what your "REST" API should really look like.
To answer your questions, I would not break it into two calls, I would however take some data from that (GET) url and put it in the body of your request. The request would probably be a POST or PUT (or maybe even patch), but definitely not a GET since something is actually changing.
As for a solution, how about a POST request to a /transfer. After all you are (could be) creating a new transfer which takes for example the player, their new team and maybe their old team.
I would use URL to identify the resource which in this case seems to be a competitor's team.
So would
Make the url as /competitors/{competitorId}/teams
Make the call PUT
Have a body with newTeamId and if required the oldTeamId.

Restful API: Is it meaningful to send PUT without enclosed entity?

Consider the following scenario:
There are two existing entity: shopping card #1 and item #1. I want to add item #1 to shopping card #1. There are two possible ways to design a Restful api:
1:
Without body:
PUT http://myshoppingsite.com/api/shoppingcards/1/items/1
Host: myshoppingsite.com
2: With body (having enclosed-entity):
PUT http://myshoppingsite.com/api/shoppingcards/1/items/
Host: myshoppingsite.com
{itemId: "1"}
Actually, I cannot decide which one is better and is more meaningful in terms of restfulness. Any idea?
(Note: I believe the http method should be PUT because of idempotency, but this is not my question here.)
PS: The problem I have with the first design is that there is no such enclosed entity in the request. Linguistically put is a transitive verb, so I expect somebody puts something somewhere. I think the same story somehow is in the HTTP world.
PUT is a HTTP verb that is supposed to create or replace the target URI, so this makes your first option immediately wrong. This request should replace all the items in your shopping cart:
PUT http://myshoppingsite.com/api/shoppingcards/1/items/
Since you want to add something to your shopping cart, this is not an option. This leaves effectively two options. First: the common one:
POST http://myshoppingsite.com/api/shoppingcards/1/items/
POST can mean many things, but in the context of REST services it's often used to append something to a collection. However, you mention that you want idempotence. You have two options here, first you can still use POST and within the context of your API guarantee that the request will be idempotent. Using POST does not mean that it's per definition non-idempotent, it just means that the HTTP spec alone does not guarantee it. That does not prevent you from making the request idempotent.
The other option is indeed PUT:
PUT http://myshoppingsite.com/api/shoppingcards/1/items/1
Your have a concern with that though, because in the context of your API you say that the request body would end up empty.
The reason for this is that you attach special to the last /1 in the url, and I think this what's wrong. If you want to follow REST best practices, then urls should not have any special meaning.
I think a saner way to do this, if you insist on using PUT is to get rid of the notion of "an id". That concept only exists in your database and should not make its way to the API.
Instead, I imagine that your service has a list of products such as this one:
http://myshoppingsite.com/products/1
To add a product to a shopping cart using PUT, this request might look something like this:
PUT http://myshoppingsite/api/shoppingcards/1/items/[completely-arbitrary-string-or-perhaps-a-uuid]
Content-Type: application/json
{
"product" : "http://myshoppingsite.com/products/1",
"quantity" : 5
}
Personally, I would just use POST though.
Q: there should be some information about the product you are addisng, no? Yes and that information is part of Uril. Why is it bad?
I'm not saying it's bad, I'm saying it's not RESTful. Pick up any book about REST and you will see this confirmed. This might also be a good place to start reading more about what REST is:
http://martinfowler.com/articles/richardsonMaturityModel.html
I would personally say that very little people build true RESTful services. This is why I also want to specifically point out that I don't want to say this is bad or good for your specific API, it's simply not RESTful.
What if I don't care about these principles and want to keep my special-meaning url scheme?
Well that's a fair point, but then we've gone beyond the original question here. If you want to design an API where the last bit of the url is actually the 'representation' of the item in your shopping cart, then yes I agree that having it also in the body is redundant.
In that situation I'd say, keep the request body empty. Just don't call it REST I guess.

RESTful URL for search vs admin

I have a scenario where I have to either
Pull the data from backend as search
Pull the same data from backend to administrate
The URLs I am using are -
/cars
/cars/management
The search can be then subsequently filtered as
/cars?color=blue
The concern that I have is that management is not a resource - it is actually an action. The management page contains links for other functionality associated with car management [add a car/delete a car/list cars/modify cars etc]
Has somebody else faced this issue? Can you let me know your solution?
There is nothing wrong with having a management resource that is a page showing management options for cars. Just because "cars" is the only thing in your database doesn't mean that is the only resource you can present to the user. You could have a resource that is just a form to pick a color (that makes a POST or PUT to the car resource). You could have a resource that is just a form to fill out the address you want the car delivered to. You could have a resource that is just a check box whether you want leather seats or not. You can have as many resources as you like and that make sense, even if all the resources are are pages with forms or links back to the car resource.
Just don't put any verbs in your URLs. You should still be using state transfer using HTTP verbs to change the state of the resources. Don't have a link like
GET /cars/123/deleteCar
on the management page. Instead there might be a link on the management page that (probably using Javascript since browsers have poor native support for HTTP verbs) performs a HTTP request along the lines of
DELETE /cars/123
when the user clicks the link. Something like jQuery can help with that. So long as the management page is using the HTTP verbs to change the state of the resources you are following REST since HTTP is a REST constrained protocol. REST doesn't say don't have actions, it says the actions should be constrained to state transfer.
There is no such concept as a "RESTful URL";
There is no issue with your URLs(/cars, /cars/management)
"/cars/management" is valid resource and it is not an action at all.
The RESTfull way to do this is to use the same URL with different HTTP verbs:
GET /cars for search/listing.
POST /cars for insert.
PUT /cars?id=123 (or /cars/123) for update.
DELETE /cars?id=123 for delete.

Yet more questions on RESTful URIs

Numerical IDs vs names
As an example, which of these would you choose for identifying a single transaction, from a single bank account, for a single company:
/companies/freds-painting-ltd/accounts/savings/transactions/4831
/companies/freds-painting-ltd/accounts/1/transactions/4831
/companies/62362/accounts/1/transactions/4831
You idiot, something totally different! Crikey, did you even READ Fielding's dissertation?
Now, I think the 1st one is the most readable. If I have more than one company, or if I'm someone like an accountant managing multiple companies, it's immediately clear which company, and which account, I'm looking at. It's also more bookmarkable/emailable and would prevent 'fishing' for other companies by changing the company ID. I would want transaction IDs to be unique to an account (I.e. Both 'savings' and 'current' accounts could have transaction '1'
A 'company' will be my 'top-level', or 'first class' resource. Nothing at all would ever be shared between companies. As such, it would be the ideal candidate for a shard (or 'ancestor'/'namespace' in Google App Engine parlance). So I'd only have to worry about the account names being unique within one company. Every company could have an account called 'savings'.
Not sure what the situation in the rest of the world is, though LTDs or PLCs in UK would have a unique name, there could be many 'Dave's Window Cleaning' businesses (what's know as a trading name).
The business owner(s) could potentially opt for the top level /company/company-name URI to be public, and contain some basic details like their website, contact details etc, but everything below that would NEVER be accessible by search engines.
So my thoughts/concerns are:
1) Is it reasonable, when someone signs in to add their business, to say "Sorry, 'Dave's Window Cleaning' business is taken. How about 'Dave's Window Cleaning Portsmouth' (Having taken their location in another field)? My worry with this is that, for a more well known company, you're giving away the fact that they have an account with you. Or that someone could use that form to search for names. Perhaps not a biggie.
2) The size of the company name. Would it be reasonable for a name like 'Dave's Window cleaning, gardening, and loads of other stuff'? Thus creating a URL like 'daves-window-cleaning-gardening-and-loads-of-other-stuff/'
3) How to deal with someone changing their business name - I would approach it by creating a new company with that string ID, copying over everything, then deleting the old resource. The original URI would return 404 rather than redirecting - as you can't guarantee someone else won't want to take the now unused name, or even if more than one person has used the same name in the past.
4) Should the 'real' unique ID be an number in the back end, and for every request to be handled by first doing a query for what company ID this name actually related to.
5) The impact of searching for a transaction in the persistence layer.
6) The possibility of URL rewriting, but then that wouldn't work cleanly in GAE, nor would it solve the issue of ensuring company names are unique.
RESTful webservice vs RESTful website
So, we potentially have this lovely RESTful webservice that the latest snazzy iphone/android app can use (delusions of grandeur). But what about the main website itself? I note, right now, that the URL I see at the top of my page is not 'RESTful': /questions/ask is an action. There is no 'ask' resource on the server. It's more the state of the page, the preparation for POSTing to /questions/ - or if I'm editing, PUTing to /questions/{id}
I also note that Stackoverflow has URIs like /questions/362352/name-of-the-question, and that the latter part can be omitted, and one will be redirected to it.
Should I host a completely separate webapp that consumes my lovely webservice (from the same domain)? Do I even need a separate REST server, or can I rely on content negotiation (JSON/XML) and HTTP verb to select the right method (I'm using Jersey), and return the right representation?
So I could have /companies/aboxo/ return the whole HTML page (using stringtemplate.org) if it's a GET /,text/plain or test/html, and JSON/XML for others?
But what happens for 'add/edit/delete' transaction? Would GET / /companies/freds-painting-ltd/savings/transactions/?template=add be ok (or GET ../transactions/352?template=edit), and that would return the right HTML?
Thinking about this last detail is driving me mad for some reason.
Comments, suggestions, outright ridicule - all welcome!
Marcos
Rails solves the "id vs name" problem by displaying both in the URL but using only the id to actually identify eg:
/companies/62362-freds-painting-ltd/accounts/1-savings/transactions/4831
ie - for the ones that have a "pretty url" the function that generates your path write both the id and the name... but for your router, where relevant: you strip off everything thats not the id.
incidentally, it means your customer could actually write whatever they like into the URL and it'd make no difference:
/companies/62362-i_luv_blue_turtles/accounts/1-your_mum/transactions/4831
and your router still just sees:
/companies/62362/accounts/1/transactions/4831
:)
For a cannonical URI I suggest just /transactions/{id} as I presume the transaction knows what the company and account is. Therefore, #4 :-)
Is SEO a concern? I presume you don't want random folks off the internet googling for X company's transactions?! Therefore, I would just keep names (which may change) out of the URI.