### Home Classes Methods

### In Files

- lib/rdoc/servlet.rb

### Parent

WEBrick::HTTPServlet::AbstractServlet

### Methods

- ::new
- #asset
- #do_GET
- #documentation_page
- #documentation_search
- #documentation_source
- #error
- #generator_for
- #if_modified_since
- #installed_docs
- #not_found
- #ri_paths
- #root
- #root_search
- #show_documentation
- #store_for

### Files

- CONTRIBUTING.rdoc
- CVE-2013-0256.rdoc
- ExampleRDoc.rdoc
- LICENSE.rdoc
- Manifest.txt
- README.rdoc
- RI.rdoc
- Rakefile
- TODO.rdoc

### Class/Module Index

Quicksearch

- RDoc
- RDoc::Alias
- RDoc::AnonClass
- RDoc::AnyMethod
- RDoc::Attr
- RDoc::ClassModule
- RDoc::CodeObject
- RDoc::Comment
- RDoc::Constant
- RDoc::Context
- RDoc::Context::Section
- RDoc::CrossReference
- RDoc::ERBIO
- RDoc::ERBPartial
- RDoc::Encoding
- RDoc::Error
- RDoc::Extend
- RDoc::Gauntlet
- RDoc::Generator
- RDoc::Generator::Darkfish
- RDoc::Generator::JsonIndex
- RDoc::Generator::Markup
- RDoc::Generator::RI
- RDoc::GhostMethod
- RDoc::Include
- RDoc::Markdown
- RDoc::Markdown::Literals
- RDoc::Markup
- RDoc::Markup::AttrChanger
- RDoc::Markup::AttrSpan
- RDoc::Markup::AttributeManager
- RDoc::Markup::Attributes
- RDoc::Markup::BlankLine
- RDoc::Markup::BlockQuote
- RDoc::Markup::Document
- RDoc::Markup::Formatter
- RDoc::Markup::FormatterTestCase
- RDoc::Markup::HardBreak
- RDoc::Markup::Include
- RDoc::Markup::IndentedParagraph
- RDoc::Markup::List
- RDoc::Markup::ListItem
- RDoc::Markup::Paragraph
- RDoc::Markup::Parser
- RDoc::Markup::Parser::Error
- RDoc::Markup::Parser::ParseError
- RDoc::Markup::PreProcess
- RDoc::Markup::Raw
- RDoc::Markup::Rule
- RDoc::Markup::Special
- RDoc::Markup::TextFormatterTestCase
- RDoc::Markup::ToAnsi
- RDoc::Markup::ToBs
- RDoc::Markup::ToHtml
- RDoc::Markup::ToHtmlCrossref
- RDoc::Markup::ToHtmlSnippet
- RDoc::Markup::ToJoinedParagraph
- RDoc::Markup::ToLabel
- RDoc::Markup::ToMarkdown
- RDoc::Markup::ToRdoc
- RDoc::Markup::ToTableOfContents
- RDoc::Markup::ToTest
- RDoc::Markup::ToTtOnly
- RDoc::Markup::Verbatim
- RDoc::MetaMethod
- RDoc::MethodAttr
- RDoc::Mixin
- RDoc::NormalClass
- RDoc::NormalModule
- RDoc::Options
- RDoc::Parser
- RDoc::Parser::C
- RDoc::Parser::ChangeLog
- RDoc::Parser::Markdown
- RDoc::Parser::RD
- RDoc::Parser::Ruby
- RDoc::Parser::RubyTools
- RDoc::Parser::Simple
- RDoc::Parser::Text
- RDoc::RD
- RDoc::RD::BlockParser
- RDoc::RD::Inline
- RDoc::RD::InlineParser
- RDoc::RDoc
- RDoc::RI
- RDoc::RI::Driver
- RDoc::RI::Driver::Error
- RDoc::RI::Driver::NotFoundError
- RDoc::RI::Error
- RDoc::RI::Paths
- RDoc::Require
- RDoc::RubyLex
- RDoc::RubyLex::Error
- RDoc::RubyToken
- RDoc::RubygemsHook
- RDoc::Servlet
- RDoc::SingleClass
- RDoc::Stats
- RDoc::Stats::Normal
- RDoc::Stats::Quiet
- RDoc::Stats::Verbose
- RDoc::Store
- RDoc::Store::Error
- RDoc::Store::MissingFileError
- RDoc::Task
- RDoc::Task
- RDoc::TestCase
- RDoc::TokenStream
- RDoc::TomDoc
- RDoc::TopLevel
- Object

