POST Request twice - rest

How does doing the same post request twice create duplicate for the same resource.
From what I learnt and understood,
whenever someone does
POST api/users/reg
I must register the user and create the resource URL for the specific user.
Now if someone tries to register with same data on the given api, how is it supposed to create a duplicate resource. It would respond with an error showing that the username is already taken.

Rethink your API design. The resource type users may have many users with unique resource id.
api/users/reg/:userId
This way you can post any number of users given the id is different each time.

Related

What is the best way to implement checking whether a username is already registered on the client side, if I want to keep my API RESTful?

As the title suggests, I am looking to have the client be able to check whether a username or email is already registered before the user submits the registration form. I had considered using an API endpoint that would return true or false for a given username, but this seems more RPC than RESTful. Is it bad practice to have such an endpoint if the rest of my API is RESTful? If so, what would a RESTful approach to this situation look like?
A key concept in REST is that anything that can be named can be a resource; this includes procedures. If you want to have an endpoint that accepts a username in the request body and returns true/false that's perfectly fine.
Alternatively, you can (or may already) treat a user as a resource. Take the GitHub API as an example: you can fetch a user by sending a GET request to https://api.github.com/users/{username}. If the user exists, and therefore the username is taken, you'll get back 200 OK. If the user does not exist you'll get 404 Not Found.
If you want to check if a username has been taken you can just issue a request for that username and then check the response. If you choose this approach HEAD is the more appropriate method. HEAD is essentially the same as GET except that the response body is empty. Since you don't need the body to determine if the user exists you can save a tiny bit of bandwidth with HEAD over GET.
You could do a POST /registrations and return a 400 with validation errors array and just have client side logic filter that array for invalid username. In other words, no reason you can't hit the endpoint multiple times. This should help decouple your UX from your API.

REST API architecture

I just started to construct REST API refer to this guide.
It's my first time coustructing REST API architecture, so something ambiguous.
POST vs GET
Before learning about REST API, I choose POST when I don't want form-data being exposed(e.g. user's ID, password, phone number).
But in REST API, POST means 'create new resource' if what I learn is right.
If so, what is the proper method for following case :
'check user's ID is duplicate or not', 'find my id or password'
represent specific action
REST API guide says that use noun to represent.
I Usually named function or method by verb+noun combination(e,g, checkId, findPassword).
Then what is proper(or better) way to represent?
GET /user/check-id
GET /user/id/check
GET /user/id/duplicate
Take a look at the RESTful verbs. POST is definitely used to create something, and GET is a query. That being said, you are absolutely right that GET URL Parameters are often logged all over the place, and you should not use them in GET urls if they contain sensitive data.
To check if a user's ID is a duplicate, I'd do a POST with the user's ID, and return a HTTP 409 code if it already exists.
The find password is a different question. In short, don't do it. You should NEVER, EVER, EVER store a user's password in plain-text. Doing so is negligence in today's computing world. Resetting a password should involve creating a password reset request (A POST to a /user/id/reset), which results in a password request being sent via another channel, but never, ever return a password from a GET request.

Creating user record / profile for first time sign in

I use an authentication service Auth0 to allow users to log into my application. The application is a Q&A platform much like stackoverflow. I store a user profile on my server with information such as: 'about me', votes, preferences, etc.
When new user signs in i need to do 1 of 2 things:
For an existing user - retrieve the user profile from my api server
For a new user - create a new profile on the database
After the user signs in, Auth0(the authentication service) will send me some details(unique id, name and email) about the user but it does not indicate whether this is a new user(a sign up) or a existing user(a sign in).
This is not a complex problem but it would be good to understand best practice. I can think of 2 less than ideal ways to deal with this:
**Solution 1 - GET request **
Send a get request to api server passing the unique id
If a record is found return it
Else create new profile on db and return the new profile
This seems incorrect because the GET request should not be writing to the server.
**Solution 2 - One GET and a conditional POST request **
Send a get request to api server passing the unique id
The server checks the db and returns the profile or an error message
If the api server returns an error message send a post request to create a new profile
Else redirect to the home page
This seems inefficient because we need 2 requests to achieve a simple result.
Can anyone shed some light on what's best practice?
There's an extra option. You can use a rule in Auth0 to send a POST to the /users/create endpoint in your API server when it's the first time the user is logging in, assuming both the user database in Auth0 and in your app are up-to-date.
It would look something like this:
[...]
var loginCount = context.stats.loginsCount;
if (loginCount == 1) {
// send POST to your API and create the user
// most likely you'll want to await for response before moving on with the login flow
}
[...]
If, on the other hand, you're referring to proper API design and how to implement a find-or-create endpoint that's RESTful, maybe this answer is useful.
There seems to be a bit of disagreement on the best approach and some interesting subtleties as discussed in this post: REST Lazy Reference Create GET or POST?
Please read the entire post but I lean towards #Cormac Mulhall and #Blake Mitchell answers:
The client wants the current state of the resource from the server. It is not aware this might mean creating a resource and it does not care one jolt that this is the first time anyone has attempted to get this resource before, nor that the server has to create the resource on its end.
The following quote from The RESTful cookbook provided by #Blake Mitchell makes a subtle distinction which also supports Mulhall's view:
What are idempotent and/or safe methods?
Safe methods are HTTP methods that do not modify resources. For instance, using GET or HEAD on a resource URL, should NEVER change the resource. However, this is not completely true. It means: it won't change the resource representation. It is still possible, that safe methods do change things on a server or resource, but this should not reflect in a different representation.
Finally this key distinction is made in Section 9.1.1 of the HTTP specification:
Naturally, it is not possible to ensure that the server does not
generate side-effects as a result of performing a GET request; in
fact, some dynamic resources consider that a feature. The important
distinction here is that the user did not request the side-effects,
so therefore cannot be held accountable for them.
Going back to the initial question, the above seems to support Solution 1 which is to create the profile on the server if it does not already exist.

