Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for base64-encoded props #6

Merged
merged 1 commit into from
Feb 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions example/netlify.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,8 @@ publish = "public/"

[functions]
external_node_modules = ["fsevents"]

[[redirects]]
from = "/_gatsby/image/*"
to = "/.netlify/builders/gatsby"
status = 200
7 changes: 7 additions & 0 deletions example/netlify/functions/gatsby.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { createIPXHandler } from '@netlify/ipx'

export const handler = createIPXHandler({
domains: ['images.unsplash.com'],
propsEncoding: 'base64',
basePath: '/_gatsby/image/'
})
2 changes: 1 addition & 1 deletion example/netlify/functions/ipx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ import { createIPXHandler } from '@netlify/ipx'

export const handler = createIPXHandler({
domains: ['images.unsplash.com'],
basePath: '/.netlify/functions/ipx/'
basePath: '/.netlify/builders/ipx/'
})
45 changes: 28 additions & 17 deletions example/public/index.html
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<title>Netlify Optimized Images</title>
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
</head>
<body class="m-4">
<h1 class="text-4xl mb-4">Netlify Optimized Images</h1>

<figure>
<img src="/.netlify/functions/ipx/f_webp,w_450/img/test.jpg"/>
<figcaption>/.netlify/functions/f_webp,w_450/img/test.jpg<figcaption></figure>
<head>
<title>Netlify Optimized Images</title>
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
</head>

<figure>
<img src="/.netlify/functions/ipx/f_webp,w_450/https://images.unsplash.com/photo-1514888286974-6c03e2ca1dba"/>
<figcaption>/.netlify/functions/f_webp,w_450/img/https://images.unsplash.com/photo-1514888286974-6c03e2ca1dba<figcaption></figure>
<body class="m-4">
<h1 class="text-4xl mb-4">Netlify Optimized Images</h1>

<footer class="mt-4">
<hr>
<figure>
<img src="/.netlify/builders/ipx/f_webp,w_450/img/test.jpg" />
<figcaption>/.netlify/builders/ipx/f_webp,w_450/img/test.jpg<figcaption>
</figure>

<figure>
<img src="/.netlify/builders/ipx/f_webp,w_450/https://images.unsplash.com/photo-1514888286974-6c03e2ca1dba" />
<figcaption>/.netlify/builders/ipx/f_webp,w_450/img/https://images.unsplash.com/photo-1514888286974-6c03e2ca1dba
<figcaption>
</figure>
<figure>
<img
src="/_gatsby/image/aHR0cHM6Ly9pbWFnZXMudW5zcGxhc2guY29tL3Bob3RvLTE1MTc4NDk4NDU1MzctNGQyNTc5MDI0NTRhP2l4bGliPXJiLTEuMi4xJml4aWQ9TW53eE1qQTNmREI4TUh4d2FHOTBieTF3WVdkbGZIeDhmR1Z1ZkRCOGZIeDgmYXV0bz1mb3JtYXQmZml0PWNyb3Amdz0yMDAwJnE9ODA=/dz0zMDAmaD00MDAmZm09YXZpZg==.avif"
alt="Gatsby" />
<figcaption>/_gatsby/image/aHR0cHM6Ly9pbWFnZXMudW5zcGxhc2guY29tL3Bob3RvLTE1MTc4NDk4NDU1MzctNGQyNTc5MDI0NTRhP2l4bGliPXJiLTEuMi4xJml4aWQ9TW53eE1qQTNmREI4TUh4d2FHOTBieTF3WVdkbGZIeDhmR1Z1ZkRCOGZIeDgmYXV0bz1mb3JtYXQmZml0PWNyb3Amdz0yMDAwJnE9ODA=/dz0zMDAmaD00MDAmZm09YXZpZg==.avif</figcaption>
</figure>
<footer class="mt-4">
<hr>
Images optimized with
<a href="https://github.com/unjs/ipx" target="_blank">unjs/ipx</a>
served by <a href="https://www.netlify.com/products/functions/">Netlify Builder Functions</a>
</footer>
</footer>

</body>

</body>
</html>
</html>
20 changes: 18 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import { builder, Handler } from '@netlify/functions'
import { parseURL } from 'ufo'
import etag from 'etag'
import { loadSourceImage } from './http'
import { decodeBase64Params } from './utils'

export function createIPXHandler ({
cacheDir = join(tmpdir(), 'ipx-cache'),
basePath = '/_ipx',
propsEncoding,
...opts
}: Partial<IPXOptions> & { cacheDir?: string; basePath?: string } = {}) {
}: Partial<IPXOptions> & { cacheDir?: string; basePath?: string, propsEncoding?: 'base64' } = {}) {
const ipx = createIPX({ ...opts, dir: join(cacheDir, 'cache') })

const handler: Handler = async (event, _context) => {
Expand All @@ -20,8 +22,22 @@ export function createIPXHandler ({
const requestEtag = event.headers['if-none-match']
const url = event.path.replace(basePath, '')

const [modifiers = '_', ...segments] = url.substr(1).split('/')
// eslint-disable-next-line prefer-const
let [modifiers = '_', ...segments] = url.slice(1).split('/')
let id = decodeURIComponent(segments.join('/'))

if (propsEncoding === 'base64') {
const params = decodeBase64Params(url)
if (params.error) {
return {
statusCode: 400,
body: params.error
}
}
id = params.id
modifiers = params.modifiers
}

const requestHeaders: Record<string, string> = {}
const isLocal = !id.startsWith('http')
if (isLocal) {
Expand Down
40 changes: 40 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* Support for Gatsby-style base64-encoded URLs
*/
export function decodeBase64Params (path:string) {
const [url, transform] = path.split('/')
if (!url || !transform) {
return {
error: 'Bad Request'
}
}
const id = Buffer.from(url, 'base64').toString('utf8')
// Strip the extension
const transforms = Buffer.from(transform.split('.')[0], 'base64').toString(
'utf8'
)
if (!id || !transforms) {
return {
error: 'Bad Request'
}
}
const params = new URLSearchParams(transforms)

// [ipx modifier name, gatsby modifier name]
const props = [
['width', 'w'],
['height', 'h'],
['format', 'fm']
]

const modifiers: Array<string> = []

for (const [modifier, prop] of props) {
const value = params.get(prop)
if (value) {
modifiers.push(`${modifier}_${value}`)
}
}

return { id, modifiers: modifiers.join(',') }
}