Response to request for resources related to a resource that doesn't exist

64 views
Skip to first unread message

Greg Williamson

unread,
Jul 16, 2015, 6:28:47 PM7/16/15
to api-...@googlegroups.com
Let's say I have a resource

    /providers/123

When a consumer sends a GET for that, it receives 200 OK and a record for the provider identified by 123, or a 404 Not Found if there is no provider with id 123. Fine.

Now let's say I have another resource

    /providers/123/publications

which represents a collection of publications authored by provider 123. When a consumer sends a GET for that:

 - If the provider exists and has some publications, they get 200 OK with the collection of publications.
 - If the provider exists and has no publications, they get 200 OK with a collection that is empty.

But what if the provider doesn't exist? 404? 200 with empty set? 200 with empty set and a warning? Something else?

Thanks!

Joel Pitt

unread,
Jul 16, 2015, 6:38:33 PM7/16/15
to api-...@googlegroups.com
I would expect a 404. :-)
> --
> You received this message because you are subscribed to the Google Groups
> "API Craft" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to api-craft+...@googlegroups.com.
> Visit this group at http://groups.google.com/group/api-craft.
> For more options, visit https://groups.google.com/d/optout.

Donghwan Kim

unread,
Jul 17, 2015, 12:49:29 AM7/17/15
to api-...@googlegroups.com
+1 for 404.

I think case A where the provider has no publications(tray) and case B where the provider has publications(tray) but there are no publication(fruit) are the same.

-- Donghwan

Donghwan Kim

unread,
Jul 17, 2015, 1:31:01 AM7/17/15
to api-...@googlegroups.com
You may want to see a similar discussion about that in this group - https://groups.google.com/d/msg/api-craft/wngl_ZKONyk/FRdIylojMlwJ

-- Donghwan

On Friday, July 17, 2015 at 7:28:47 AM UTC+9, Greg Williamson wrote:

Donghwan Kim

unread,
Jul 17, 2015, 1:33:14 AM7/17/15
to api-...@googlegroups.com
Oops sorry nevermind my answers. I've just misunderstood.


On Friday, July 17, 2015 at 7:28:47 AM UTC+9, Greg Williamson wrote:

Jack Repenning

unread,
Jul 17, 2015, 12:43:41 PM7/17/15
to api-...@googlegroups.com
On Jul 16, 2015, at 3:28 PM, Greg Williamson <gwill...@zephyrhealth.com> wrote:

But what if the provider doesn't exist? 404? 200 with empty set? 200 with empty set and a warning? Something else?

Mark me in the "404" column, too.

In fact, why would you think otherwise? The REST notion is that /providers/123/publications names a resource (a collection resource, in this case). Is there some way in which the collection /providers/123/publications could meaningfully exist when the provider /providers/123 does not?

I've seen cases that almost qualify, but the extraordinary circumstance of "publications" existing when "provider" does not have always revealed that the model's states need an overhaul.

For instance, suppose you're running a book store, the providers are publishing companies, and the publications are lists of books they've published. When a publishing company goes out of business, you might delete their provider entity, creating the difficulty you asked about with regard to their books still on  your shelves. But you'll still need to remember which books they formerly published: things like their warehouse of unsold books and their accounts-payable lists are tangible assets that don't evaporate: someone acquires the right to sell off the inventory and call in the payments; you may still need to know how to order one more copy of some book, and your accounts-payable software may need to know where to send that final check. So the addressing conundrum reveals a deeper one: you were too hasty in deleting /providers/123. You should keep the provider record, but mark it "defunct", or something like that. Now the provider resource still exists, there's no difficulty in defining and using /providers/123/publications, and other corners of your code are probably easier, too.

-- 
Jack Repenning
Repenni...@gmail.com

signature.asc

Mike Kelly

unread,
Jul 19, 2015, 7:33:16 AM7/19/15
to api-...@googlegroups.com

Sent from my mobile


On 17 Jul 2015 17:43, "Jack Repenning" <repenni...@gmail.com> wrote:
>
> On Jul 16, 2015, at 3:28 PM, Greg Williamson <gwill...@zephyrhealth.com> wrote:
>>
>>
>> But what if the provider doesn't exist? 404? 200 with empty set? 200 with empty set and a warning? Something else?
>
>
> Mark me in the "404" column, too.
>
> In fact, why would you think otherwise? The REST notion is that /providers/123/publications names a resource (a collection resource, in this case). Is there some way in which the collection /providers/123/publications could meaningfully exist when the provider /providers/123 does not?
>

