Image Placeholder for your development environment

Image Placeholder for your development environment

Some time ago I was working together with Paweł on one of our clients web application. We used copy of products catalog coming from production server on our development machines. What we were lacking were product photos, causing application layout to look poorly and making any css job hard. We tried to find a smart solution for that case.

Every time you request non-existing image in your app, you got a 404. What if we could detect such case and modify response to actually contain image and return 200 OK? Custom rack middleware is a perfect place for that. The code is pretty simple:

require 'net/http'

module ImagePlaceholder
  class Middleware
    def initialize(app, image_extensions: %w(jpg png), size_pattern: {/.*/ => 100}, host: '')
      @app = app
      @image_extensions = image_extensions
      @size_pattern = size_pattern
      @host = host

    def call(env)
      status, headers, response =
      request_path = URI.decode(

      if not_found?(status) && image?(request_path)
        [status, headers, response]


    def serve_placeholder_image(size = 100)
      net_response  = Net::HTTP.get_response(URI("https://#{@host}/#{size}"))
      rack_response =, net_response.code.to_i)
      safe_headers  = net_response.to_hash
                        .reject { |key, _| hop_by_hop_header_fields.include?(key.downcase) }
                        .reject { |key, _| key.downcase == 'content-length' }

      safe_headers.each do |key, values|
        values.each do |value|
          rack_response.add_header(key, value)

    def hop_by_hop_header_fields
      %w(connection keep-alive proxy-authenticate proxy-authorization te trailer transfer-encoding upgrade)

    def not_found?(status)
      status == 404

    def image?(path)
      @image_extensions.include? File.extname(path)[1, 3]

    def matched_size(path)
      @size_pattern.find { |pattern, _| pattern.match(path) }[1]
  1. Check whether image is requested
  2. Check if status is 404
  3. If yes, make a get request to a service like and modify response with image from it
  4. Otherwise, just return standard response

Our initial version used Fill Murray which brought us smile every time we launched products catalog to do some work on.

You can go with Steven Seagal eating a carrot or Nicolas Cage if you would like to. Just add host option to middleware use:

# config/environments/development.rb

Rails.application.configure do
  config.middleware.use ImagePlaceholder::Middleware, host: ''

You can also match desired image sizes, providing pattern:

# config/environments/development.rb

Rails.application.configure do
  config.middleware.use ImagePlaceholder::Middleware, size_pattern: {
    %r{/uploads/.*/s_[0-9]+\.[a-z]{3}$}  => 200,  # /uploads/product/cover/42/s_9781467775687.jpg
    %r{/uploads/.*/xl_[0-9]+\.[a-z]{3}$} => 750,  # /uploads/product/cover/42/xl_9781467775687.jpg
    %r{.*} => 1024,                               # /uploads/random/spanish_inquisition.png

By default, ImagePlaceholde::Middleware supports .jpg and .png images, but you can extend supported filetypes with ease:

# config/environments/development.rb

Rails.application.configure do
  config.middleware.use ImagePlaceholder::Middleware, image_extensions: %w(jpg jpeg png webp gif)

And last, but not least, it can be used with any Rack application:

use ImagePlaceholder::Middleware, size_pattern: { /.*/ => '320/320' }, host: ''
run YourRackApp

To start using it, put gem image_placeholder into your Gemfile. If you would like to contribute or read more, visit


Say hello to React.js! Learn it with practical examples all the way!

We wrote a book which is a perfect entry point to this world of the modern JavaScript tooling. It’s not a full ES2015 bible, nor is it a full React.js 16 API description. We went straight to the main value - how you can implement typical UI widgets. This is the focus on the book, as many practical examples as possible.

Click here to read more!

React.js by example

There is more... check out other books published by us

You might also like