My HTTP API requires the frontend to pass an accountId on API calls due to the fact we support admin users who are not tied to a single account and could be querying any account.
Initially I implemented this as a header the issue here is that caching would not work.
The current implementation looks like api.com/endpoint?accountId=123 whilst this works well - I would like to understand if this is the correct approach when implementing a RESTful HTTP API.
UPDATE:
Based on a comment - this is for GET
IMO, you did things "the right way" (TM) by putting this information in a HTTP header -- that seems to be the correct place for this to live. However your caching system currently doesn't care about HTTP headers, so that leaves you with a practical problem (which doesn't really care about "the right way"). So...
Based on that, it sounds like you have two options:
Fix your caching to include specific headers as part of the cache key, or
Add relevant information to the URL for caching purposes
I'd suggest (1) where you update the cache key to be a hash of the URL + other relevant information that would result in a different result (in this case, the HTTP header including the account ID or session information). This allows you to keep putting information in the right place while also not causing issues for cached pages.
Of course this might not be possible, so the only practical solution I can offer you is (2) where you pull stuff into the URL in order to support caching. I think this is an anti-pattern, but it will get the job done.
Related
Say I'm creating a journaling application and I want users to be able to post entries to their journals.
I do not intend to ever allow a user (even a moderator) to post an entry in someone else's journal.
That said, are there any arguments for exposing the account or journal id in my endpoint path?
I would think that POST api/journals/postEntry would be sufficient as I can determine the user via access token or JWT token.
Can anyone think of arguments for providing the journalId in the path? EX: POST api/journals/{user journalId}/postEntry
Can anyone think of arguments for providing the journalId in the path? EX: POST api/journals/{user journalId}/postEntry
Short answer: it's a violation of the uniform interface constraint.
See Fielding, 2000.
What you are doing, in effect, is creating this little corner of the world where, instead of using the target-uri to identify a resource, you are instead using target-uri + token.
Which means that your thing doesn't use the semantics that the general purpose components in the world are expecting.
For example, when I copy the URI out of my user agent, and share it with someone else, that other person doesn't get the result I expect -- they end up looking at their view, not mine.
The fact that we can stick a URI in an email message and have it just work for the person reading the email is a really big piece in the adoption story.
Furthermore, the cache constraint in REST rather depends on being able to use the identifier as the primary cache key. So your bespoke identity mechanism has the potential to mess up caching.
IN PRACTICE: you are using HTTP, and HTTP has caching rules that prohibit sharing authenticated requests. So the caching issues mentioned above are purely theoretical.
Alternatives you might consider
You could arrange for /api/journals/postEntry to redirect to /api/journals/{userJournalId}/postEntry
You could use the Content-Location header to indicate that there is a more specific identifier for the current representation.
You can use the canonical link relation to help clients navigate to the preferred resource from the alternatives.
I'm trying to figure out best or common practices for API design.
My concern is basically this:
PUT /users/:id
In my view this endpoint could by used for a wide array of functions.
I would use it to change the user name or profile, but what about ex, resetting a password?
From a "model" point of view, that could be flag, a property of the user, so it would "work" to send a modification.
But I would expect more something like
POST /users/:id/reset_password
But that means that almost for each modification I could create a different endpoint according to the meaning of the modification, i.e
POST /users/:id/enable
POST /users/:id/birthday
...
or even
GET /user/:id/birthday
compared to simply
GET /users/:id
So basically I don't understand when to stop using a single POST/GET and creating instead different endpoints.
It looks to me as a simple matter of choice, I just want to know if there is some standard way of doing this or some guideline. After reading and looking at example I'm still not really sure.
Disclaimer: In a lot of cases, people ask about REST when what they really want is an HTTP compliant RPC design with pretty URLs. In what follows, I'm answering about REST.
In my view this endpoint could by used for a wide array of functions. I would use it to change the user name or profile, but what about ex, resetting a password?
Sure, why not?
I don't understand when to stop using a single POST/GET and creating instead different endpoints.
A really good starting point is Jim Webber's talk Domain Driven Design for RESTful systems.
First key idea - your resources are not your domain model entities. Your REST API is really a facade in front of your domain model, which supports the illusion that you are just a website.
So your resources are analogous to documents that represent information. The URI identifies the document.
Second key idea - that URI is used by clients to cache representations of the resource, so that we don't need to send requests back to the server all the time. Instead, we have built into HTTP a bunch of standard ways for communicating caching meta data from the server to the client.
Critical to that is the rule for cache invalidation: a successful unsafe request invalidates previously cached representations of the same resource (ie, the same URI).
So the general rule is, if the client is going to do something that will modify a resource they have already cached, then we want the modification request to go to that same URI.
Your REST API is a facade to make your domain model look like a web site. So if we think about how we might build a web site to do the same thing, it can give us insights to how we arrange our resources.
So to borrow your example, we might have a web page representation of the user. If we were going to allow the client to modify that page, then we might think through a bunch of use cases (enable, change birthday, change name, reset password). For each of these supported cases, we would have a link to a task-specific form. Each of those forms would have fields allowing the client to describe the change, and a url in the form action to decide where the form gets submitted.
Since what the client is trying to achieve is to modify the profile page itself, we would have each of those forms submit back to the profile page URI, so that the client would know to invalidate the previously cached representations if the request were successful.
So your resource identifiers might look like:
/users/:id
/users/:id/forms/enable
/users/:id/forms/changeName
/users/:id/forms/changeBirthday
/users/:id/forms/resetPassword
Where each of the forms submits its information to /users/:id.
That does mean, in your implementation, you are probably going to end up with a lot of different requests routed to the same handler, and so you may need to disambiguate them there.
Background:
I have a single page application that pulls data from a REST API. The API is designed such that the only URL necessary is the API root, ie https://example.com/api which provides URLs for other resources so that the client doesn't need to have any knowledge of how they are constructed.
API Design
The API has three main classes of data:
Module: Top level container
Category: A sub-container in a specific module
Resource: An item in a category
SPA Design
The app consuming the API has views for listing modules, viewing a particular module's details, and viewing a particular resource. The way the app works is it keeps all loaded data in a store. This store is persistent until the page is closed/refreshed.
The Problem:
My question is, if the user has navigated to a resource's detail view (example.com/resources/1/) and then they refresh the page, how do I load that particular resource without knowing its URL for the API?
Potential Solutions:
Hardcode URLs
Hardcoding the URLs would be fairly straightforward since I control both the API and the client, but I would really prefer to stick to a self describing API where the client doesn't need to know about the URLs.
Recursive Fetch
I could fetch the data recursively. For example, if the user requests a Resource with a particular ID, I could perform the following steps.
Fetch all the modules.
For each module, fetch its categories
Find the category that contains the requested resource and fetch the requested resource's details.
My concern with this is that I would be making a lot of unnecessary requests. If we have 100 modules but the user is only ever going to view 1 of them, we still make 100 requests to get the categories in each module.
Descriptive URLs
If I nested URLs like example.com/modules/123/categories/456/resources/789/, then I could do 3 simple lookups since I could avoid searching through the received data. The issue with this approach is that the URLs quickly become unwieldy, especially if I also wanted to include a slug for each resource. However, since this approach allows me to avoid hardcoding URLs and avoid making unnecessary network requests, it is currently my preferred option.
Notes:
I control both the client application and the API, so I can make changes in either place.
I am open to redesigning the API if necessary
Any ideas for how to address this issue would by greatly appreciated.
Expanding on my comment in an answer.
I think this is a very common problem and one I've struggled with myself. I don't think Nicholas Shanks's answer truly solves this.
This section in particular I take some issues with:
The user reloading example.com/resources/1/ is simply re-affirming the current application state, and the client does not need to do any API traversal to get back here.
Your client application should know the current URL, but that URL is saved on the client machine (in RAM, or disk cache, or a history file, etc.)
The implication I take from this, is that urls on your application are only valid for the life-time of the history file or disk cache, and cannot be shared with other users.
If that is good enough for your use-case, then this is probably the simplest, but I feel that there's a lot of cases where this is not true. The most obvious one indeed being the ability to share urls from the frontend-application.
To solve this, I would sum the issue up as:
You need to be able to statelessly map a url from a frontend to an API
The simplest, but incorrect way might simply be to map a API url such as:
http://api.example.org/resources/1
Directly to url such as:
http://frontend.example.org/resources/1
The issue I have with this, is that there's an implication that /resource/1 is taken from the frontend url and just added on to the api url. This is not something we're supposed to do, because it means we can't really evolve this api. If the server decides to link to a different server for example, the urls break.
Another option is that you generate uris such as:
http://frontend.example.org/http://api.example.org/resources/1
http://frontend.example.org/?uri=http://api.example.org/resources/1
I personally don't think this is too crazy. It does mean that the frontend needs to be able to load that uri and figure out what 'view' to load for the backend uri.
A third possibility is that you add another api that can:
Generate short strings that the frontend can use as unique ids (http://frontend.example.org/[short-string])
This api would return some document to the frontend that informs what view to load and what the (last known) API uri was.
None of these ideas sound super great to me. I want a better solution to this problem, but these are things I came up with as I was contemplating this.
Super curious if there's better ideas out there!
The current URL that the user is viewing, and the steps it took to get to the current place, are both application state (in the HATEOAS sense).
The user reloading example.com/resources/1/ is simply re-affirming the current application state, and the client does not need to do any API traversal to get back here.
Your client application should know the current URL, but that URL is saved on the client machine (in RAM, or disk cache, or a history file, etc.)
The starting point of the API is (well, can be) compiled-in to your client. Commpiled-in URLs are what couple the client to the server, not URLs that the user has visited during use of the client, including the current URL.
Your question, "For example, if the user requests a Resource with a particular ID", indicates that you have not grasped the decoupling that HATEOAS provides.
The user NEVER asks for a resource with such-and-such an ID. The user can click a link to get a query form, and then the server provides a form that generates requests to /collection/{id}. (In HTML, this is only possible for query strings, not path components, but other hypermedia formats don't have this limitation).
When the user submits the form with the ID number in the field, the client can build the request URL from the data supplied by the server+user.
I have recently started testing rest based web services. I am wondering what are common issues faced while testing them.
I generally look for
response status (http code is among 200/400/500)
response headers (cache control, response type, content length )
if expected fields / values are present in json response.
I want to know what else to look for and issues in general while testing rest based web services
This is actually a very broad question but, here are the things that I look for while testing rest API's:
Response codes, Response headers
Check if Authentication/Authorization is correct based on user privileges
Check to see if the supplied value can break the output
Intentionally pass different Data-Type values to see if proper handling is done or not
Use load testing tools to see how many concurrent requests an API can handle
Again these are just a few things that will depend on the type of API you are building. Feel free to add more as you progress.
There are many, but let me share a few that aren't even specifically API issues but a full API integration test will help find it.
We did an integration API test where a publisher's product listing endpoint was hit, and then we randomly picked 100 of those products. Every few weeks we would find a bunch of bad product ID's. How was it possible? They would update the database but the product listing endpoint was cached and had bad information for hours until it was refreshed automatically.
Another time we found an e-commerce company in Brooklyn that, on average, had 3,500 products out of their 50k+ were missing a category. This meant 3,500 products not showing up if you browsed by categories, and potential lost sales.
We have a whole case study of this stuff on our website. Weird and unexpected stuff happens all the time. Test for everything and catch as much as you can. Every object in the payload should be verified, it may seem like overkill but there are platforms that can do all that work for you.
Here are suggestions based on my experience while testing Restful APIs.
Make sure that you are validating proprietary headers if you are using with your APIs.
Confirm that you are including correct location header in the response so that Rest API caller can use that for verification or for subsequent calls.
Check that location header protocol is correct i.e as per your design. (http/https). It's very important for subsequent calls.
I'm in the process of developing a REST service that allows a user to claim their listing based on a couple of pieces of information that appear on their invoice (invoice number and billing zip).
I've read countless articles and Stack Overflow questions about when to use GET and when to use POST. Overall, the common consensus is that GET should be used for idempotent operations and POST should be used for operations that create something on the server side. However, this article:
http://blog.teamtreehouse.com/the-definitive-guide-to-get-vs-post
has caused me to question using GET for this particular scenario, simply because of the fact that I'm using these 2 pieces of information as a mechanism to validate the identity of the user. I'm not updating anything on the server using this particular method call, but I also don't necessarily want to expose the information in the URL.
This is an internal web service and only the front-end that calls the service is publicly exposed, so I don't have to worry about the URL showing up in a user's browser history. My only concern would be the unlikely event that someone gain server log access, in which case, I'd have bigger problems.
I'm leaning toward POST for security reasons; however, GET feels like the correct method due to the fact that the request is idempotent. What is the recommended method in this case?
Independently of POST vs GET, I would recommend NOT basing your security as something as simple as a zip code and an invoice number. I would bet on the fact that invoice numbers are sequential (or close), and there aren't that many zip codes around - voila, I got full access to your listings.
If you're using another authentication method (typically in HTTP header), then you're good - it doesn't matter if you have an invoice number if the URL, so might as well use GET.
If you're not, then I guess POST isn't as bad as GET in term of exposing confidential content.
There isn't really any added security in a POST vs a GET. Sure, the request isn't in the URL, but it's REST we are talking about here, and the URL wouldn't be seen by a human anyway.
You question starts with some bad presumptions. Firstly, GET is not just for any old idempotent operation, it is for GETting resources from the server; it just happens that doing so should be side effect free. Secondly, the URL is not the only way for a GET request to send data to the server, you can use a payload with a GET request (at least as far as HTTP is concerned, some implementations are bad and don't support this or make it hard). Third, as pointed out, you have chosen some terrible data fields to secure your access. Finally, you are using a plain text protocol any way, so what neither method really offers and better security.
You should use the the verb that best describes what you are doing, you are getting some information from the server, so use GET. Use some proper security, such as basic HTTPS encryption. If you want to avoid these fields 'clogging' up the URL, you can send data in the payload of the request, something like:
GET /listings HTTP/1.1
Content-Type = application/json
{ "zip" : "IN0N0USZ1PC0D35",
"invoice" : "54859081145" }