README.md

<div align="center">
  <img src="https://user-images.githubusercontent.com/11348/195426081-7a62709e-3309-4f6a-9740-4ef57d8df5d4.png" width="800" />
  <br /><br />
  Image server as a <a href="https://hex.pm/packages/plug"><code>Plug</code></a>, powered by <a href="https://www.libvips.org/"><code>libvips</code></a>.
  <br /><br />
  <a href="https://github.com/mirego/plug_image_processing/actions/workflows/ci.yml"><img src="https://github.com/mirego/plug_image_processing/actions/workflows/ci.yml/badge.svg" /></a>
  <a href="https://hex.pm/packages/plug_image_processing"><img src="https://img.shields.io/hexpm/v/plug_image_processing.svg" /></a>
</div>

## Usage

### Installation

PlugImageProcessing is published on Hex. Add it to your list of dependencies in `mix.exs`:

```elixir
# mix.exs
def deps do
  [
    {:plug_image_processing, ">= 0.0.1"}
  ]
end
```

Then run mix deps.get to install the package and its dependencies.

To expose a `/imageproxy` route, add the plug in your endpoint, before your router plug, but after `Plug.Parsers`:

```elixir
# lib/my_app_web/endpoint.ex
plug(PlugImageProcessing.Web, path: "/imageproxy")
#...
plug(MyAppWeb.Router)
```

## Features

### Sources

A single source for image is supported for now: the `url` query parameter.

```sh
/imageproxy/resize?url=https://s3.ca-central-1.amazonaws.com/my_image.jpg&width=300
```

It will download the image from the remote location, modify it using libvips and return it to the client.

### Operations

A number of operations exposed by libvips are supported by `PlugImageProcessing`. See the `PlugImageProcessing.Operations.*` module for more details.

### Requests validations

Validations can be added so your endpoint is more secure.

### Signature key

By adding a signature key in your config, a parameter `sign` needs to be included in the URL to validate the payload.
The signature prevent a client to forge a large number of unique requests that would go through the CDN and hitting our server.

```elixir
plug(PlugImageProcessing.Web, url_signature_key: "1234")
```

Then a request path like:

```sh
/imageproxy/resize?url=https://s3.ca-central-1.amazonaws.com/my_image.jpg&width=300&quality=60
```

will fail because the `sign` parameter is not present.

**The HMAC-SHA256 hash is created by taking the URL path (including the leading /), the request parameters (alphabetically-sorted and concatenated with & into a string). The hash is then base64url-encoded.**

```elixir
Base.url_encode64(:crypto.mac(:hmac, :sha256, "1234", "/resize" <> "quality=60&url=https://s3.ca-central-1.amazonaws.com/my_image.jpg&width=300"))
# => "O8Xo9xrP0fM67PIWMIRL2hjkD_c5HzzBtRLfpo43ENY="
```

Now this request will succeed!

```sh
/imageproxy/resize?url=https://s3.ca-central-1.amazonaws.com/my_image.jpg&width=300&quality=60&sign=O8Xo9xrP0fM67PIWMIRL2hjkD_c5HzzBtRLfpo43ENY=
```

## License

`PlugImageProcessing` is © 2022 [Mirego](https://www.mirego.com) and may be freely distributed under the [New BSD license](http://opensource.org/licenses/BSD-3-Clause). See the [`LICENSE.md`](https://github.com/mirego/plug_image_processing/blob/master/LICENSE.md) file.

## About Mirego

[Mirego](https://www.mirego.com) is a team of passionate people who believe that work is a place where you can innovate and have fun. We’re a team of [talented people](https://life.mirego.com) who imagine and build beautiful Web and mobile applications. We come together to share ideas and [change the world](http://www.mirego.org).

We also [love open-source software](https://open.mirego.com) and we try to give back to the community as much as we can.