REST API: How to search for other attribute - api

I use node.js as REST API.
There are following actions available:
/contacts, GET, finds all contacts
/contacts, POST, creats new contact
/contacts/:id, GET, shows or gets specifiy contact by it's id
/contacts/:id, PUT, updates a specific contact
/contacts/:id, DELETE, removes a specific contact
What would now be a logic Route for searching, quering after a user?
Should I put this to the 3. route or should I create an extra route?

I'm sure you will get a lot of different opinions on this question. Personally I would see "searching" as filtering on "all contacts" giving:
GET /contacts?filter=your_filter_statement
You probably already have filtering-parameters on GET /contacts to allow pagination that works well with the filter-statement.
EDIT:
Use this for parsing your querystring:
var url = require('url');
and in your handler ('request' being your nodejs http-request object):
var parsedUrl = url.parse(request.url, true);
var filterStatement = parsedUrl.query.filter;

Interesting question. This is a discussion that I have had several times.
I don't think there is a clear answer, or maybe there is and I just don't know it or don't agree with it. I would say that you should add a new route: /contacts/_search performing an action on the contacts list, in this case a search. Clear and defined what you do then.

GET /contacts finds all contacts. You want a subset of all contacts. What delimiter in a URI represents subsets? It's not "?"; that's non-hierarchical. The "/" character is used to delimit hierarchical path segments. So for a subset of contacts, try a URI like /contacts/like/dave/ or /contacts/by_name/susan/.
This concept of subsetting data by path segments is for more than collections--it applies more broadly. Your whole site is a set, and each top-level path segment defines a subset of it: http://yoursite.example/contacts is a subset of http://yoursite.example/. It also applies more narrowly: /contacts/:id is a subset of /contacts, and /contacts/:id/firstname is a subset of /contacts/:id.

Related

Algolia vue-instantsearch : disjunction between two distincts facets

