Socket
Socket
Sign inDemoInstall

ipx

Package Overview
Dependencies
Maintainers
1
Versions
70
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ipx - npm Package Compare versions

Comparing version 0.0.1 to 0.1.0

.dockerignore

8

config/default.js
module.exports = {
ipx: {
input: {
adapter: 'file.js',
adapter: 'fs.js',
dir: 'storage'
},
cache: {
adapter: 'file.js',
adapter: 'fs.js',
dir: 'cache',
cleanCron: '* * * * * *',
maxUnusedMinutes: 2
cleanCron: '0 0 3 * * *',
maxUnusedMinutes: 24 * 60
}
}
}
{
"name": "ipx",
"version": "0.0.1",
"version": "0.1.0",
"license": "MIT",

@@ -11,3 +11,3 @@ "contributors": [

"start": "bak start",
"dev": "nodemon node_modules/.bin/bak start"
"dev": "DEBUG=ipx* nodemon node_modules/.bin/bak start"
},

@@ -18,2 +18,4 @@ "dependencies": {

"cron": "^1.3.0",
"debug": "^3.1.0",
"etag": "^1.8.1",
"fs-extra": "^4.0.3",

@@ -20,0 +22,0 @@ "is-valid-path": "^0.1.1",

# 🖼 IPX
High performance, secure and easy to use and image proxy based on [Sharp](https://github.com/lovell/sharp) and [libvips](https://github.com/jcupitt/libvips).
High performance, secure and easy to use image proxy based on [Sharp](https://github.com/lovell/sharp) and [libvips](https://github.com/jcupitt/libvips).

@@ -14,2 +14,3 @@ **WARNING:: THIS PROJECT AND DOCS ARE STILL WIP!**

- Smart and auto cache cleaning.
- Twelve factor friendly.

@@ -20,3 +21,3 @@ ## API

Example: `http://cdn.example.com/webp/w:200/avatars/bafollo.png`
Operations are separated by a colon `,` (Example: `op1,op2`) and their arguments separated using underscore `_` (Example: `s_200_300`)

@@ -27,2 +28,43 @@ ََ‍‍Use `_` value in place for `{format}` or `{operations}` to keep original values of source image.

### Examples
- Just change format to `webp` and keep other things same as source:
`http://cdn.example.com/webp/_/avatars/buffalo.png`
- Keep original format (`png`) and set width to `200`:
`http://cdn.example.com/_/w_200/avatars/buffalo.png`
- Resize to `200x300px` using `embed` method and change format to `jpg`:
`http://cdn.example.com/jpg/s_200_300,embed/avatars/buffalo.png`
## Docker deployment
Latest docker image is automatically built under [pooya/ipx](https://hub.docker.com/r/pooya/ipx).
Quick start:
```bash
docker run \
-it \
--rm \
--volume ./storage:/app/storage:ro \
--volume ./cache:/app/cache \
--port 3000:3000
pooya/ipx
```
Using docker-compose:
```yml
image: pooya/ipx
volumes:
- ./storage:/app/storage:ro
- ./cache:/app/cache
ports:
- 3000:3000
```
## Operations

@@ -32,3 +74,2 @@

-------------|-----------------------|-------------|---------------------------------------------------------
`f` | `format` | f:webp | Change format.
`s` | `width`, `height` | s:200:300 | Resize image.

@@ -41,4 +82,23 @@ `w` | `width` | w:200 | Change image with.

## Config
Config can be customized using `IPX_*` environment variables or `config/local.js` file. Here are defaults:
```js
ipx: {
input: {
adapter: 'IPX_INPUT_ADAPTER', // Default: fs.js
dir: 'IPX_INPUT_DIR' // Default: storage
},
cache: {
adapter: 'IPX_CACHE_ADAPTER', // Default: fs.js
dir: 'IPX_CACHE_DIR', // Default: cache
cleanCron: 'IPX_CACHE_CLEAN_CRON', // Default: 0 0 3 * * * (every night at 3:00 AM)
maxUnusedMinutes: 'IPX_CACHE_CLEAN_MINUTES' // Default: 24 * 60 (24 hours)
}
}
```
## License
MIT - Pooya Parsa
const Boom = require('boom')
const Config = require('config')
const IPX = require('./ipx')
const etag = require('etag')

@@ -10,2 +11,6 @@ const ipx = new IPX(Config.get('ipx'))

path: '{format}/{operations}/{src*}',
options: {
// https://hapijs.com/api#-routeoptionscache
cache: false
},
async handler ({ params = {} }, h) {

@@ -18,7 +23,23 @@ const { format, operations, src } = params

const img = await ipx.get({ format, operations, src })
const response = h.response(img.data)
// Get basic info about request
const info = await ipx.getInfo({ format, operations, src })
if (img.format) {
response.type('image/' + img.format)
// Sets the response 'ETag' and 'Last-Modified' headers and
// checks for any conditional request headers to decide
// if the response is going to qualify for an HTTP 304 (Not Modified)
// https://hapijs.com/api#-hentityoptions
let response = h.entity({
etag: etag(info.cacheKey).replace(/"/g, ''),
modified: info.stats.mtime
})
// Get real response
if (!response) {
const data = await ipx.getData(info)
response = h.response(data)
}
// Set additional headers
if (info.format) {
response.type('image/' + info.format)
} else {

@@ -25,0 +46,0 @@ response.type('image')

@@ -6,2 +6,3 @@ const OPERATIONS = require('./operations')

const { CronJob } = require('cron')
const debug = require('debug')('ipx')

@@ -11,3 +12,3 @@ const operationSeparator = ','

class Shark {
class IPX {
constructor (options) {

@@ -58,2 +59,3 @@ this.options = options

)
debug('Starting cache clean cron ' + this.options.cache.cleanCron)
this.cacheCleanCron.start()

@@ -105,9 +107,3 @@ }

/**
* Convert and get the result
* @param {String} format
* @param {String} operations
* @param {String} src
*/
async get ({ format, operations, src }) {
async getInfo ({ format, operations, src }) {
// Validate format

@@ -127,6 +123,12 @@ if (format === '_') {

// Validate src
if (!src || src.indexOf('..') >= 0 || !await this.input.validate(src)) {
if (!src || src.indexOf('..') >= 0) {
throw Boom.notFound()
}
// Get src stat
const stats = await this.input.stats(src)
if (!stats) {
throw Boom.notFound()
}
// Parse and validate operations

@@ -141,18 +143,22 @@ let _operations = this.parseOperations(operations)

// Calculate unique hash key
const cacheKey =
src +
'/' +
(_operations.length ? _operations.map(o => o.cacheKey).join(argSeparator) : '_') +
'.' +
format
// Compute unique hash key
const operationsKey = _operations.length ? _operations.map(o => o.cacheKey).join(argSeparator) : '_'
const statsKey = stats.mtime.getTime().toString(16) + '-' + stats.size.toString(16)
const cacheKey = src + '/' + statsKey + '/' + operationsKey + '.' + format
// Return info
return {
operations: _operations,
stats,
cacheKey,
format,
src
}
}
async getData ({ cacheKey, stats, operations, format, src }) {
// Check cache existence
const cache = await this.cache.get(cacheKey)
if (cache) {
console.log('HIT!')
return {
format,
data: cache
}
return cache
}

@@ -170,3 +176,3 @@

_operations.forEach(({ operation, args }) => {
operations.forEach(({ operation, args }) => {
try {

@@ -191,6 +197,3 @@ sharp = operation.handler(this, sharp, ...args)

return {
data,
format
}
return data
}

@@ -205,2 +208,2 @@

module.exports = Shark
module.exports = IPX
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc