Question

I developed a web-app sometime ago for licensing our software. This has customers, accounts, users and licences. A licence is assigned to a user and activated with a serial number. Licences are created as the output of processing a purchase-order, i.e. there isn't any direct way of POSTing a new licence.

I'm reading "RESTful Web Services" at the moment and contemplating how I would make it RESTful (HATEOAS also).

Most of the URL's I'm clear about, but there are some interesting actions needed on licences. The basic URL for a licence will be /licence/{licenceID}.

  • Assign an available licence to a user (done by support staff)
  • Release a licence from a user (put it back into the pool of available licences)
  • Activate a licence with a serial number, with a key generated in return
  • Reactivate a licence
  • Renew a licence to a new expiry date
  • Disable a licence: one-way only, not reversable. Licence still exists

Now, in REST I can only use standard methods and mustn't embed an action say "assign" into the URL. What I'm thinking is to pick out the parts of the licence I want to affect. This gives: -

  • List: GET /licences/
  • Get: GET /licences/{licenceID}
  • Assign: POST /licences/{licenceID}/assignee/{userID}
  • Release: DELETE /licences/{licenceID}/assignee
  • Activate: POST /licences/{licenceID}/serialNumber/{serialNumber}
  • Deactivate: DELETE /licences/{licenceID}/serialNumber
  • Renew: POST /licences/{licenceID}/expires
  • Disable: DELETE /licences/{licenceID}/enabled

My questions are: -

  • Is this URL scheme the "correct" or sensible good-practice way of doing it?
    • Or should I have a collection of "licence assignments" and "licence activations" (for example: /assignments/{licenceId}/{userId})
  • Am I missing something fundamental (maybe clear when I've finished the book)
  • Should the parameters (userId and serialNumber) be as path parameters or query parameters?
    • {userId} refers to a user on the system so that could be a path parameter
    • {serialNumber} is generated on the client (Java Swing) from it's own info (no central DB of serial numbers).

Many thanks!

Was it helpful?

Solution

  • List: GET /licences/

Fine, though I would use GET /licences myself :)

  • Get: GET /licences/{licenceID}

Looks good

  • Assign: POST /licences/{licenceID}/assignee/{userID}

I'd suggest this was counter-productive, unless licences are assignable to multiple licensees. Instead, I suggest

PATCH /licences/{licenceID}
{ assignee={userID} }

or

PUT /licences/{licenceID}/assignee
{userID}

Which to choose should depend on how often the assignee of a license changes. If frequently, use the latter option, if infrequently, use the former.

  • Release: DELETE /licences/{licenceID}/assignee

Good. If you use this though, then you should use the second of the two storage options given previously. If you chose the first one, then something like:

PATCH /licences/{licenceID}
{ assignee=NULL }
  • Activate: POST /licences/{licenceID}/serialNumber/{serialNumber}
  • Deactivate: DELETE /licences/{licenceID}/serialNumber
  • Renew: POST /licences/{licenceID}/expires

You can treat these three the same as you decide for assignee to make things easier for your clients.

  • Disable: DELETE /licences/{licenceID}/enabled

I suggest:

> DELETE /licences/{licenceID}
< 201 Created
< Location: /disabled-licenses/{licenseID}

The URI namespace /licenses would then map to your domain model licenses WHERE valid==true and /disabled-licenses would map to licenses WHERE valid==false. There's nothing wrong with that. Access to invalid licenses can then be restricted at the HTTP level (i.e. by URI path) rather than at the application level (by checking the field value in your database).

My questions are: -

  • Is this URL scheme the "correct" or sensible good-practice way of doing it?
    • Or should I have a collection of "licence assignments" and "licence activations" (for example: /assignments/{licenceId}/{userId})

Your suggested scheme is mostly good with some alterations.

  • Am I missing something fundamental (maybe clear when I've finished the book)

No, not really.

  • Should the parameters (userId and serialNumber) be as path parameters or query parameters?
    • {userId} refers to a user on the system so that could be a path parameter
    • {serialNumber} is generated on the client (Java Swing) from it's own info (no central DB of serial numbers).

Again, if a license only has one user ID and one serial number, then the values of those are resource properties and/or subresources. If modeled as subresources, they belong in the URI, if properties, then in the body.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top