Class: SoberSwag::Server

Inherits:
Object
  • Object
show all
Defined in:
lib/sober_swag/server.rb

Overview

A basic, rack-only server to serve up swagger definitions. By default it is configured to work with rails, but you can pass stuff to initialize.

Constant Summary collapse

RAILS_CONTROLLER_PROC =
proc do
  Rails.application.routes.routes.map { |route|
    route.defaults[:controller]
  }.to_set.reject(&:nil?).map { |controller|
    begin
      "#{controller}_controller".classify.constantize
    rescue StandardError
      nil
    end
  }.compact.filter { |controller| controller.ancestors.include?(SoberSwag::Controller) }
end
EFFECT_HTML =
<<~HTML.freeze
  <!DOCTYPE html>
  <html>
    <head>
      <title>ReDoc</title>
      <!-- needed for adaptive design -->
      <meta charset="utf-8"/>
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">

      <!--
      ReDoc doesn't change outer page styles
      -->
      <style>
        body {
          margin: 0;
          padding: 0;
        }
      </style>
    </head>
    <body>
      <redoc spec-url='SCRIPT_NAME'></redoc>
      <script src="https://cdn.jsdelivr.net/npm/redoc@REDOC_VERSION/bundles/redoc.standalone.js"> </script>
    </body>
  </html>
HTML

Instance Method Summary collapse

Constructor Details

#initialize(controller_proc: RAILS_CONTROLLER_PROC, cache: false, redoc_version: 'next') ⇒ Server

Start up.

Parameters:

  • controller_proc (Proc) (defaults to: RAILS_CONTROLLER_PROC)

    a proc that, when called, gives a list of Controllers to document

  • cache (Bool | Proc) (defaults to: false)

    if we should cache our definitions (default false)

  • redoc_version (String) (defaults to: 'next')

    what version of the redoc library to use to display UI (default 'next', the latest version).



26
27
28
29
30
31
32
33
34
# File 'lib/sober_swag/server.rb', line 26

def initialize(
  controller_proc: RAILS_CONTROLLER_PROC,
  cache: false,
  redoc_version: 'next'
)
  @controller_proc = controller_proc
  @cache = cache
  @html = EFFECT_HTML.gsub(/REDOC_VERSION/, redoc_version)
end

Instance Method Details

#cache?Boolean (private)

Returns:

  • (Boolean)


84
85
86
# File 'lib/sober_swag/server.rb', line 84

def cache?
  @cache.respond_to?(:call) ? @cache.call : @cache
end

#call(env) ⇒ Object

Standard Rack call method.



65
66
67
68
69
70
71
72
# File 'lib/sober_swag/server.rb', line 65

def call(env)
  req = Rack::Request.new(env)
  if req.path_info&.match?(/json/si) || req.get_header('Accept')&.match?(/json/si)
    [200, { 'Content-Type' => 'application/json' }, [generate_json_string]]
  else
    [200, { 'Content-Type' => 'text/html' }, [@html.gsub(/SCRIPT_NAME/, "#{env['SCRIPT_NAME']}.json")]]
  end
end

#generate_json_stringObject (private)



76
77
78
79
80
81
82
# File 'lib/sober_swag/server.rb', line 76

def generate_json_string
  if cache?
    @json_string ||= JSON.dump(generate_swagger)
  else
    JSON.dump(generate_swagger)
  end
end

#generate_swaggerObject (private)



88
89
90
91
92
93
94
95
96
97
# File 'lib/sober_swag/server.rb', line 88

def generate_swagger
  routes = sober_controllers.flat_map(&:defined_routes).reduce(SoberSwag::Compiler.new) { |c, r| c.add_route(r) }
  {
    openapi: '3.0.0',
    info: {
      version: '1',
      title: 'SoberSwag Swagger'
    }
  }.merge(routes.to_swagger)
end

#sober_controllersObject (private)



99
100
101
# File 'lib/sober_swag/server.rb', line 99

def sober_controllers
  @controller_proc.call
end