سؤال

I'm new to REST API, so I decided to get familiar with it by designing a small web service API. I have its design written down and would like you to review it. I feel like I have made some mistakes in designing it and understanding REST concepts, which I try to address with questions on my design at the very end. I'm mostly unsure about my use of URLs for the API.

The web service I try to design provides a way for a user to store key=value pairs, i.e. retrieve value knowing its key, update the value of an existing key and delete an existing key. The whole CRUD set of actions!

Here is what I have came up with.

Versioning

Since my API might evolve, I want a notion of API versions, so I have

GET api.example.com/supported-versions

Which returns a JSON list of integers denoting the API versions supported.

The API will be available at api.example.com/{VERSION}/ endpoint, e.g. api.example.com/1/ for the first version.

Key=value storage

GET api.exmaple.com/1/keys/{KEY}

Allows a user to get a value associated with a key KEY. The server responds with a status code (200, 404, etc.) and a text value on success, both encoded in JSON.


POST and PUT api.exmaple.com/1/keys/{KEY}?value={VALUE}

Allows a user to create/update the value associated with the key KEY. The server returns a status code (200, 404, etc.). VALUE is a text string.

DELETE api.exmaple.com/1/keys/{KEY}

Allows a user to delete a key=value pair with key KEY. The server Which will delete the key=value pair and return a status code (200, 404, etc.).


Let's imagine that there is an OAuth2 authentication set up, which is used for the up above POST/PUT/DELETE methods (but not GET anyone can GET, you don't need authentication for that), so there is a way to uniquely identify a user and keep track which key=value pairs belong to which user.

Now, I want an authenticated user to be able to get a list of all keys they have, so that they don't have to store this information on client-side in order to send DELETE or PUT request later.

GET api.exmaple.com/1/keys?page={PAGE}

This allows a user to get a list of all existing keys they have created. PAGE is an optional parameter. User can increase page count until the user gets an error status code. It returns a paged list of all existing keys a user have created and also a status code (200, 404, etc.).


Is there anything wrong with this API?

Should the first GET/POST/PUT/DELETE from Key=value storage section be on /keys/ or /values/?

Is it fine that the last "GET", the one which returns all keys a user has, is also /keys/?

هل كانت مفيدة؟

المحلول

Your solution is OK, save for a few things:

  1. Versioning REST APIs at the resource level is generally not a good practice, although this not necessarily a consensus view. See here for some comments and links to further discussion.

  2. To your second question, you could probably argue either way as to whether /keys/{id}/ or /values/{id}/ is correct, but my instinct would be to either use keys since it's the "parent" of the tuple, or I'd use an entirely different name such as /data/ or /elements/, or whatever it is these things actually represent.

  3. I would probably have different GET methods for the whole key-value dictionary, e.g. /keys/{id}/, and a separate resource for those for a particular user, e.g. /users/{id}/keys/{keyId}.

Finally, it's not great (although possible) to use query strings with POST/PUT/DELETE methods. It is a query string, after all. Instead, you could use POST /data/, and put the key-value pair as JSON data in the request body. See this question as well.

نصائح أخرى

When the REST service returns a list of resources, such as the user's keys or the available versions, return (json) structures that contain URLs to these resources. Google for "linked data" to see the benefits of this approach.

E.g. the request:

HTTP> GET /Data/Version=1/User=Kasper/My_keys

Would result in the response:

200

{ keys: 
   [ 
      { name: "SO_account",
        link: "http://api.example.com/Data/Version=1/keys/SO_Account
      },
      { name: "Facebook_account";
        link: "http://api.example.com/Data/Version=1/keys/Facebook_account"
      }
   ]
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى softwareengineering.stackexchange
scroll top