app/controllers/apipie/apipies_controller.rb
module Apipie
class ApipiesController < ActionController::Base
include ActionView::Context
include ApipieHelper
layout Apipie.configuration.layout
around_action :set_script_name
before_action :authenticate
def authenticate
if Apipie.configuration.authenticate
instance_eval(&Apipie.configuration.authenticate)
end
end
def index
params[:version] ||= Apipie.configuration.default_version
get_format
if params[:type].to_s == 'swagger' && params[:format].to_s == 'json'
head :forbidden and return if Apipie.configuration.authorize
should_render_swagger = true
end
respond_to do |format|
if Apipie.configuration.use_cache?
render_from_cache
return
end
@language = get_language
Apipie.load_documentation if Apipie.configuration.reload_controllers? || !Rails.application.config.eager_load
I18n.locale = @language
if should_render_swagger
prev_warning_value = Apipie.configuration.generator.swagger.suppress_warnings
begin
Apipie.configuration.generator.swagger.suppress_warnings = true
@doc = Apipie.to_swagger_json(params[:version], params[:resource], params[:method], @language)
ensure
Apipie.configuration.generator.swagger.suppress_warnings = prev_warning_value
end
else
@doc = Apipie.to_json(params[:version], params[:resource], params[:method], @language)
@doc = authorized_doc
end
format.json do
if @doc
render :json => @doc
else
head :not_found
end
end
format.html do
unless @doc
render 'apipie_404', :status => 404
return
end
@versions = Apipie.available_versions
@doc = @doc[:docs]
@doc[:link_extension] = (@language ? ".#{@language}" : '')+Apipie.configuration.link_extension
if @doc[:resources].blank?
render "getting_started" and return
end
@resource = @doc[:resources].first if params[:resource].present?
@method = @resource[:methods].first if params[:method].present?
@languages = Apipie.configuration.languages
if @resource && @method
render 'method'
elsif @resource
render 'resource'
elsif params[:resource].present? || params[:method].present?
render 'apipie_404', :status => 404
else
render 'index'
end
end
end
end
def apipie_checksum
end
private
helper_method :heading
def get_language
return nil unless Apipie.configuration.translate
lang = Apipie.configuration.default_locale
[:resource, :method, :version].each do |par|
next unless params[par]
splitted = params[par].split('.')
if splitted.length > 1 && (Apipie.configuration.languages.include?(splitted.last) || Apipie.configuration.default_locale == splitted.last)
lang = splitted.last
params[par].sub!(".#{lang}", '')
end
end
lang
end
def authorized_doc
return if @doc.nil?
return @doc unless Apipie.configuration.authorize
new_doc = { :docs => @doc[:docs].clone }
new_doc[:docs][:resources] = if @doc[:docs][:resources].kind_of?(Array)
@doc[:docs][:resources].select do |resource|
authorize_resource(resource)
end
else
@doc[:docs][:resources].select do |_resource_id, resource|
authorize_resource(resource)
end
end
new_doc
end
def authorize_resource resource
if instance_exec(resource[:id], nil, resource, &Apipie.configuration.authorize)
resource[:methods] = resource[:methods].select do |m|
instance_exec(resource[:id], m[:name], m, &Apipie.configuration.authorize)
end
true
else
false
end
end
def get_format
[:resource, :method, :version].each do |par|
next unless params[par]
[:html, :json].each do |format|
extension = ".#{format}"
if params[par].include?(extension)
params[par] = params[par].sub(extension, '')
params[:format] = format
end
end
end
request.format = params[:format] if params[:format]
end
def render_from_cache
path = Apipie.configuration.doc_base_url.dup
path << "/" << params[:version] if params[:version].present?
path << "/" << params[:resource] if params[:resource].present?
path << "/" << params[:method] if params[:method].present?
# Sanitize path against directory traversal attacks (e.g. ../../foo)
# by turning path into an absolute path before appending it to the cache dir
path = File.expand_path("#{path}.#{request.format.symbol}", '/')
cache_file = File.join(Apipie.configuration.cache_dir, path)
if File.exist?(cache_file)
content_type = case params[:format]
when "json" then "application/json"
else "text/html"
end
send_file cache_file, :type => content_type, :disposition => "inline"
else
Rails.logger.error("API doc cache not found for '#{path}'. Perhaps you have forgot to run `rake apipie:cache`")
head :not_found
end
end
def set_script_name
Apipie.request_script_name = request.env["SCRIPT_NAME"]
yield
ensure
Apipie.request_script_name = nil
end
end
end