# Immediately respond from Middleware

**URL:** <https://discourse.slimframework.com/t/immediately-respond-from-middleware/3632>\
**Category:** Questions\
**Created:** [November 11, 2019, 2:49am UTC](https://discourse.slimframework.com/t/immediately-respond-from-middleware/3632 "2019-11-11T02:49:13Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![nukes88](https://avatars.discourse-cdn.com/v4/letter/n/2bfe46/32.png) [@nukes88](https://discourse.slimframework.com/u/nukes88)\
**Post date:** [November 11, 2019, 2:49am UTC](https://discourse.slimframework.com/t/immediately-respond-from-middleware/3632/1 "2019-11-11T02:49:13Z")

</div>

Hi there,

Is there a way for a middleware to immediately return a response to the client without going through the routes?

I’m thinking of using middleware to check for IP and if its not in the range of IPs I accept, i want to return a response saying “i don’t know you” or the like.

I’m currently using the withAttribute and then checking the attribute i set there, but i want to add the middleware to a group of routes and adding a check in each route is really just troublesome.

Any thoughts? how can i just reject/respond immediately/skip routes from the middleware itself?

---

<div class="post-metadata">

**Author:** ![jDolba](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/jdolba/32/815_2.png) [@jDolba](https://discourse.slimframework.com/u/jDolba)\
**Post date:** [November 11, 2019, 5:31am UTC](https://discourse.slimframework.com/t/immediately-respond-from-middleware/3632/2 "2019-11-11T05:31:36Z")

</div>

I think this is what you are looking for, simple if statement in middleware? (using slim v4)

```
//....
class ContentLengthMiddleware implements MiddlewareInterface
{
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        if (SOMECONDITION) {
            // usual flow, go deeper in Middlewares stack
            return $handler->handle($request); // will return usual response
        }

        $response = new Response(); // your completely custom Response, ignoring usual middleware stack
        // do your stuff

        return $response;
    }
}
```

---

<div class="post-metadata">

**Author:** ![nukes88](https://avatars.discourse-cdn.com/v4/letter/n/2bfe46/32.png) [@nukes88](https://discourse.slimframework.com/u/nukes88)\
**Post date:** [November 11, 2019, 6:28am UTC](https://discourse.slimframework.com/t/immediately-respond-from-middleware/3632/3 "2019-11-11T06:28:59Z")

</div>

Thanks for the reply, but your answer is talking about skipping processing INSIDE the middleware, then continue on to the routes (get/post/etc) right?

I want a middleware to check something and if it meets the condition, to skip the routes. For example:

```auto
$checkIpMiddleware = function(...){...};
$app->get('/lala', function(...){...})->add($checkIpMiddleware);

```

I want the code inside the GET /lala to completely be ignored if the IP does not match any of my accepted ones in $checkIpMiddleware and immediately return a response to the client.

I’ve been able to do that by doing withAttribute in the middleware and then getAttribute in the route, like:

```auto
$ipAllowed = $request->getAttribute('ip_allowed');
if (!isset($ipAllowed)) {
    return $response;
}

```

but if i have a group, for example:

```auto
$app->group('/admin', function(...){
    $group->('/login', function (Request $request, Response $response, $args) {
        $ipAllowed = $request->getAttribute('ip_allowed');
        if (!isset($ipAllowed)) {
            return $response;
        }
         // code
    });
    $group->('/client', ...{
       //same check
          $ipAllowed = $request->getAttribute('ip_allowed');
          if (!isset($ipAllowed)) {
               return $response;
          }
    });
    $group->(....
    // more
})

```

That would mean copy pasting alot of the ip\_allowed condition check into the start of all of those right?

Is there something less troublesome to write?

---

<div class="post-metadata">

**Author:** ![pedropereira](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/pedropereira/32/982_2.png) [@pedropereira](https://discourse.slimframework.com/u/pedropereira)\
**Post date:** [November 11, 2019, 9:57am UTC](https://discourse.slimframework.com/t/immediately-respond-from-middleware/3632/4 "2019-11-11T09:57:52Z")

</div>

jDolba response is correct.

Returning a Response in the middleware ends the middleware chain, stoping whatever middleware you have next (dependending on the stage of the middleware it can end the chain before routing, for example).

What make the chain running one middleware after another is calling return $handler-\>handle($request);

---

<div class="post-metadata">

**Author:** ![nukes88](https://avatars.discourse-cdn.com/v4/letter/n/2bfe46/32.png) [@nukes88](https://discourse.slimframework.com/u/nukes88)\
**Post date:** [November 11, 2019, 10:06am UTC](https://discourse.slimframework.com/t/immediately-respond-from-middleware/3632/5 "2019-11-11T10:06:52Z")

</div>

Thanks for the reply, is it because the routing part is also considered a middleware?  
Sorry i’m new to this.

So that means i can do this:

```auto
$checkCrmIPMiddleware = function (Request $request, RequestHandler $handler) {
    $serverParams = $request->getServerParams();

    $ipList = [
        '999.999.999.999'
    ];

    if (in_array($serverParams['REMOTE_ADDR'], $ipList)) {
        $request = $request->withAttribute('ip_allowed', 'y');
        $response = $handler->handle($request);
        return $response;
    } else {
        $response = new Response();
        $response->getBody()->write('Nope');
        return $response;
    }
};

```

then using it in:

```auto
$app->group('/admin', function (RouteCollectorProxy $group) {
    
    $group->post('/user', function (Request $request, Response $response, $args) {
        ...
        
        return $response;
    });
})->add($checkCrmIPMiddleware );

```

I should get a ‘Nope’ response if my IP is not in the list right?

But i’m getting this instead:

```auto
Cannot instantiate interface Psr\Http\Message\ResponseInterface

```

Thanks again for the help!

---

<div class="post-metadata">

**Author:** ![pedropereira](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/pedropereira/32/982_2.png) [@pedropereira](https://discourse.slimframework.com/u/pedropereira)\
**Post date:** [November 11, 2019, 10:23am UTC](https://discourse.slimframework.com/t/immediately-respond-from-middleware/3632/6 "2019-11-11T10:23:17Z")

</div>

Yes, that is correct.

That error seems related to the ‘nope’ Response you are creating. I’m assuming here you are trying to create a new response from the response interface, which would be incorrect.

For example, when using Slim-Psr7 you can do something like this:

$responseFactory = new \Slim\Psr7\ResponseFactory;

$response = $responseFactory-\>createResponse();

Hope it helps 🙂

---

<div class="post-metadata">

**Author:** ![odan](https://avatars.discourse-cdn.com/v4/letter/o/9de053/32.png) [@odan](https://discourse.slimframework.com/u/odan)\
**Post date:** [November 11, 2019, 11:10am UTC](https://discourse.slimframework.com/t/immediately-respond-from-middleware/3632/7 "2019-11-11T11:10:11Z")

</div>

> [@nukes88](#):
>
> Cannot instantiate interface Psr\Http\Message\ResponseInterface

This is, because a middleware must implement the [PSR-15](https://www.php-fig.org/psr/psr-15/) interface.

---

<div class="post-metadata">

**Author:** ![pedropereira](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/pedropereira/32/982_2.png) [@pedropereira](https://discourse.slimframework.com/u/pedropereira)\
**Post date:** [November 11, 2019, 9:29pm UTC](https://discourse.slimframework.com/t/immediately-respond-from-middleware/3632/8 "2019-11-11T21:29:37Z")

</div>

@odan

I think what you said would give him a Type error instead. Instantiation errors happens when “new” is called. Maybe “new” is calling the Response Interface instead of a Response Object… ?!

The PSR-15 signature of the function seems correct.

---

<div class="post-metadata">

**Author:** ![odan](https://avatars.discourse-cdn.com/v4/letter/o/9de053/32.png) [@odan](https://discourse.slimframework.com/u/odan)\
**Post date:** [November 11, 2019, 10:32pm UTC](https://discourse.slimframework.com/t/immediately-respond-from-middleware/3632/9 "2019-11-11T22:32:19Z")

</div>

I would not say that this a valid PSR-15 interface, because it’s a closure (function) and not a class.

```php
$checkCrmIPMiddleware = function (Request $request, RequestHandler $handler) {

```

---

<div class="post-metadata">

**Author:** ![nukes88](https://avatars.discourse-cdn.com/v4/letter/n/2bfe46/32.png) [@nukes88](https://discourse.slimframework.com/u/nukes88)\
**Post date:** [November 12, 2019, 1:13am UTC](https://discourse.slimframework.com/t/immediately-respond-from-middleware/3632/10 "2019-11-12T01:13:36Z")

</div>

This worked:

```auto
...
use Slim\Psr7\Factory\ResponseFactory;
...
if (in_array($serverParams['REMOTE_ADDR'], $ipList)) {
    $request = $request->withAttribute('ip_allowed', 'y');
    $response = $handler->handle($request);
    return $response;
} else {
    $responseFactory = new ResponseFactory();
    $response = $responseFactory->createResponse();
    $response->getBody()->write('No');
    return $response;
}

```

Thanks for all the help!

---

<div class="post-metadata">

**Author:** ![nukes88](https://avatars.discourse-cdn.com/v4/letter/n/2bfe46/32.png) [@nukes88](https://discourse.slimframework.com/u/nukes88)\
**Post date:** [November 12, 2019, 4:04am UTC](https://discourse.slimframework.com/t/immediately-respond-from-middleware/3632/11 "2019-11-12T04:04:20Z")

</div>

Changed to this:

```auto
//put this in the middleware closure declaration so i can use $app inside it
...
use ($app) 
...
//then use that to get the factory to create the response
$response = $app->getResponseFactory()->createResponse();

```

However, I got the above from the custom error handlers and render part and actually scarpped that and now changed my code to throw errors instead with a custom exception so i can pass the status code as well:

```auto
class ExceptionWithStatus extends \Exception {
    private $statusCode;

    public function __construct($message, $statusCode) {
        $this->statusCode = $statusCode;
        parent::__construct($message);
    }

    public function getStatusCode() {
        return $this->statusCode;
    }
}

$checkCrmIPMiddleware = function (Request $request, RequestHandler $handler) {
    $serverParams = $request->getServerParams();

    $ipList = [
        'xxx.xx.xxx.xxx'
    ];

    if (in_array($serverParams['REMOTE_ADDR'], $ipList)) {
        $response = $handler->handle($request);
        return $response;
    } else {
        throw new ExceptionWithStatus('Nope', 401);
    }
};

```

the errors will be caught by the custom error response closure (from the docs) and i can append my custom status code:

```auto
... //error response closure
   return $response->withStatus($exception->getStatusCode());
}

```
