Time |
S |
Nick |
Message |
00:38 |
|
|
quimrstorres joined #rest |
01:07 |
|
|
gigo1980______ joined #rest |
01:14 |
|
|
quimrstorres joined #rest |
01:17 |
|
|
tbsf joined #rest |
01:29 |
|
|
tbsf joined #rest |
02:14 |
|
|
quimrstorres joined #rest |
03:02 |
|
|
tbsf joined #rest |
03:03 |
|
|
SupaHam joined #rest |
03:16 |
|
|
quimrstorres joined #rest |
03:30 |
|
|
daxim_ joined #rest |
03:30 |
|
|
FritzLakritz_ joined #rest |
03:31 |
|
|
upasana joined #rest |
03:33 |
|
|
SupaHam joined #rest |
04:00 |
|
|
StatelessCat joined #rest |
04:17 |
|
|
quimrstorres joined #rest |
05:18 |
|
|
quimrstorres joined #rest |
05:39 |
|
|
Devastator joined #rest |
05:46 |
|
|
Macaveli joined #rest |
06:18 |
|
|
quimrstorres joined #rest |
07:47 |
|
|
gigo1980________ joined #rest |
08:07 |
|
|
trudko joined #rest |
08:07 |
|
trudko |
Hi everyone I have question about rest API design. We have a screen with three different types of data , then we have filter for each of this data. These filters are comming from the backend I am curious if I should create REST API filters for it or create separate link for each filter. These particular filters arent used anywehere else and there are more types of filters around the app |
08:17 |
|
|
gigo1980________ joined #rest |
08:20 |
|
|
quimrstorres joined #rest |
08:27 |
|
|
graste joined #rest |
08:53 |
|
|
interop_madness joined #rest |
09:04 |
|
trygvis |
trudko: what are these filters? just names that the user can select from? |
09:33 |
|
|
DracoBlue1 joined #rest |
09:56 |
|
|
quimrstorres joined #rest |
10:08 |
|
|
nesselbosch joined #rest |
10:36 |
|
|
gigo1980________ joined #rest |
10:51 |
|
|
DracoBlue joined #rest |
10:53 |
|
trudko |
trygvis: there is also info about how many records |
10:53 |
|
trudko |
will be displayed if the filter is active |
11:03 |
|
trygvis |
right, but that is a part of the search result, right? like, it would contain the number of items, the used filters and item list? |
11:15 |
|
|
Devastator joined #rest |
11:25 |
|
|
Left_Turn joined #rest |
12:13 |
|
|
nesselbosch joined #rest |
12:51 |
|
|
tbsf joined #rest |
13:16 |
|
|
quimrsto_ joined #rest |
14:10 |
|
|
tbsf joined #rest |
15:13 |
|
|
gigo1980________ joined #rest |
15:16 |
|
|
tbsf joined #rest |
15:18 |
|
|
mooncup joined #rest |
15:45 |
|
|
eschmidbauer left #rest |
15:52 |
|
|
bluezone joined #rest |
16:01 |
|
|
tbsf_ joined #rest |
16:35 |
|
|
tbsf joined #rest |
16:44 |
|
|
quimrstorres joined #rest |
17:27 |
|
|
tbsf joined #rest |
17:45 |
|
|
quimrstorres joined #rest |
18:09 |
|
|
gigo1980________ joined #rest |
18:21 |
|
|
tbsf joined #rest |
18:21 |
|
|
tbsf joined #rest |
18:30 |
|
|
vkareh joined #rest |
18:46 |
|
|
quimrsto_ joined #rest |
18:50 |
|
|
DracoBlue joined #rest |
19:02 |
|
|
vkareh left #rest |
19:38 |
|
|
gigo1980________ joined #rest |
19:48 |
|
|
quimrstorres joined #rest |
20:25 |
|
|
quimrstorres joined #rest |
21:45 |
|
|
BlueProtoman joined #rest |
21:46 |
|
BlueProtoman |
Suppose I have a website where users can follow one another. Which should I prefer; PUT /user/follow/{someone}, or PATCH /user with a JSON data field containing {someone}? |
21:51 |
|
whartung |
kind of depends on how you're representing your resources, and how you expect them to be used. |
21:54 |
|
BlueProtoman |
whartung: We're using the Google App Engine datastore for our project. |
21:54 |
|
fumanchu_ |
I would PATCH user/follows/ personally |
21:55 |
|
whartung |
that would work too |
21:55 |
|
BlueProtoman |
Everything supports PATCH these days, right? |
21:55 |
|
whartung |
what you use for the backend is not germane to the problem -- resource representation and back end implementation are separate, disparate things |
21:55 |
|
whartung |
I don't :) |
21:56 |
|
BlueProtoman |
Gimme a couple minutes and I'll have a codified spec to show off |
21:56 |
|
fumanchu_ |
where do you want the user-agent to go to know when a follow has been added/updated? that's the URL you want to PUT/POST/PATCH to. |
21:57 |
|
BlueProtoman |
Probably won't navigate at all, that might be done through AJAX |
21:58 |
|
fumanchu_ |
I didn't mean to imply "browse to". Whatever URL is in the AJAX GET is the one you want to invalidate with your PUT/PATCH/POST |
21:59 |
|
BlueProtoman |
"invalidate" meaning "not return the same result as it did before"? |
21:59 |
|
whartung |
correct |
21:59 |
|
fumanchu_ |
right; bust the cache |
21:59 |
|
whartung |
si |
22:01 |
|
|
tbsf_ joined #rest |
22:12 |
|
BlueProtoman |
http://pastebin.com/prq4zbWD Initial thoughts? |
22:13 |
|
BlueProtoman |
This is for an art website where users can freely remix other people's work. I'm defining a RESTful API, and then building the user-navigable URL structure upon that. |
22:14 |
|
whartung |
so, you know, to be blunt, this is a bunch of URLs, whereas REST is more about specification of hypermedia. |
22:14 |
|
BlueProtoman |
whartung: Mind elaborating? |
22:14 |
|
whartung |
but as an aside, what is this "ninja" library? |
22:14 |
|
BlueProtoman |
whartung: Web framework for Java. |
22:15 |
|
whartung |
so, as much as I hate to use the Web as an anlogy for REST, it is a good analogy for hypermedia |
22:15 |
|
whartung |
Consider the amazon website |
22:15 |
|
BlueProtoman |
What about it? |
22:15 |
|
whartung |
if you look at the pages, you have links (like Shopping cart and check out and a zillion other things). |
22:16 |
|
BlueProtoman |
Right. |
22:16 |
|
whartung |
as a user of the application, that's how you approach it -- you look for actions that are useful for your use case, and you follow them |
22:16 |
|
whartung |
So, we all know about shopping cart and my wish list and check out |
22:16 |
|
BlueProtoman |
That we do. |
22:16 |
|
whartung |
but what we don't know, at lest I don't know, is we don't know what URLs are behind those links? |
22:17 |
|
whartung |
we have no idea |
22:17 |
|
whartung |
because the URLs are not the application, the link relationships are the application |
22:17 |
|
BlueProtoman |
Why wouldn't we know? Can't I just mouse over the URLs? |
22:17 |
|
whartung |
and that's what REST is about -- you have hypermedia representing your application state, along with links to operate and transform that state. |
22:17 |
|
whartung |
sure, you can, but do you care? |
22:17 |
|
BlueProtoman |
hm, good point |
22:18 |
|
BlueProtoman |
"Hypermedia" being "things the user actually sees"? |
22:18 |
|
whartung |
hyper media is annotated media |
22:18 |
|
whartung |
data + links |
22:18 |
|
whartung |
all of the user properties plus a link to UPDATEUSER and DELETEUSER and FOLLOWUSER and whatever else is relevent to your application |
22:19 |
|
whartung |
but for words, are not the urls themseleves, they're just the high level names the application provider provides |
22:19 |
|
whartung |
those words are documented in the Hypermedia specification for the application |
22:19 |
|
BlueProtoman |
Ok. So what about the GETs I have? |
22:19 |
|
BlueProtoman |
(or, rather, the things the GETs represent) |
22:20 |
|
whartung |
that way the consumer knows what links to follow when they want something |
22:21 |
|
whartung |
so what would be better to see is not some much "here's some GETs" but rather "Here's the some resources", the resource format, an exampke resource, and the list of possible links and what they do. |
22:21 |
|
whartung |
THEN you can create GET/PUT/POSTs etc out of that specification |
22:21 |
|
whartung |
because in theory, the consumer application doesn't need to KNOW any of these URLs, they're mostly provided to it save for a few "well know" urls |
22:22 |
|
whartung |
for example, you "type in" www.amazon.com, and then simpley "follow links" for all of the rest |
22:22 |
|
BlueProtoman |
So in practical terms, figure out what data the users of my website actually want, THEN construct the URLs around that? |
22:22 |
|
whartung |
yes |
22:22 |
|
fumanchu_ |
but after you've done that, come back to me and I'll give you practical reasons why the URL's do matter ;) |
22:22 |
|
whartung |
build the resources and the semantics surroundiing them |
22:22 |
|
BlueProtoman |
We've actually designed our data already. |
22:23 |
|
whartung |
yea, certainly -- I'm not saying they "don't matter" (they sorta don't) but rather, a list of URLs does not a REST application make |
22:23 |
|
BlueProtoman |
Our project is an art website where people can remix other people's work freely. So the two main important resources are the users and the works they create. |
22:23 |
|
BlueProtoman |
(Given my understanding of your description, at least) |
22:24 |
|
BlueProtoman |
Users will be able to like works and follow other users. They'll be able to look at general information about a user (read: profile pages, list of works, etc.) |
22:24 |
|
whartung |
how is that "remixing"? |
22:25 |
|
BlueProtoman |
whartung: *That's* not. *This* is: a user can remix another's work (non-destructively) to provide their own creative spin on it for any purpose. Parody, innovation, collaboration, annotation, etc. Almost like forking a repo on GitHub (except the changes are meant to stand out on their own and not be pushed back to the original) |
22:26 |
|
BlueProtoman |
"Remix" == "make changes" |
22:26 |
|
whartung |
but that's done all through a client application, your server doesn't do any "remixing", it simply saves and manages the underlying content and the relationships ("likes") between them |
22:26 |
|
BlueProtoman |
Right. |
22:28 |
|
BlueProtoman |
That is correct. |
22:30 |
|
fumanchu_ |
a few thoughts on your URL design: |
22:30 |
|
fumanchu_ |
1) I think you're going to find users/subscribed/{other} to be way too chatty |
22:30 |
|
fumanchu_ |
unless they have large payloads |
22:30 |
|
BlueProtoman |
fumanchu_: Also, this is just for the API on which I'm going to build the thing users will actually use in-browser |
22:31 |
|
fumanchu_ |
of course |
22:31 |
|
BlueProtoman |
Yep, just wanna make sure we're on the same page. Please, go on. |
22:31 |
|
fumanchu_ |
but you're going to be sad when user 1 follows users 1..10000000 and a client fetches users/subscribed/2, users/subscribed/3 ... users/subscribed/1000000 in series |
22:32 |
|
fumanchu_ |
better to have users/subscribed/ be a single catalog of whom they follow |
22:32 |
|
fumanchu_ |
with links to /users/2, etc |
22:33 |
|
fumanchu_ |
ditto for likes but squared |
22:34 |
|
fumanchu_ |
er |
22:34 |
|
fumanchu_ |
shouldn't those be users/{userid}/subscribed anyway? |
22:35 |
|
BlueProtoman |
fumanchu_: {user} will be a username, not an ID number |
22:35 |
|
fumanchu_ |
sure but the routes don't include that in your paster |
22:35 |
|
fumanchu_ |
paste* |
22:35 |
|
BlueProtoman |
OK. Fair. And pagination in API requests like this is a thing, isn't it? |
22:36 |
|
fumanchu_ |
it can be. I generally resist pagination, preferring to chunk by semantic boundaries rather than number-of-records-so-far |
22:36 |
|
BlueProtoman |
E.g. I won't *actually* get all the users (unless there are few enough), but maybe 10 or 20 at a time |
22:37 |
|
BlueProtoman |
As for that, yes it will be but "users/action" will modify the authenticated user who is making the request. I will add variants that generalize to any user...unless you suggest I just do that in the first place? |
22:37 |
|
fumanchu_ |
users/{name}/subscribed shouldn't return all the users. it should return *links* to all the subscribed users, plus just enough information for the client to decide which one they want to select if needed |
22:37 |
|
BlueProtoman |
I'm borrowing from GitHub's API, which does this |
22:37 |
|
BlueProtoman |
fumanchu_: Ah, yes, okay. Yeah, I can float that. |
22:40 |
|
fumanchu_ |
then PATCH that to alter |
22:40 |
|
BlueProtoman |
fumanchu_: So e.g. "/api/users/subscribed" will get everyone (or at least some subset of, or links to) the user making the request is subscribed to. "/api/users/{someone}/subscribed" would get everyone {someone} is subscribed to |
22:40 |
|
fumanchu_ |
to alter the membership, that is |
22:41 |
|
whartung |
that suggests that the client must PATCH with actual URLs, fumanchu_ -- and, most of the time, URLs should be in control of the server, not the client. |
22:41 |
|
fumanchu_ |
URL's are identifiers. It's up to the server to validate them. |
22:41 |
|
|
tbsf joined #rest |
22:42 |
|
BlueProtoman |
If I'm gonna PATCH, why not just send the usernames instead of full URLs? |
22:43 |
|
BlueProtoman |
Also, if I may ask, what's wrong with PUT/DELETE /users/subscribed/{other}, as GitHub does it? https://developer.github.com/v3/users/followers/#follow-a-user |
22:44 |
|
fumanchu_ |
you can send usernames if you like. you're going to return URL's to each user for a GET to the catalog, and I prefer the symmetry of PATCH sending the same format it receives. but up to you |
22:44 |
|
BlueProtoman |
Ah, right, symmetry, that makes sense. |
22:45 |
|
fumanchu_ |
the problem with PUT catalog/item instead of PATCH catalog/ is that the former doesn't invalidate cached copies of the catalog |
22:45 |
|
fumanchu_ |
so the same client that PUT catalog/item may then GET catalog and "where'd my new item go?" |
22:46 |
|
BlueProtoman |
fumanchu_: Why can't I invalidate the cache with a PUT? |
22:46 |
|
fumanchu_ |
PUT catalog/item invalidates cached copies of catalog/item only |
22:46 |
|
fumanchu_ |
that's just the way HTTP caching works |
22:47 |
|
fumanchu_ |
(most write-through caches work that way) |
22:47 |
|
BlueProtoman |
Does DELETE have the same problem? |
22:47 |
|
fumanchu_ |
there have been a *LOT* of people trying to work around that and cross-invalidate but it's better to let that constraint inform your URL design from the beginning in my experience |
22:47 |
|
fumanchu_ |
yep |
22:51 |
|
BlueProtoman |
So, what about this part of the HTTP spec? "A PUT request applied to the target resource can have side effects on other resources." |
22:51 |
|
BlueProtoman |
http://devdocs.io/http/rfc7231#section-4.3.4 |
22:51 |
|
BlueProtoman |
Can't such side effects include invalidating a cache? |
22:51 |
|
fumanchu_ |
in the Github design, it does have side-effects. but the user viewing a cached copy of the catalog won't see them. |
22:52 |
|
fumanchu_ |
and no, that's not what the spec is talking about |
22:52 |
|
BlueProtoman |
Wait, by "cache", you mean the *client* caching the response, right? (And not me, to save on GAE queries?) |
22:52 |
|
whartung |
no |
22:52 |
|
fumanchu_ |
you might be running Varnish etc on the server and construct some crazy cross-invalidation rule |
22:52 |
|
whartung |
intervening HTTP caches (which you have no control over) |
22:54 |
|
fumanchu_ |
and if you try to adjust the client-side cache you end up sending a bunch of Cache-Control: no-cache headers and there goes your caching and...wasn't using REST for scalability in the first place? |
22:54 |
|
BlueProtoman |
whartung: I don't understand, I thought that the server had to return a 304 before a client could whip out its cache? |
22:54 |
|
fumanchu_ |
better to accept the caching constraints and design with them rather than against them |
22:55 |
|
whartung |
a common scenario is client <--> local cache/proxy <--> internet <--> your application |
22:55 |
|
whartung |
by local I mean local to the organization where the client is, not necessarly the browser |
22:56 |
|
fumanchu_ |
actually internet <--> corporate proxy cache <--> browse cache <--> your app |
22:56 |
|
whartung |
right |
22:56 |
|
fumanchu_ |
browser* |
22:56 |
|
BlueProtoman |
So someone's office might return a cached response and their workstation is none the wiser? |
22:56 |
|
fumanchu_ |
yes! hooray scalable systems! |
22:56 |
|
whartung |
and neither is your application |
22:57 |
|
whartung |
who knows how much caching AT&T does, for example |
23:00 |
|
BlueProtoman |
So if there's possibly caching outside the user's purview, how does using a PATCH over PUT/DELETE resolve the issue of getting stale responses? |
23:01 |
|
whartung |
It's more a question of whether PATCH is being honored by legacy caches as an invalidating verb. |
23:02 |
|
BlueProtoman |
Huh? |
23:02 |
|
whartung |
by standard, when a cache see the PUT to the URL, it will invalidate anything that it's holding on to because of it (same with DELETE) |
23:02 |
|
whartung |
the question is whether the cache also treats PATCH the same way |
23:03 |
|
whartung |
an older cache may not be aware of PATCH |
23:05 |
|
fumanchu_ |
I haven't run into that recently |
23:05 |
|
whartung |
yea I dont know how pervasive it is any more |
23:05 |
|
fumanchu_ |
the point is not whether you PATCH or PUT, it's the URL to which you are sending the verb |
23:06 |
|
whartung |
yes |
23:06 |
|
whartung |
the key point being that it only invalidates the URL that it sees in the PUT |
23:06 |
|
fumanchu_ |
if you want GET <url> to be up-to-date, then PATCH/PUT to that same URL |
23:06 |
|
whartung |
right |
23:06 |
|
whartung |
lets say you have GET /parent and that brings back "everything" |
23:07 |
|
whartung |
but you also have PUT /parent/child to change a dependent of parent |
23:07 |
|
whartung |
when you do GET /parent, PUT /parent/child, GET /parent, that last GET may very well match the first GET and not "see" the PUT (becuase only /parent/child was invlidated, not /parent) |
23:08 |
|
fumanchu_ |
treat *every* other URL that might have received "side effects" as what Helland calls a "secondary index" http://www.ics.uci.edu/~cs223/papers/cidr07p15.pdf |
23:08 |
|
whartung |
oh -- ths is long :) |
23:08 |
|
fumanchu_ |
aw, we were just getting warmed up ;) |
23:08 |
|
whartung |
lol |
23:15 |
|
|
BlueProtoman joined #rest |
23:15 |
|
BlueProtoman |
Gah, Wi-fi suddenly crapped the bed. What did I miss? |
23:15 |
|
whartung |
just us lamenting your cowardly ways |
23:16 |
|
BlueProtoman |
Gimme a sec, logs |
23:17 |
|
BlueProtoman |
OK, so if older caches may not recognize PATCH, wouldn't that make the situation worse? |
23:18 |
|
BlueProtoman |
OK, I understand better, caching is done on a URL basis |
23:18 |
|
fumanchu_ |
I haven't found that to be a problem in the last 5 years at least |
23:20 |
|
BlueProtoman |
Bottom line: minimize the number of URLs I use so I can work with caching? |
23:20 |
|
fumanchu_ |
in this sense, yes |
23:24 |
|
BlueProtoman |
Ok. Now, here's another consideration; should I make it easy for users to be able to use my API directly in-browser? |
23:26 |
|
BlueProtoman |
Or is that just secondary? (If I prioritized in-browser usage then I couldn't rely on certain HTTP features as much) |
23:27 |
|
fumanchu_ |
secondary but not ignored |
23:28 |
|
fumanchu_ |
most of our devs have JSONView installed so they can click links and navigate the API a bit |
23:30 |
|
|
quimrstorres joined #rest |
23:36 |
|
fumanchu_ |
2. users/{name}/subscribed/ and users/{name}/subscribers. you really want one of those to be canonical and the other to be secondary, so don't implement PATCH for both. |
23:36 |
|
fumanchu_ |
see Helland again for the rationale |
23:41 |
|
fumanchu_ |
3. if you don't want to think so hard and would rather follow some simpler rules, use my https://bitbucket.org/fumanchu/shoji/src/tip/spec.txt?fileviewer=file-view-default media type ;) obey its constraints and you can hardly go wrong |
23:46 |
|
BlueProtoman |
fumanchu_: One is for anyone {name} follows, one is for anyone following {name} |
23:47 |
|
fumanchu_ |
right, I get that. but only one can be invalidated automatically. |
23:47 |
|
BlueProtoman |
Oh, wait, ok |
23:47 |
|
BlueProtoman |
I see |
23:47 |
|
BlueProtoman |
Yeah, I was only going to let one of them (probably subscribed) be changed directly |
23:48 |
|
fumanchu_ |
cool |
23:48 |
|
BlueProtoman |
Also, what's that you linked me to? Some JSON data exchange thing? |
23:49 |
|
fumanchu_ |
my media type |
23:50 |
|
BlueProtoman |
Wait, wait wait a second. Just had a thought regarding our original discussion re: caching...how long are responses usually cached for anyway? Minutes? Hours? Days? |
23:50 |
|
BlueProtoman |
(On the proxy/gateway side, that is) |
23:50 |
|
fumanchu_ |
there's no "usually". it's up to your servers to specify that. |
23:51 |
|
fumanchu_ |
the longer they are, the more efficient (and therefore scalable) your whole system is going to be |
23:51 |
|
fumanchu_ |
the fastest HTTP requests are the ones the browser never makes because they hit the local cache |
23:55 |
|
BlueProtoman |
There's surely *some* circumstances where it's more appropriate to do DELETE/PUT? |
23:56 |
|
fumanchu_ |
sure; when you have fewer, larger resources |
23:56 |
|
BlueProtoman |
Like if I'm updating a user as a whole (e.g. changing their bio), or updating a piece of artwork? |
23:57 |
|
fumanchu_ |
right. the design question then becomes which attributes of that object are in the entity and which are in the catalog, and which (hopefully 0) are in both. |
23:58 |
|
BlueProtoman |
So if I'm updating a *collection* (e.g. a list of likes), use PATCH? And when updating or removing a single resource (like a user, which has a fixed number of fields), use PUT/DELETE? |
23:59 |
|
fumanchu_ |
yes to the former |
23:59 |
|
fumanchu_ |
the latter can be PUT, but if you're updating a subset of fields, I still like PATCH |