How to enable Gzip compression in Laravel while hosting on AWS Lambda
Tags: laravel, serverless, aws, programming
Published: 2021-12-09 14:00:31

As I came across [AWS Lambda Serverless](https://aws.amazon.com/lambda/) services, it intrigued me and I wanted to learn more about its features. 

Since my background is in PHP development and there were no platforms available to host PHP environments, it made sense to adopt Lambda into our development. 

It’s a developer’s dream, not having to worry about scaling the cloud infrastructure, hefty bills, and offers low maintenance to boot.

Gradually, I learned about [bref](https://bref.sh/), a package that made it easy to host your PHP application on serverless. I started working on this package, finding the documentation and tutorials online. I successfully hosted my Laravel application on Lambda.

I came across various challenges during deployments.

A few days back, I was trying to fix my website from an SEO perspective, while doing a technical audit of my website, I came across a compression issue with my website. All the crawlers were asking to use a compression mechanism in my responses.

Digging deeper, I learned that AWS doesn't have compression enabled for its HTTP APIs. I spoke to the AWS support team and they asked me to implement a few changes in response, which will enable binary support for lambda response, AWS expects its response should have below attributes in response:

```
"body": gzippedResponse.toString("base64"),
"isBase64Encoded": true,
"statusCode": 200,
"headers": {
   "Content-Encoding": "gzip"
}
```
I wanted to take the same approach with my Laravel application. I found one article about [Gzip compression with Laravel Vapor](https://bannister.me/blog/gzip-compression-on-laravel-vapor/), since I wasn't using Vapor, I had to research and implement in my own tech stack.

The documentation I found was easy to follow and helped me make the changes to my app. Now when I run my app, it works perfectly!

I configured my serverless.yml file with:

```
provider:
    # ...
    apiGateway:
        binaryMediaTypes:
            - '*/*'
    environment:
        BREF_BINARY_RESPONSES: '1'
```

Then I made middleware as mentioned in the article:

```
<?php
 
namespace App\Http\Middleware;
 
use Closure;
use Illuminate\Http\Request;
 
class GzipEncodeResponse
{
    public function handle(Request $request, Closure $next)
    {
        $response = $next($request);
 
        if (in_array('gzip', $request->getEncodings()) && function_exists('gzencode')) {
            $response->setContent(gzencode($response->getContent(), 9));
            $response->headers->add([
                'Content-Encoding' => 'gzip',
                'X-Vapor-Base64-Encode' => 'True',
            ]);
        }
        return $response;
    }
}
```

And then added this middleware in my kernel.php file:

```
protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \App\Http\Middleware\GzipEncodeResponse::class,
    ],

    'api' => [
        'throttle:api',
        \Illuminate\Routing\Middleware\SubstituteBindings::class,     
    ],
];
```
And did `serverless deploy`

Everything was working perfectly as expected. I achieved my gzip compression in my HTTP APIs