Search code examples
restapi-design

Single endpoint instead of API - what are the disadvantages?


I have a service, which is exposed over HTTP. Most of traffic input gets into it via single HTTP GET endpoint, in which the payload is serialized and encrypted (RSA). The client system have common code, which ensures that the serialization and deserialization will succeed. One of the encoded parameters is the operation type, in my service there is a huge switch (almost 100 cases) that checks which operation is performed and executes the proper code.

        case OPERATION_1: {
            operation = new Operation1Class(basicRequestData, serviceInjected);
            break;
        }
        case OPERATION_2: {
            operation = new Operation2Class(basicRequestData, anotherServiceInjected);
            break;
        }

The endpoints have a few types, some of them are typical resource endpoints (GET_something, UPDATE_something), some of them are method based (VALIDATE_something, CHECK_something).

I am thinking about refactoring the API of the service so that it is more RESTful, especially in the resource-based part of the system. To do so I would probably split the endpoint into the proper endpoints (e.g. /resource/{id}/subresource) or RPC-like endpoints (/validateSomething). I feel it would be better, however I cannot make up any argument for this.

The question is: what are the advantages of the refactored solution, and what follows: what are the disadvantages of the current solution?

The current solution separates client from server, it's scalable (adding new endpoint requires adding new operation type in the common code) and quite clear, two clients use it in two different programming languages. I know that the API is marked as 0-maturity in the Richardson's model, however I cannot make up a reason why I should change it into level 3 (or at least level 2 - resources and methods).


Solution

  • Most of traffic input gets into it via single HTTP GET endpoint, in which the payload is serialized and encrypted (RSA)

    This is potentially a problem here, because the HTTP specification is quite clear that GET requests with a payload are out of bounds.

    A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.

    It's probably worth taking some time to review this, because it seems that your existing implementation works, so what's the problem?

    The problem here is interop - can processes controlled by other people communicate successfully with the processes that you control? The HTTP standard gives us shared semantics for our "self descriptive messages"; when you violate that standard, you lose interop with things that you don't directly control.

    And that in turn means that you can't freely leverage the wide array of solutions that we already have in support of HTTP, because you've introduce this inconsistency in your case.

    The appropriate HTTP method to use for what you are currently doing? POST


    REST (aka Richardson Level 3) is the architectural style of the world wide web.

    Your "everything is a message to a single resource" approach gives up many of the advantages that made the world wide web catastrophically successful.

    The most obvious of these is caching. "Web scale" is possible in part because the standardized caching support greatly reduces the number of round trips we need to make. However, the grain of caching in HTTP is the resource -- everything keys off of the target-uri of a request. Thus, by having all information shared via a single target-uri, you lose fine grain caching control.

    You also lose safe request semantics - with every message buried in a single method type, general purpose components can't distinguish between "effectively read only" messages and messages that request that the origin server modify its own resources. This in turn means that you lose pre-fetching, and automatic retry of safe requests when the network is unstable.

    In all, you've taken a rather intelligent application protocol and crippled it, leaving yourself with a transport protocol.

    That's not necessarily the wrong choice for your circumstances - SOAP is a thing, after all, and again, your service does seem to be working as is? which implies that you don't currently need the capabilities that you've given up.

    It would make me a little bit suspicious, in the sense that if you don't need these things, why are you using HTTP rather than some messaging protocol?