Kraal
Kraal

Reputation: 2877

What would be a valid REST approach for a file conversion service?

What would be an appropriate REST compatible approach that would allow a client to call a RESTful service in order to convert a (large) document to a target format ?

I was thinking about something similar to this :

  1. Client makes a POST on /conversion/request resource with conversion configuration (target type, secure key, notification resource URL in the form http://host_to_be_notified/notification/status/id) that will return a request id. The conversion request would be added to an internal queue and can be modified / deleted by the client as long as the conversion is not started.
  2. Once conversion is started the /conversion/request/id is deleted by the server
  3. Once conversion is done the server creates a /conversion/result/id (same id as above in 1) resource then does a PUT on the notification status resource (to set it to "ready" and providing the key) which will inform the client of the completion of its request
  4. When ready the client makes a GET on /conversion/result/id resource to obtain the converted document
  5. If the client went offline for any reason, he can try to retrieve the result as in 4. If the document is not ready, the client just has to wait for the notification to be sent.

However...

  1. Is it a valid approach ?
  2. should I forget about using REST and should I rather think about using SOAP (and have a blocking call, knowing that I would prefer avoiding blocking calls) or JMS (all approaches have their pros/cons, and one big cons against JMS in my context is that it would require the setup of queues for all clients which may be refused) (note: that's why I also added "SOAP" and "JMS" tags to this question)
  3. Any idea of how to improve the approach and what are the questions I should think about before going any further ?

Thanks in advance for your help !

Michel

Upvotes: 2

Views: 88

Answers (2)

inf3rno
inf3rno

Reputation: 26137

I would use only a single resource like this:

POST /conversion/ {meta} {attachment} -> 201 created {links: [{rel: "self", href: "/conversion/1"}]}

After that the conversion representation would contain properties an links like these in different states:

enqueued

{
    id: 1,
    status: "enqueued",
    links: [
        {rel: "self", href: "/conversion/1"},
        {rel: "remove", href: "/conversion/1"},
        {rel: "status-change", href: "/conversion/1/status/events"}
    ]
}

processing

{
    id: 1,
    status: "processing",
    percent: 99,
    links: [
        {rel: "self", href: "/conversion/1"},
        {rel: "status-change", href: "/conversion/1/status/events"},
        {rel: "percent-change", href: "/conversion/1/percent/events"}
    ]
}

complete

{
    id: 1,
    status: "complete",
    links: [
        {rel: "self", href: "/conversion/1"},
        {rel: "result", href: "/conversion/1/file"}
    ]
}

The status-change and percent-change could use SSE, polling or websockets to push the data back or trigger an update. Ofc. this is just a draft.

Upvotes: 0

Rob Conklin
Rob Conklin

Reputation: 9464

In the past I have dealt with this with a POST for the initial request, returning an URI with the location of the final doc as the payload. I then respond to GETS at that location with a HTTP 202 response until the processing is complete. When the processing is complete, I return HTTP 200, and the content. This minimizes the complexity for the client (it's a simple polling), and stays very in-line with HTTP semantics.

If you really want to implement a call-back method, you can, but it adds significant complexity, and I can't imagine that it simplifies things on the other end. The polling process gives them more freedom to either implement a try/wait-loop or dump the location to a table/queue for batch processing.

Finally, this method significantly simplifies error handling. You can always return a 500 error on the same GET that the client is making. You don't have to specify different call-backs for different error conditions (which ends up being a real pain-point for your API).

Upvotes: 4

Related Questions