user1032531 user1032531 - 2 years ago 82
reST (reStructuredText) Question

How should Slim be used to combine multiple REST requests?

I have a page which makes several requests using the same HTTP method to an API and displays the results.

<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);

curl_setopt($ch, CURLOPT_URL, "https://rest.api.com/staff");
$staff=curl_exec( $ch );
curl_setopt($ch, CURLOPT_URL, "https://rest.api.com/departments/accounting");
$departments=curl_exec( $ch );
curl_setopt($ch, CURLOPT_URL, "https://rest.api.com/roles");
$roles=curl_exec( $ch );

curl_close($ch);

echo $twig->render('offices.html', ['staff'=>$staff,'departments'=>$departments,'roles'=>$roles]);


The API is located at https://rest.api.com, and is under my control. The three endpoints sometimes need to be individually accessed so must remain.

<?php
$app = new \Slim\App();

$app->get('/users', function ($request, $response, $args) {
return $response->withJson(getUsers(),200);
});
$app->get('/departments/{subdept}', function ($request, $response, $args) {
return $response->withJson(getDepartments($args['subdept']),200);
});
$app->get('/roles', function ($request, $response, $args) {
return $response->withJson(getRoles(),200);
});
// other endpoints...

$app->run();


How should the three requests be combined into a single request? I don't wish to do something like the following as it is inflexible and requires additional documentation for each combination endpoint.

$app->get('/users_and_departments_and_roles', function ($request, $response, $args) {
return $response->withJson([
'users'=>getUsers(),
'departments'=>getDepartments($args['subdept']),
'roles'=>getRoles()
],200);
});

Answer Source

Maybe combining requests is not the best description for what you are trying to achieve, because I don't think we actually can combine HTTP requests. This could be easier if you wanted to use POST method but, to achieve this using GET method what you want is probably a route pattern which can be used to return multiple combination of user, role and department based on what caller asks for.

Assuming only numeric values are acceptable for subdept for the sake of simplicity, here is an example to express my general idea about the solution:

$app->get('/api/combine/user:{users_required:true|false}/role:{roles_require:true|false}/department:{subdept:[0-9]+|false}', function ($req, $res, $args) {

    return $response->withJson([
        'users'=> $args['users_required'] == 'true' ? getUsers() : [],
        'departments'=> $args['subdept'] == 'false' ? [] :  getDepartments($args['subdept']),
        'roles'=> $args['roles_required'] == 'true' ? getRoles() : []
        ],200);

});

This route will always return a result including users, roles and departments keys but these keys might include empty arrays as values if caller does not want any of them, and that's up to caller, but caller must always specify if he does not want any of these keys or not and the order of route parameters are always the same. For example one can access https://rest.api.com/user:false/role:true/department:100 to get a result ignoring users (/user:false), a list of roles (/role:true) and departments for subdept=100 (/deptartment:100).

A more complex pattern might help you but the general idea is to define a route pattern which can determine what combination of available individual endpoints user wants and return the result based on that.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download