No matching classes.

# RDoc::Servlet

This is a WEBrick servlet that allows you to browse ri documentation.

You can show documentation through either `ri --server` or, with RubyGems 2.0 or newer, `gem server`. For ri, the server runs on port 8214 by default. For RubyGems the server runs on port 8808 by default.

You can use this servlet in your own project by mounting it on a WEBrick server:

    require 'webrick'

    server = WEBrick::HTTPServer.new Port: 8000

    server.mount '/', RDoc::Servlet

If you want to mount the servlet some other place than the root, provide the base path when mounting:

    server.mount '/rdoc', RDoc::Servlet, '/rdoc'

### Attributes

asset_dirs[R]

Maps an asset type to its path on the filesystem

options[R]

An RDoc::Options instance used for rendering options

### Public Class Methods

new(server, stores, cache, mount_path = nil, extra_doc_dirs = []) click to toggle source

Creates a new WEBrick servlet.

Use `mount_path` when mounting the servlet somewhere other than /.

Use `extra_doc_dirs` for additional documentation directories.

`server` is provided automatically by WEBrick when mounting. `stores` and `cache` are provided automatically by the servlet.

    # File lib/rdoc/servlet.rb, line 61
    def initialize server, stores, cache, mount_path = nil, extra_doc_dirs = []
      super server

      @cache      = cache
      @mount_path = mount_path
      @extra_doc_dirs = extra_doc_dirs
      @stores     = stores

      @options = RDoc::Options.new
      @options.op_dir = '.'

      darkfish_dir = nil

      # HACK dup
      $LOAD_PATH.each do |path|
        darkfish_dir = File.join path, 'rdoc/generator/template/darkfish/'
        next unless File.directory? darkfish_dir
        @options.template_dir = darkfish_dir
        break
      end

      @asset_dirs = {
        :darkfish   => darkfish_dir,
        :json_index =>
          File.expand_path('../generator/template/json_index/', __FILE__),
      }
    end

### Public Instance Methods

asset(generator_name, req, res) click to toggle source

Serves the asset at the path in `req` for `generator_name` via `res`.

    # File lib/rdoc/servlet.rb, line 92
    def asset generator_name, req, res
      asset_dir = @asset_dirs[generator_name]

      asset_path = File.join asset_dir, req.path

      if_modified_since req, res, asset_path

      res.body = File.read asset_path

      res.content_type = case req.path
                         when /css$/ then 'text/css'
                         when /js$/  then 'application/javascript'
                         else             'application/octet-stream'
                         end
    end

do_GET(req, res) click to toggle source