Using algolia vue-instantsearch, i’m encountering a special case and i’m having an hard time finding a solution.
Refinement behaviors is that you get the results that matches all your refinement filters.
If i filter on a brand and a price, i’ll get the results that matches both the brand and the price.
I need to add some specific filters that work differently. I would like to be able to say “returns me the results that matches either refinementA, or refinementB, or refinementC.”
The reason is that those refinements are checking fields that are not present on all the products.
If i check a value for refinementA, i want to keep all the results that has no value for field corresponding to refinementA, but remove those that has a value for refinementA that does not match with the one i filtered one.
Im thinking about handling myself some inputs instead of ias-components, and modifying by hand each query that is send to algolia by checking the value of my own inputs when searchFunction is triggered (https://www.algolia.com/doc/api-reference/widgets/instantsearch/js/#widget-param-searchfunction).
I did not found yet how i can trigger a search from an non-vue-instantsearch input event, and i’m not sure how the above solution could affect the internal working of vue-instantsearch.
I’m looking for feedbacks about a more standard way of doing this, or for any advices !
I got the answer by exchanging with a vue-instantsearch maintainer.
vue-instantsearch does not provide any option to do it.
A workaround is to overwrite algoliasearch search method, that is used under the hood by vue-instant-search.
const client = algoliasearch('', '');
const originalSearch = client.search;
client.search = function search(queries) { ... }
More informations in this github issue : https://github.com/algolia/vue-instantsearch/issues/1102

MVC user's full name in Url, how to handle duplicates

I want to setup the following url in my MVC4 website, using the user's full name in the url:
http://www.myapp.com/profile/steve-jones
I have setup the following route in Global.asax:
routeCollection.MapRoute(
"profile", "profile/{userName}",
new { controller = "myController", action = "profile", userName = string.Empty
});
And I can take the parameter 'steve-jones' and match it to a user with matching name. My only problem though is, what if there is more than one 'Steve Jones', how can I handle this?
Does anyone know of a workaround/solution to this so that I can use a user's full name as part of the url and still be able to retrieve the correct user in the controller method?
Am I forced into including the user's id with the url (something that I do not want to appear)?
The usual way of handling this is by appending a number when creating the profiles. So if "steve-jones" is already a name in the database, then make the user's display name "steve-jones2". You basically have to insist that all profile urls are unique, which includes updating any existing database and account creation code.
Alternatively (and/or additionally), if two same names are found then have the script reroute to a disambiguation page where the user is presented with links and snippet of profile info of the many existing Steve Joneseses so they can go to the full correct profile.
Another way of handling it is by giving all user profiles an additional numeric code on the end. At my university all logins are based on name, so they give everyone pseudo-random 3-digit extensions so that they are safe as long as they don't get 1000 people with the exact same names :)
Some people might be happier being steve-jones-342 if there is no steve-jones or steve-jones1, if you're concerned.

How about using URI path variables for an HTTP POST?

I've searched a lot but I couldn't find the proper answer to my question regarding my conditions.
I'm building a REST API, and the case, which seems a border line case to me, is the following:
-I'm dealing with two entities, Users and Roles. An User can have multiple roles assigned.
-To assign a Role to a User, the Role must be already in the DataBase.
-To assign a Role to a User, the only thing needed is the 'code' of the role, that is a short string.
-The uri path template used now is:
--Users: localhost:8080/api/users
--Given User: localhost:8080/api/users/{userId}
--Roles of a given User: localhost:8080/api/users/{userId}/roles
Now, to 'link' a given User with a given Role, two options come to my mind.
-The first is the one that sounds as best practice in any scenario, sending the post data in the body, perhaps as a JSON.
-The other one, sending it through the uri and with an empty body. For example, to link User with id U001 with role R001, one would have to post to the following uri sending no data in the body: localhost:8080/api/users/U001/roles/R001
The thing is that I don't mind using the first option, and it seems to be the best and most correct one, but in this particular case, I'm not sure wether it is better to send an almost empty body (because it only holds the role id, a very short string) posting it to 'localhost:8080/api/users/U001/roles' or skipping the body and just sending the role id through the uri as a path parameter like localhost:8080/api/users/U001/roles/R001
Thank you all in advance for your help.
There is nothing wrong with putting role in the URI. Your intuition was on the right track. I'd do it this way.
PUT: locahost:8080/api/users/{userid}/role/{roleId}
And here's why.
FIRST: The PUT verb is Idempotent. In other words (taken straight from the spec)
... the side-effects of N > 0 identical requests is the same as for a single request.
Which is what I'd assume you want in this regard. You don't want multiple records in your state storage for each instance of user & role. A user should feel at ease making the same PUT request without adversely effecting (adding duplicate records) the system.
When doing the same thing with a POST I'd expect to have a new record created for every request.
SECOND: The PUT verb is supposed to identify a specific resource. (taken straight from the spec)
... PUT request identifies the entity enclosed with the request -- the user agent knows what URI is intended and the server MUST NOT attempt to apply the request to some other resource. If the server desires that the request be applied to a different URI,
it MUST send a 301 (Moved Permanently) response; the user agent MAY then make its own decision regarding whether or not to redirect the request.
What if role R102 becomes obsolete and R104 is preferred? Return a 301 (Moved Permanently) with a HEADER (Location : localhost:8080/api/users/{userid}/role/R104).
FINALLY: When everything works well. Return a 201 (Created) when created and a 200 (No Content) on every subsequent request to the same URI. If they provide a Role that is not in the system return a 501 (Not Implemented).
Hmm - in this case - a POST with a 302 may be a bit messy.
Why not a very simple 'PUT'/'DELETE' with indeed the URIs suggested ?
With simple; 20X meaning succeeded, possibly some 30X to indicate it was already there - and anything else a fail ?

Understanding RESTful. URIs for complex actions

I'm trying to build a RESTful service, and I've faced with some problems. I'll describe these problems (questions) with an example of an imaginary RESTful service.
For example, I need a "News" service on my site. News can be of different types: local news and global news. News are added by administrator. User can view both local and global news (separately or all-together). News are shown by pages. User can view the exact news.
So, I've built such a verb-noun table for this task:
GET /news - Get all news
POST /news - Create news
GET /news/{id} - Show the news with id={id}
PUT /news/{id} - Edit the news with id={id}
GET /news/{type}/{page}/{per_page} - Get news page #{page} of type {type}
GET /news/{page} - Get news page #{page} of both types
So, there are problems:
1) how to distinguish {page} and {id}? maybe {id} can be only number, but {page} - a string, started with 'p' (for example 'p1'}?
2) User can change the value "per_page" - how many news are shown on a page. Isn't it too complicated - /news/{type}/{page}/{per_page}? How it can be simplified?
3) How should be URLs in browser look like on this services? URLs won't be exact as URIs from table above?
For example:
/news - Viewing news (1st page with default 'per_page' and default 'type')
/news/{type} - Viewing news (1st page with default 'per_page' and type={type})
/news/{id} - Viewing exact news with id={id}
/news/{type}/{page}/{per_page} - Viewing exact page of news of exact type.
4) Additional functional. For example filter search ( getting news by date, author or title).
How to realize this with REST? How filter object (xml or json) should be transmitted? How to make URL of page with results of the filter? /news/{date:12.12.2012,author:'admin'} or something better?
Sorry for my rough English, If you see some grammar and etc mistakes - feel free to correct them.
Thanks in advance.
I'd say you should use regular params for the type, page and per_page. Type, Page and Per_Page do not represent unique Resources, but are rather filters to the collection of News Resources. So I'd do
/news
/news/{id}
/news?type={type}&page={page}&per_page={per_page}
Same for additional filtering.
Make sure to check out http://www.ics.uci.edu/~fielding/pubs/dissertation/evaluation.htm#sec_6_2
As Gordon wrote, you can use request params as normal. Remember that REST doesn't means only clean and nice urls.
So, leave ids and type parameters in uri, but pagination params add with query string.
Also, to distinguish different uri parts, you could use pattern used in Google's gdata i.e. params are preceded with name
/news
/news/id/{id}
/news/type/{type}
with some parsing on server side, you could add many parameters, optional parameters and not enforce exact ordering.