Technically, from a REST (or even www) point of view, the behaviour of a resource at one URL has no direct bearing on another; they are opaque identifiers and that applies even to these types of "nested" URLs.

REST pedantry aside: if the client is requesting a thing that's not there they should get a 404.

Cheers,
M

Greg Williamson

unread,
Jul 20, 2015, 1:07:26 PM7/20/15
to api-...@googlegroups.com
Seeing all these upvotes for 404, of course now in retrospect it seems silly to even ask.

So what do you guys think about this URI:

/publications?providerId=123

where that provider doesn't exist. Still 404? Or is it 200 with an empty set? I think the latter, and perhaps this is what was distracting/confusing to me.

Jack Repenning

unread,
Jul 20, 2015, 1:34:02 PM7/20/15
to api-...@googlegroups.com
On Jul 20, 2015, at 10:07 AM, Greg Williamson <gwill...@zephyrhealth.com> wrote:

So what do you guys think about this URI:

/publications?providerId=123

where that provider doesn't exist. Still 404? Or is it 200 with an empty set? I think the latter, and perhaps this is what was distracting/confusing to me.

200 + [].  Because the un-matching address term is in a query parameter, and queries in general can provide collections, it's easier on the client if the response is always a list  -- an empty list, in this case, since there are no matches.

For this specific request, the "consistency" case could go either way, but for the more general case it's clear that "queries return lists"

* GET /publications?providerId=123
* GET /publications?providerId=456&publicationData=2013-12-14&author=Whitfield

A rule like "queries return lists" is easier to remember and code than "queries return lists unless it's obvious from some prior knowledge that this particular case couldn't have multiple answers."

-- 
Jack Repenning
Repenni...@gmail.com

signature.asc

Manu Whig

unread,
Aug 5, 2015, 8:30:47 PM8/5/15
to API Craft
Agree with Jack's answer above. 

/providers/123/publications is referring to a predefined resource, accessed via a hierarchical URI. It could be empty, but if any link in the hierarchical URI is absent, the resource is absent.
/publications?providerId=123 is not a predefined resource. 

Follow on question:

What should /providers/123/publications/456 return if 
1. /providers/123/publications returns 200 with [] but
2. /publications/456 returns 200 with the publication ?

Basically /publications/456 exists, but is not associated with /providers/123

417? 404? 200 with []?

I am inclined to go with 417 (though not strictly as per the HTTP spec, it indicates that the precondition of publication:456 being accessible via provider:123 failed). Don't have a strong opinion about this currently.

Jack Repenning

unread,
Aug 5, 2015, 9:21:26 PM8/5/15
to api-...@googlegroups.com
On Aug 5, 2015, at 5:30 PM, Manu Whig <whi...@gmail.com> wrote:

Follow on question:

What should /providers/123/publications/456 return if 
1. /providers/123/publications returns 200 with [] but
2. /publications/456 returns 200 with the publication ?

Basically /publications/456 exists, but is not associated with /providers/123

417? 404? 200 with []?

I am inclined to go with 417 (though not strictly as per the HTTP spec, it indicates that the precondition of publication:456 being accessible via provider:123 failed). Don't have a strong opinion about this currently.

I'm still '200 + []' for this case as well.

Returning 4XX means something very close to "client-code bug." Unless there's some reason, in the larger context not described here, why asking for this publication is an actual bug, it just looks like a legitimate filtered query, with a legitimate empty result.

-- 
Jack Repenning
Repenni...@gmail.com

signature.asc

Jørn Wildt

unread,
Aug 6, 2015, 2:43:41 AM8/6/15
to api-...@googlegroups.com
Maybe I am only repeating what others have already said, but considering that URLs are supposed to be "opaque" identifiers without any semantics build into the URL structure I would ignore the actual structure and think of it like this:

1) If the concept is "search for items matching some parameters" and that search resource exists then always return 200 + array of items (and leave the array empty if no items are matching the parameters).

2) If the concept is "get a specific item" then return 200 if it exists or 404 if it does not.

3) If the concept is "search for items belonging to X matching some additional parameters" then return 404 if X does not exist and 200 + array of items (and leave the array empty if no items are matching the parameters).

Scenarios (1) and (3) are equivalent at some proper abstraction level, so its mostly a matter of mental image of the model - do we *require* that X exists and then find items related to X or do we just search for items where "belonging to X" is an optional parameter.

Usually we then encoded X as part of the hierarchical path and "parameters" as URL query parameters (or POST payload).

/Jørn



Reply all
Reply to author
Forward
0 new messages