REST API Resource Naming Conventions - User or Users (pluralisation)

Long Version
For some, myself included, one of the most painful and headache causing parts of building a REST API is determining the name for each resource and the accompanying endpoints.
Whilst it is, of course, down to personal preference; there are certain things that are encouraged by the community. For example, most people, including me, will pluralise their resource names:
GET /notifications
POST /posts
However, there are cases where pluralising just doesn't seem correct. Consider the following example where user essentially represents the logged in user, not the entire users resource:
Endpoints only relevant to the authenticated user
// Phone Verification
POST /user/phone/request
POST /user/phone/resend
POST /user/phone/verify
// User creation based on authenticated and verified phone
POST /user
// Update authenticated user's profile
PUT /user
// Delete the authenticated user
DELETE /user
// Add/remove the authenticated user's profile image
POST /user/image
DELETE /user/image
// Update the authenticated user's device token
PUT /device/token
Endpoints that access the entire users resource
GET /user
GET /user/{id|self}
In the above example, to me, it feels like the singular user resource name is more suited given on the majority of the endpoints, user refers to the authenticated user, not the entire database of users. But, on the other hand, having GET /user return all users just seems plain wrong...
As a result, I am now torn between user and users - both have strong arguments either way as I see it but would very much welcome another person's opinion on the matter...
Short Version
TLDR - To put it simply, consider the following two endpoints:
// Get all users
GET /users
// Update the authenticated user's device token
PUT /user/device
Both of the above seem correct in my eyes. The problem with the above is that there is no way I am going to have both user and users, it has to be one or the other in my opinion.
The dilemma; Why would I use user when the resource refers to the entire users database? Why would I use users when the resource only refers to the authenticated user?
I cannot get my head around this one... Anyone got any thoughts on this? Or, even better, an alternative solution to my proposed endpoint structure?
Update
After some deep thinking, I have come up with an alternative solution to this but I am still not 100% sure on it as I am not overly keen on using the auth resource name.
Consider this:
// auth = authenticated user
// users = users collection
POST /auth/request
POST /auth/resend
POST /auth/verify
POST /auth
PUT /auth
DELETE /auth
POST /auth/image
DELETE /auth/image
PUT /auth/device/token
GET /users
GET /users/{id}
There are obviously different opinions on this matter, the answer below contains my personal views.
The bottom line is that it's all quite subjective and depends on the way one looks at a certain (type of) resource.
Why would I use user when the resource refers to the entire users
database?
In my opinion, you should never use singular for an endpoint that contains multiple resources.
Some people, however, argue that we should stick to singulars for all resources, mostly for the sake of simplicity and uniformity.
Why would I use users when the resource only refers to the
authenticated user?
You will find quite some different opinions on this, but the consensus and most widely adopted is generally to stick with plurals, except for resources that can only contain a single item (for example, a user profile only containing only one avatar).
Also, since using a singular form for the users resource wouldn't make sense following the above logic, we don't want to mix singular and plural names.
// Update the authenticated user's device token
PUT /user/device
You can interpret 'updating the authenticated user's device token' as follows:
Add a device token to a user entity of the users resource collection.
If your API supports view devices' data of other users, the API can be like /users/$user_id/devices
whereas, when you always have to get the current logged-in user's devices information, the API can simply be /devices (as current user is implied).
i.e IMO, wherever you have only 1 parent resource accessible (say in this case current user is always singular), you can skip that resource in the API URL.

user likes in a RESTful API

how do you handle a user 'liking' a post or object in a RESTful API so that they can only like it once? Do you create a many to many relationship and create an endpoint to check if a user liked the object for each object that you load? This seems very request intensive and I'm wondering if there is a better, established solution?
Assuming that the users must be authenticated to perform the request and the request contain all the details to be properly authenticated, you could consider the following approach:
POST /posts/:postid/likes: Records a like for the user in post with the given id.
GET /posts/:postid/likes: Returns a representation of all likes for the post with the given id.
DELETE /posts/:postid/likes/:userid: Deletes a like for the user in the post with the given id.