greptilian logo

IRC log for #rest, 2016-03-31

https://trygvis.io/rest-wiki/

| Channels | #rest index | Today | | Search | Google Search | Plain-Text | plain, newest first | summary

All times shown according to UTC.

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

| Channels | #rest index | Today | | Search | Google Search | Plain-Text | plain, newest first | summary

https://trygvis.io/rest-wiki/