Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is routing API calls through my own RESTful API considered an acceptable strategy?

Tags:

java

rest

spring

This question might be considered opinionated but I really can't seem to find a straight answer. So either I'm missing something or I'm asking the wrong questions. So, I'm an undergrad student and new in the whole Spring app development and I'm currently creating an app with React acting as the frontend and building a RESTful API using Spring in order to support it with necessary operations for the backend. Among other services, the backend API I'm building is used as a middle-man forwarding calls to the Google Geocoding API and other 3rd party APIs. **My biggest question since I started this is, is this a valid strategy? ** (at least, something acceptable by industry professionals)

My Research

  • The biggest pro that this method has is that it allows me to effectively hide my API keys from the client rendering any attacks impossible.
  • At the same time, this whole process adds (I believe) unnecessary complexity and delay in the overall responses resulting in a possible hindered user experience.
  • Something I'm not quite sure yet would be that I'll have to add async capabilities to the services exposed by my own API in order to facilitate multiple users. (This last part might be entirely wrong but I haven't been able to understand how multiple users are handled when querying the same endpoint concurrently.)
  • I have used Apache JMeter to test the performance of the app on concurrent POST calls and it seems to be able to handle them on around 170ms. (I'll post screenshots of the results below.)

Code

I'll try to include code demonstrating the controller that's responsible for the calls to the Geocoding API.

@RestController
@RequestMapping("/api")
@Slf4j
@RequiredArgsConstructor
@Component
public class GeocodingController {
    private final OkHttpClient httpClient = new OkHttpClient();

    @PostMapping(value = "/reversegeocoding")
    public String getReverseGeocode(@RequestBody LatLng latlng) throws IOException, ExecutionException, InterruptedException {
        String encodedLatLng = latlng.toString();
        Request request  = new Request.Builder()
                .url("https://maps.googleapis.com/maps/api/geocode/json?" +
                        "language=en&result_type=street_address&latlng=" + encodedLatLng +
                        "&key=MY_API_KEY")
                .build();

        CallbackFuture future = new CallbackFuture();
        httpClient.newCall(request).enqueue(future);
        Response response = future.get();
        return response.body().string();

    }
}

The getReverseGeocode() method takes in as an argument the following object:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class LatLng {

    double lat;
    double lng;

    public String toString() {
        return lat + "," + lng;
    }
}

So, the Request Body is mapped onto the above object once the request arrives.
Finally the CallbackFuture is just an adapter class based on this answer.

public class CallbackFuture extends CompletableFuture<Response> implements Callback {

    @Override
    public void onFailure(Call call, IOException e) {
        super.completeExceptionally(e);
    }

    @Override
    public void onResponse(Call call, Response response) {
        super.complete(response);
    }
}

JMeter Results

JMeter Results

Duration Assertion Setup

Thread Group Settings - 10 Threads (Users)

like image 322
Invalid_Path Avatar asked Aug 11 '20 17:08

Invalid_Path


People also ask

What is a good practice that should be followed for a REST API?

REST API Must Accept and Respond with JSON It is a common practice that APIs should accept JSON requests as the payload and also send responses back. JSON is a open and standardized format for data transfer. It is derived from JavaScript in a way to encode and decode JSON via the Fetch API or another HTTP client.

What is routing in REST API?

Routing is a functionally based tag or Uri template used by APIs to match the desired action or methods expected to be executed. There are two types or rather two different types of Routing being used during development.

What are the different ways to communicate through a REST API?

These methods – GET, POST, PUSH, PATCH, and DELETE – correspond to create, read, update, and delete resources. REST headers contain information that represent metadata associated with every single REST API request.


2 Answers

Yeah, this is done all the time. Not all external APIs are setup to allow for you to grant access to your users directly. You also may have requirements for logging and or access control. It does mean you need to dedicate your resources to the calls but unless you are expecting an excessive load its not worth optimizing for too far in advance. Sometimes you can offload the proxy responsibilities to something like nginix instead which can be more efficient than your application backend.

In my experience it is worthwhile to keep these proxies in their own separate package that is isolated from your other code where possible. Then if you need to scale them independently of your main app you can easily break them out.

like image 103
Deadron Avatar answered Sep 22 '22 20:09

Deadron


Yes, this is an entirely valid strategy. There are many benefits to using this approach and whilst it can feel like it's adding unnecessary complexity, the benefits often out way the cost.

Firstly you're avoiding "leaky abstractions", the client shouldn't care how you implement a particular piece of functionality, they just care that it works! It also means that you should be able to change the implementation in the future without the client even knowing.

Secondly, you're decoupling your APIs from others. If the wrapped API changes, you can handle this yourself without the clients having to change their code (there will be times when this can't be done, but it offers a good defence to this).

Also, it gives you a convenient point to implement your own functionality around these APIs (rate limiting, access control and logging for example).

The @Async issue is not specific to wrapping third party APIs, it's an issue for all endpoints you have which have blocking IO.

like image 42
StuPointerException Avatar answered Sep 23 '22 20:09

StuPointerException