# SubRequest handling into another route

**URL:** <https://discourse.slimframework.com/t/subrequest-handling-into-another-route/140>\
**Category:** Questions\
**Created:** [April 17, 2016, 3:23pm UTC](https://discourse.slimframework.com/t/subrequest-handling-into-another-route/140 "2016-04-17T15:23:26Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![acidvertigo](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/acidvertigo/32/65_2.png) [@acidvertigo](https://discourse.slimframework.com/u/acidvertigo)\
**Post date:** [April 17, 2016, 3:23pm UTC](https://discourse.slimframework.com/t/subrequest-handling-into-another-route/140/1 "2016-04-17T15:23:26Z")

</div>

Hello,

for my app i want to separate the api from two different frontends. The api routes themselves return a json response and i want to call api methods directly from the frontend routes.

to explain better my API routes are for example:

```
$app->group('/api', function () {
$this->group('/configuration', function () {
    $this->get('[/{id:[0-9]+}]', 'App\Actions\Configuration\GetConfig')->setName('get-config');
    $this->post('[/{id:[0-9]+}]', 'App\Actions\Configuration\AddConfig')->setName('set-config');
    $this->put('[/{id:[0-9]+}]', 'App\Actions\Configuration\UpdateConfig')->setName('update-config');
    $this->delete('[/{id:[0-9]+}]', 'App\Actions\Configuration\DeleteConfig')->setName('delete-config');
});
$this->group('/language', function () {
    $this->get('[/{id:[0-9]+}]', 'App\Actions\Language\GetLanguage')->setName('get-language');
    $this->post('[/{id:[0-9]+}]', 'App\Actions\Language\AddLanguage')->setName('insert-language');
    $this->put('[/{id:[0-9]+}]', 'App\Actions\Language\UpdateLanguage')->setName('update-language');
    $this->delete('[/{id:[0-9]+}]', 'App\Actions\Language\DeleteLanguage')->setName('delete-language');
});
});

```

And my Application route can be:

```
$app->get('/language[/{id:[0-9]+}]', function ($request, $response, $args) use ($app) {

// Make a subrequest to the api method
 $res = $app->subRequest('GET', 'api/language', (!isset($args['id'])) ? '' : $args['id']);
 $json = $res->getBody();
 $language = json_decode($json, true);

    // Sample log message
    $this->logger->info("Slim-Skeleton '/' route");

    // Render index view
    return $this->renderer->render($response, 'index.phtml', ['lang' => $language]);
})->setName('get-api-language');

```

The problem is that when i call the $app-\>subrequest method the render renders the subrequest response first and then outputs the index.phtml template populated with the decoded json data.

There is in slim a better method to not outputdirectly the subrequest response into the main application request?

---

<div class="post-metadata">

**Author:** ![JoeBengalen](https://avatars.discourse-cdn.com/v4/letter/j/b5e925/32.png) [@JoeBengalen](https://discourse.slimframework.com/u/JoeBengalen)\
**Post date:** [April 17, 2016, 3:35pm UTC](https://discourse.slimframework.com/t/subrequest-handling-into-another-route/140/2 "2016-04-17T15:35:35Z")

</div>

`App::subRequest()` should not output anything, it will invoke the application and return the response.

Are you echoing anything in the api action? If so replace that with the `$response->getBody()->write($..)` method

---

<div class="post-metadata">

**Author:** ![acidvertigo](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/acidvertigo/32/65_2.png) [@acidvertigo](https://discourse.slimframework.com/u/acidvertigo)\
**Post date:** [April 17, 2016, 3:45pm UTC](https://discourse.slimframework.com/t/subrequest-handling-into-another-route/140/3 "2016-04-17T15:45:21Z")

</div>

Thank you for your answer.

the controller called is:

```
<?php

 namespace App\Actions\Language;

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use App\DataMappers\Language\LanguageMapper;

class GetLanguage {

   protected $db;

    public function __construct($container) {
        $this->db = $container->get('db');
    }

    public function __invoke(Request $request, Response $response, $args) {
 
    $mapper = new LanguageMapper($this->db);

    if (isset($args['id'])) {
        $res = $mapper->findById($args['id']);
        if (empty($res)) {
            return $response->withStatus(404)
                            ->withHeader('Content-Type', 'text/html')
                            ->write('Page not found');
        }
    } else {
        $res = $mapper->findAll();
    }

    return json_encode($res);
}
}

```

The language mapper object makes sample query to database via PDO and returns a JsonSerializable container class, there are not echo in all the api.

forgot to say that I’m on latest slim3.

UPDATE:

If i var\_dump($reponse) inside the main route the result is null like this:

```
$app->get('/language[/{id:[0-9]+}]', function ($request, $response, $args) use ($app) {

// Make a subrequest to the api method
$res = $app->subRequest('GET', 'api/language', (!isset($args['id'])) ? '' : $args['id']);
$json = $res->getBody();
$language = json_decode($json, true);

// Sample log message
$this->logger->info("Slim-Skeleton '/' route");

// resulting response is null
var_dump($reponse);

// Render index view
return $this->renderer->render($response, 'index.phtml', ['lang' => $language]);
})->setName('get-api-language');

```

So you are right the subrequest outputs nothing, but $this-\>renderer-\>render method seems that catch the subRequest response

---

<div class="post-metadata">

**Author:** ![JoeBengalen](https://avatars.discourse-cdn.com/v4/letter/j/b5e925/32.png) [@JoeBengalen](https://discourse.slimframework.com/u/JoeBengalen)\
**Post date:** [April 17, 2016, 3:50pm UTC](https://discourse.slimframework.com/t/subrequest-handling-into-another-route/140/4 "2016-04-17T15:50:48Z")

</div>

You are not returning a `Response` object

Replace `return json_encode($res);` with:

```php
$response->getBody()->write(json_encode($res));

// also set content type if you are not doing so elsewhere
$response = $response->withHeader('Content-Type', 'application/json;charset=utf-8')

return $response; // important to return the response object

// or Slim specific:
return $response->withJson($res);

```

---

<div class="post-metadata">

**Author:** ![acidvertigo](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/acidvertigo/32/65_2.png) [@acidvertigo](https://discourse.slimframework.com/u/acidvertigo)\
**Post date:** [April 17, 2016, 3:56pm UTC](https://discourse.slimframework.com/t/subrequest-handling-into-another-route/140/5 "2016-04-17T15:56:59Z")

</div>

Thank you,  
i made the changes, but i get the same result.

you are right, if i make var\_dump($reponse) into the main route the result is NULL.

Seems that the return $this-\>renderer-\>render($response, catched the subrequest response internally

Instead I find that creating a new reponse object makes the tweak:

```
$app->get('/language[/{id:[0-9]+}]', function ($request, $response, $args) use ($app) {

// Make a subrequest to the api method
$res = $app->subRequest('GET', 'api/language', (!isset($args['id'])) ? '' : $args['id']);
$json = $res->getBody();
$language = json_decode($json, true);

// Sample log message
$this->logger->info("Slim-Skeleton '/' route");

 // reset response object
**$reponse = new $response;**

// Render index view
return $this->renderer->render($response, 'index.phtml', ['lang' => $language]);
})->setName('get-api-language');

```

This is very strange thing, i’m searchning in the render method why the subrequest response is taken.

---

<div class="post-metadata">

**Author:** ![JoeBengalen](https://avatars.discourse-cdn.com/v4/letter/j/b5e925/32.png) [@JoeBengalen](https://discourse.slimframework.com/u/JoeBengalen)\
**Post date:** [April 17, 2016, 4:05pm UTC](https://discourse.slimframework.com/t/subrequest-handling-into-another-route/140/6 "2016-04-17T16:05:44Z")

</div>

Ohw I see, that is what’s happening. It seems [`subRequest`](https://github.com/slimphp/Slim/blob/3.x/Slim/App.php#L495) uses the `request` from the container, which is the same one the app itself uses (conainer returns the same instance of `response` if pulled twice). This architecture is something that bugged Slim before and there are plans to remove the request and response object from the container as they do not belong there.

I think passing a new response instance into the `subRequest` will also do the job.

---

<div class="post-metadata">

**Author:** ![acidvertigo](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/acidvertigo/32/65_2.png) [@acidvertigo](https://discourse.slimframework.com/u/acidvertigo)\
**Post date:** [April 17, 2016, 4:21pm UTC](https://discourse.slimframework.com/t/subrequest-handling-into-another-route/140/7 "2016-04-17T16:21:04Z")

</div>

Thank you for your help, building an internal client for the api is awesome and slim does the job! 😋

---

<div class="post-metadata">

**Author:** ![ML88](https://avatars.discourse-cdn.com/v4/letter/m/f14d63/32.png) [@ML88](https://discourse.slimframework.com/u/ML88)\
**Post date:** [July 11, 2016, 7:03pm UTC](https://discourse.slimframework.com/t/subrequest-handling-into-another-route/140/8 "2016-07-11T19:03:49Z")

</div>

Hi Joe,  
How would I go about passing a new instance of `response` to the `subRequest`?

Thanks!

---

<div class="post-metadata">

**Author:** ![JoeBengalen](https://avatars.discourse-cdn.com/v4/letter/j/b5e925/32.png) [@JoeBengalen](https://discourse.slimframework.com/u/JoeBengalen)\
**Post date:** [July 11, 2016, 7:25pm UTC](https://discourse.slimframework.com/t/subrequest-handling-into-another-route/140/9 "2016-07-11T19:25:19Z")

</div>

Well, if you look at the signature of the `subRequest` method you see that the last parameter is a response object. So just create a new instance `ResponseInterface` and pass it it.

Also it you do not pass a response instance at all it will create a new instance for you.

---

<div class="post-metadata">

**Author:** ![ML88](https://avatars.discourse-cdn.com/v4/letter/m/f14d63/32.png) [@ML88](https://discourse.slimframework.com/u/ML88)\
**Post date:** [July 11, 2016, 7:33pm UTC](https://discourse.slimframework.com/t/subrequest-handling-into-another-route/140/10 "2016-07-11T19:33:28Z")

</div>

I’m guessing I may be doing this incorrectly.

```
use \Psr\Http\Message\ResponseInterface as Response;

$app->post('/login', function ($request, $response, $args) use ($app) {
  $res = new Response;
  $result = $app->subRequest('POST', '/api/v1/login', 'username=' . $username . '&password=' . $password . '', $res);
  $result = json_decode($result->getBody(), TRUE);
});

```

This throws a PHP error: Cannot instantiate interface Psr\Http\Message\ResponseInterface

Thanks for the help 🙂

---

<div class="post-metadata">

**Author:** ![JoeBengalen](https://avatars.discourse-cdn.com/v4/letter/j/b5e925/32.png) [@JoeBengalen](https://discourse.slimframework.com/u/JoeBengalen)\
**Post date:** [July 11, 2016, 7:39pm UTC](https://discourse.slimframework.com/t/subrequest-handling-into-another-route/140/11 "2016-07-11T19:39:03Z")

</div>

I think you’re guessing right 😉

That error is pretty much self explanatory, you cannot create an object/instance out of an interface.

For your use case I would say just skip passing in the response.

```php
use \Psr\Http\Message\ResponseInterface as Response;

$app->post('/login', function ($request, $response, $args) use ($app) {
  $result = $app->subRequest('POST', '/api/v1/login', "username={$username}&password={$password}");
  $result = json_decode($result->getBody(), TRUE);
});

```

---

<div class="post-metadata">

**Author:** ![ML88](https://avatars.discourse-cdn.com/v4/letter/m/f14d63/32.png) [@ML88](https://discourse.slimframework.com/u/ML88)\
**Post date:** [July 11, 2016, 8:17pm UTC](https://discourse.slimframework.com/t/subrequest-handling-into-another-route/140/12 "2016-07-11T20:17:32Z")

</div>

My reason for asking on this is same as acidvertigo’s, when I do `$response->withJson($data)`, the JSON is displayed since I’m returning the `response` from the front-end. I need the `response` from the `/api/v1/login` endpoint to be a different `response` than the `/login` front-end route’s.

---

<div class="post-metadata">

**Author:** ![JoeBengalen](https://avatars.discourse-cdn.com/v4/letter/j/b5e925/32.png) [@JoeBengalen](https://discourse.slimframework.com/u/JoeBengalen)\
**Post date:** [July 11, 2016, 8:29pm UTC](https://discourse.slimframework.com/t/subrequest-handling-into-another-route/140/13 "2016-07-11T20:29:40Z")

</div>

Ah, the response body may be shared indeed. Guess you will have to create a new response object manually.

```php
$app->post('/login', function ($request, $response, $args) use ($app) {

  $result = $app->subRequest('POST', '/api/v1/login', "username={$username}&password={$password}", [], [], '', new \Slim\Http\Response());
  $result = json_decode($result->getBody(), TRUE);
});

```

---

<div class="post-metadata">

**Author:** ![ML88](https://avatars.discourse-cdn.com/v4/letter/m/f14d63/32.png) [@ML88](https://discourse.slimframework.com/u/ML88)\
**Post date:** [July 11, 2016, 8:46pm UTC](https://discourse.slimframework.com/t/subrequest-handling-into-another-route/140/14 "2016-07-11T20:46:15Z")

</div>

Thanks! That fixed it.

---

<div class="post-metadata">

**Author:** ![tflight](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/tflight/32/1205_2.png) [@tflight](https://discourse.slimframework.com/u/tflight)\
**Post date:** [November 26, 2016, 5:43pm UTC](https://discourse.slimframework.com/t/subrequest-handling-into-another-route/140/15 "2016-11-26T17:43:27Z")

</div>

@ML88, just a heads up that `subrequest` will likely go away with Slim v4.

- [Remove subrequest feature. Fixes #2044](https://github.com/slimphp/Slim/pull/2078) (PR)
- [Remove sub-request functionality](https://github.com/slimphp/Slim/issues/2044) (Issue)

---

<div class="post-metadata">

**Author:** ![ML88](https://avatars.discourse-cdn.com/v4/letter/m/f14d63/32.png) [@ML88](https://discourse.slimframework.com/u/ML88)\
**Post date:** [November 26, 2016, 5:56pm UTC](https://discourse.slimframework.com/t/subrequest-handling-into-another-route/140/16 "2016-11-26T17:56:32Z")

</div>

Looking at those links, I don’t see any discussion on why this is going away or what(if anything) it is being replaced with. Any idea on why its going away or if its being replaced with something?

---

<div class="post-metadata">

**Author:** ![tflight](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/tflight/32/1205_2.png) [@tflight](https://discourse.slimframework.com/u/tflight)\
**Post date:** [November 26, 2016, 7:08pm UTC](https://discourse.slimframework.com/t/subrequest-handling-into-another-route/140/17 "2016-11-26T19:08:41Z")

</div>

I don’t know. @geggleto might be able to provide some insight.

---

<div class="post-metadata">

**Author:** ![geggleto](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/geggleto/32/11_2.png) [@geggleto](https://discourse.slimframework.com/u/geggleto)\
**Post date:** [January 24, 2017, 2:13pm UTC](https://discourse.slimframework.com/t/subrequest-handling-into-another-route/140/18 "2017-01-24T14:13:04Z")

</div>

We are removing subRequest as it does not fit well with proper code design.

In instances where one might need a “sub” request, it is almost always the wrong design choice to resend an HTTP Request through Slim again. Typically we remove features that are not considered good practice with every Major release [Slim 2 =\> 3 we removed service location … as an example].