GET request entry point. Fills in `res` for the path, etc. in `req`.

    # File lib/rdoc/servlet.rb, line 111
    def do_GET req, res
      req.path.sub!(/^#{Regexp.escape @mount_path}/, '') if @mount_path

      case req.path
      when '/' then
        root req, res
      when '/rdoc.css', '/js/darkfish.js', '/js/jquery.js', '/js/search.js',
           %^/images/% then
        asset :darkfish, req, res
      when '/js/navigation.js', '/js/searcher.js' then
        asset :json_index, req, res
      when '/js/search_index.js' then
        root_search req, res
      else
        show_documentation req, res
      end
    rescue WEBrick::HTTPStatus::NotFound => e
      generator = generator_for RDoc::Store.new

      not_found generator, req, res, e.message
    rescue WEBrick::HTTPStatus::Status
      raise
    rescue => e
      error e, req, res
    end

documentation_page(store, generator, path, req, res) click to toggle source

Fills in `res` with the class, module or page for `req` from `store`.

`path` is relative to the mount_path and is used to determine the class, module or page name (/RDoc/Servlet.html becomes RDoc::Servlet). `generator` is used to create the page.

    # File lib/rdoc/servlet.rb, line 144
    def documentation_page store, generator, path, req, res
      name = path.sub(/.html$/, '').gsub '/', '::'

      if klass = store.find_class_or_module(name) then
        res.body = generator.generate_class klass
      elsif page = store.find_text_page(name.sub(/_([^_]*)$/, '.\1')) then
        res.body = generator.generate_page page
      else
        not_found generator, req, res
      end
    end

documentation_search(store, generator, req, res) click to toggle source

Creates the JSON search index on `res` for the given `store`. `generator` must respond to #json_index to build. `req` is ignored.

    # File lib/rdoc/servlet.rb, line 160
    def documentation_search store, generator, req, res
      json_index = @cache[store].fetch :json_index do
        @cache[store][:json_index] =
          JSON.dump generator.json_index.build_index
      end

      res.content_type = 'application/javascript'
      res.body = "var search_data = #{json_index}"
    end

documentation_source(path) click to toggle source

Returns the RDoc::Store and path relative to `mount_path` for documentation at `path`.

    # File lib/rdoc/servlet.rb, line 174
    def documentation_source path
      _, source_name, path = path.split '/', 3

      store = @stores[source_name]
      return store, path if store

      store = store_for source_name

      store.load_all

      @stores[source_name] = store

      return store, path
    end

error(exception, req, res) click to toggle source

Generates an error page for the `exception` while handling `req` on `res`.

    # File lib/rdoc/servlet.rb, line 192
    def error exception, req, res
      backtrace = exception.backtrace.join "\n"

      res.content_type = 'text/html'
      res.status = 500
      res.body = <!DOCTYPE html><html><head><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><title>Error - #{ERB::Util.html_escape exception.class}</title><link type="text/css" media="screen" href="#{@mount_path}/rdoc.css" rel="stylesheet"></head><body><h1>Error</h1><p>While processing <code>#{ERB::Util.html_escape req.request_uri}</code> theRDoc (#{ERB::Util.html_escape RDoc::VERSION}) server has encountered a<code>#{ERB::Util.html_escape exception.class}</code>exception:<pre>#{ERB::Util.html_escape exception.message}</pre><p>Please report this to the<a href="https://github.com/rdoc/rdoc/issues">RDoc issues tracker</a>.  Pleaseinclude the RDoc version, the URI above and exception class, message andbacktrace.  If you're viewing a gem's documentation, include the gem name andversion.  If you're viewing Ruby's documentation, include the version of ruby.<p>Backtrace:<pre>#{ERB::Util.html_escape backtrace}</pre></body></html>
    end

generator_for(store) click to toggle source

Instantiates a Darkfish generator for `store`

    # File lib/rdoc/servlet.rb, line 235
    def generator_for store
      generator = RDoc::Generator::Darkfish.new store, @options
      generator.file_output = false
      generator.asset_rel_path = '..'

      rdoc = RDoc::RDoc.new
      rdoc.store     = store
      rdoc.generator = generator
      rdoc.options   = @options

      @options.main_page = store.main
      @options.title     = store.title

      generator
    end

if_modified_since(req, res, path = nil) click to toggle source

Handles the If-Modified-Since HTTP header on `req` for `path`. If the file has not been modified a Not Modified response is returned. If the file has been modified a Last-Modified header is added to `res`.

    # File lib/rdoc/servlet.rb, line 256
    def if_modified_since req, res, path = nil
      last_modified = File.stat(path).mtime if path

      res['last-modified'] = last_modified.httpdate

      return unless ims = req['if-modified-since']

      ims = Time.parse ims

      unless ims < last_modified then
        res.body = ''
        raise WEBrick::HTTPStatus::NotModified
      end
    end

installed_docs() click to toggle source

Returns an Array of installed documentation.

Each entry contains the documentation name (gem name, 'Ruby Documentation', etc.), the path relative to the mount point, whether the documentation exists, the type of documentation (See RDoc::RI::Paths#each) and the filesystem to the RDoc::Store for the documentation.

    # File lib/rdoc/servlet.rb, line 279
    def installed_docs
      extra_counter = 0
      ri_paths.map do |path, type|
        store = RDoc::Store.new path, type
        exists = File.exist? store.cache_path

        case type
        when :gem then
          gem_path = path[%/([^/]*)/ri$%, 1]
          [gem_path, "#{gem_path}/", exists, type, path]
        when :system then
          ['Ruby Documentation', 'ruby/', exists, type, path]
        when :site then
          ['Site Documentation', 'site/', exists, type, path]
        when :home then
          ['Home Documentation', 'home/', exists, type, path]
        when :extra then
          extra_counter += 1
          store.load_cache if exists
          title = store.title || "Extra Documentation"
          [title, "extra-#{extra_counter}/", exists, type, path]
        end
      end
    end

not_found(generator, req, res, message = nil) click to toggle source

Returns a 404 page built by `generator` for `req` on `res`.

    # File lib/rdoc/servlet.rb, line 307
    def not_found generator, req, res, message = nil
      message ||= "The page <kbd>#{ERB::Util.h req.path}</kbd> was not found"
      res.body = generator.generate_servlet_not_found message
      res.status = 404
    end

ri_paths(&block) click to toggle source

Enumerates the ri paths. See RDoc::RI::Paths#each

    # File lib/rdoc/servlet.rb, line 316
    def ri_paths &block
      RDoc::RI::Paths.each true, true, true, :all, *@extra_doc_dirs, &block #TODO: pass extra_dirs
    end

root(req, res) click to toggle source

Generates the root page on `res`. `req` is ignored.

    # File lib/rdoc/servlet.rb, line 323
    def root req, res
      generator = RDoc::Generator::Darkfish.new nil, @options

      res.body = generator.generate_servlet_root installed_docs

      res.content_type = 'text/html'
    end

root_search(req, res) click to toggle source

Generates a search index for the root page on `res`. `req` is ignored.

    # File lib/rdoc/servlet.rb, line 334
    def root_search req, res
      search_index = []
      info         = []

      installed_docs.map do |name, href, exists, type, path|
        next unless exists

        search_index << name

        case type
        when :gem
          gemspec = path.gsub(%/doc/([^/]*?)/ri$%,
                              '/specifications/\1.gemspec')

          spec = Gem::Specification.load gemspec

          path    = spec.full_name
          comment = spec.summary
        when :system then
          path    = 'ruby'
          comment = 'Documentation for the Ruby standard library'
        when :site then
          path    = 'site'
          comment = 'Documentation for non-gem libraries'
        when :home then
          path    = 'home'
          comment = 'Documentation from your home directory'
        when :extra
          comment = name
        end

        info << [name, '', path, '', comment]
      end

      index = {
        :index => {
          :searchIndex     => search_index,
          :longSearchIndex => search_index,
          :info            => info,
        }
      }

      res.body = "var search_data = #{JSON.dump index};"
      res.content_type = 'application/javascript'
    end

show_documentation(req, res) click to toggle source

Displays documentation for `req` on `res`, whether that be HTML or some asset.

    # File lib/rdoc/servlet.rb, line 384
    def show_documentation req, res
      store, path = documentation_source req.path

      if_modified_since req, res, store.cache_path

      generator = generator_for store

      case path
      when nil, '', 'index.html' then
        res.body = generator.generate_index
      when 'table_of_contents.html' then
        res.body = generator.generate_table_of_contents
      when 'js/search_index.js' then
        documentation_search store, generator, req, res
      else
        documentation_page store, generator, path, req, res
      end
    ensure
      res.content_type ||= 'text/html'
    end

store_for(source_name) click to toggle source

Returns an RDoc::Store for the given `source_name` ('ruby' or a gem name).

    # File lib/rdoc/servlet.rb, line 408
    def store_for source_name
      case source_name
      when 'home' then
        RDoc::Store.new RDoc::RI::Paths.home_dir, :home
      when 'ruby' then
        RDoc::Store.new RDoc::RI::Paths.system_dir, :system
      when 'site' then
        RDoc::Store.new RDoc::RI::Paths.site_dir, :site
      when /^extra-(\d+)$/ then
        index = $1.to_i - 1
        ri_dir = installed_docs[index][4]
        RDoc::Store.new ri_dir, :extra
      else
        ri_dir, type = ri_paths.find do |dir, dir_type|
          next unless dir_type == :gem

          source_name == dir[%/([^/]*)/ri$%, 1]
        end

        raise WEBrick::HTTPStatus::NotFound,
              "Could not find gem \"#{source_name}\". Are you sure you installed it?" unless ri_dir

        store = RDoc::Store.new ri_dir, type

        return store if File.exist? store.cache_path

        raise WEBrick::HTTPStatus::NotFound,
              "Could not find documentation for \"#{source_name}\". Please run `gem rdoc --ri gem_name`"

      end
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.