Ruby on Rails

Handling chrome.devtools.json requests in Rails apps


Chrome recently added a new feature called “Automatic Workspace Folders” to Chrome DevTools. It can help with automatically mapping the correct folder of a project to the Workspace feature of the web inspector. In the workspace you can, for example, directly edit and save files in your project.

I don’t use the feature, but errors from requests to a specific file for this feature in my logs were cluttering my log output. Basically Chrome is constantly trying to fetch a JSON file:

Started GET “/.well-known/appspecific/com.chrome.devtools.json” for ::1 at ….

ActionController::RoutingError (No route matches [GET] “/.well-known/appspecific/com.chrome.devtools.json”):

To resolve this I wrote a small Rack middleware class that handles these requests and responds in the way Chrome wants. That solves the problem of the cluttered log entries and you can automatically set up the Workspace feature if you want. It needs a small JSON response with the path to the project and a unique UUID.

There are some other solutions out there, like a Vite plugin or a small Ruby gem (chrome_devtools_rails), but the nice thing about this small middleware is that you can simply add it to your codebase without adding an extra dependency.

Simply create the following file as lib/middleware/chrome_devtools.rb:

# frozen_string_literal: true

require "digest"
require "json"

module Middleware
  # Chrome DevTools middleware that intercepts requests to the Chrome DevTools
  # `com.chrome.devtools.json` endpoint and returns a workspace configuration.
  #
  # This allows Chrome DevTools to automatically detect and connect to the project
  # workspace in their developer tools.
  #
  # For more info: See https://chromium.googlesource.com/devtools/devtools-frontend/+/main/docs/ecosystem/automatic_workspace_folders.md
  class ChromeDevtools
    NAMESPACE = "822f7bc5-aa31-4b9f-9c14-df23d95578a1" # randomly generated when writing this code, you can change it to any UUID you want.
    PATH = "/.well-known/appspecific/com.chrome.devtools.json"

    def initialize(app)
      @app = app
    end

    def call(env)
      return @app.call(env) unless env["PATH_INFO"] == PATH

      body = {
        workspace: {
          uuid: generate_uuid,
          root: Rails.root.to_s
        }
      }

      headers = {
        "Content-Type" => "application/json",
        "Cache-Control" => "public, max-age=31536000, immutable",
        "Expires" => (Time.now + 1.year).httpdate
      }

      [200, headers, [body.to_json]]
    end

    private

    def generate_uuid
      Digest::UUID.uuid_v5(NAMESPACE, Rails.root.to_s)
    end
  end
end

And enable the middleware in your config/environments/development.rb:

require "./lib/middleware/chrome_devtools"

Rails.application.configure do
  # ...
  config.middleware.use Middleware::ChromeDevtools
end

That’s it!