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


Do you feel like the times of punching in a time card should die?

Being remote is a great thing. But, it won’t work if your way of working isn’t right. Just abandoning an office won’t work. We are against the status quo of the industry. We spent last years developing our way of working. We managed to get extraordinary results with it and we wanted to share it.

Click here to read more!

Async Remote

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

You might also like