What is the maximum number of url parameters that can be added to the exclusion list for google analytics

I set up a profile for Google Analytics. I have several dozen url parameters that various pages use and I want to exclude. Luckily, google has a field you can modify under the general profile settings [Exclude URL Query Parameters:]. Of the several dozen items I have they are all working, and not being considered part of the URL. Except for the parameter propid
I added propid to the comma separated list on Monday. But, everyday when I check GA, sure enough they are coming through with that parameter still attached.
So, am I trying to exclude too many parameters? I couldn't find any documentation on GA's site to say there was a limit.
here is the exact content of the exclude URL Query parameter field
There reason there are so many is the bh before me didn't know the difference between get/post.
propid,account,pp,kw1,kw2,kw3,sortby,page,msg,sd,ed,ea,ec,sc,subname,subcode,sa,qc,type,code,propid,acct,minbr,maxbr,minfb,maxfb,minhb,maxhb,minrm,maxrm,minst,maxst,minun,maxun,minyb,maxyb,minla,maxla,minba,maxba,minuc,maxuc,card,print,year,type
update
I thought after more time had passed the "bad data" would fall of of GA. But as of yesterday it is still reporting on the propid querystring value despite adding that as well as other variables to the exclude list.
update2
I found this post on google https://www.google.com/support/forum/p/Google+Analytics/thread?tid=72de4afc7b734c4e&hl=en
It reads that the field only allows 255 char, Ok. Problem Solved. Except my field of values is only 247 charcters.. ARGGGHH!
*Update 3 *
So Here is the code I've added to the googleAnalytics.asp include page that goes at the top of everyone of my asp classic pages. Can anyone see a flaw in the design? I don't care about ANY query string info. (it could have been named *.inc, but I like having intellisense working)
<script type="text/javascript">
<% GAPageDisplayName = REQUEST.ServerVariables("PATH_INFO") %>
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-20842347-1']);
_gaq.push(['_setDomainName', '.sc-pa.com']);
<% if GAPageDisplayName <> "" then %>
_gaq.push(['_trackPageview','<%=GAPageDisplayName %>']);
<% else %>
_gaq.push(['_trackPageview']);
<% end if %>
(function () {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
Update 4
I'll only accept an answer if you will include something talking to the original question. My question was very specific, I wanted to know exactly the number of characters google allows. Everything I included in my original question body was simply to backfill the question to put everything in context.
Might I suggest an alternate solution to the reliance on manually excluding all of these (and feasibly any string ever used)?
I'd suggest passing a parameter to the trackPageView function to 'force' the recording of a manually/programatically set 'page name' value.
Whereas by default, GA records/defines a page based on a unique URL, the inclusion of a pagename parameter would associate all pageviews of a page with that parameter as pageviews to a single page.
For example, standard GA pageview code looks like this: _gaq.push(['_trackPageview']);, whereas the inclusion of a specific page name looks like this: _gaq.push(['_trackPageview', 'Homepage']);. With the latter, presuming that the homepage is at www.site.com, regardless of how that page is accessed GA will always consolidate all pageview stats for it as 'Homepage'. So, www.site.com/index.php, www.site.com/?a=b and www.site.com/?1=2&x=y will always report as 'Homepage' as if it was one page.
The only drawback here is that you need to be incredibly careful around any occurences of pagination, nested pages, content swapping, site search, or any functionality which may in fact rely on the use of query strings; you may need to consider some logic on how the page name values are output, rather than attempting to define on a per-page basis depending on the site of your site(s).
Hope that's helpful!
Do you realize that you have propid listed twice in the exclusion field? Once at the beginning and then again about one-third of the way through. That's the only thing that stands out to me. See what happens if you remove either of these.
You also have type duplicated, so if the above fixes the problem for propid, also consider removing the second type.
Google limits the characters in the "Exclude Url Query" field (2048 characters max), not the number of queries. I had the same issue you're having and what I discovered was that I had populated my query string parameter list based on the pagenames in my pages report. Well those pagenames first pass through a view-level lowercase filter that I have set up. And since the "Exclude URL Query" field is case sensitive, some of the parameters were getting through. Hopefully this helps.