# frozen_string_literal: truemoduleGrapemoduleDSLmoduleRoutingextendActiveSupport::ConcernincludeGrape::DSL::ConfigurationmoduleClassMethodsattr_reader:endpoints# Specify an API version.## @example API with legacy support.# class MyAPI < Grape::API# version 'v2'## get '/main' do# {some: 'data'}# end## version 'v1' do# get '/main' do# {legacy: 'data'}# end# end# end#defversion(*args,&block)ifargs.any?options=args.extract_options!options=options.reverse_merge(using: :path)requested_versions=args.flattenraiseGrape::Exceptions::MissingVendorOption.newifoptions[:using]==:header&&!options.key?(:vendor)@versions=versions|requested_versionsifblockwithin_namespacedonamespace_inheritable(:version,requested_versions)namespace_inheritable(:version_options,options)instance_eval(&block)endelsenamespace_inheritable(:version,requested_versions)namespace_inheritable(:version_options,options)endend@versions.lastifinstance_variable_defined?(:@versions)&&@versionsend# Define a root URL prefix for your entire API.defprefix(prefix=nil)namespace_inheritable(:root_prefix,prefix)end# Create a scope without affecting the URL.## @param _name [Symbol] Purely placebo, just allows to name the scope to# make the code more readable.defscope(_name=nil,&block)within_namespacedonest(block)endend# Do not route HEAD requests to GET requests automatically.defdo_not_route_head!namespace_inheritable(:do_not_route_head,true)end# Do not automatically route OPTIONS.defdo_not_route_options!namespace_inheritable(:do_not_route_options,true)enddefdo_not_document!namespace_inheritable(:do_not_document,true)enddefmount(mounts,*opts)mounts={mounts=>'/'}unlessmounts.respond_to?(:each_pair)mounts.each_pairdo|app,path|ifapp.respond_to?(:mount_instance)opts_with=opts.any??opts.shift[:with]:{}mount({app.mount_instance(configuration: opts_with)=>path})nextendin_setting=inheritable_settingifapp.respond_to?(:inheritable_setting,true)mount_path=Grape::Router.normalize_path(path)app.top_level_setting.namespace_stackable[:mount_path]=mount_pathapp.inherit_settings(inheritable_setting)in_setting=app.top_level_settingapp.change!change!endendpoints<<Grape::Endpoint.new(in_setting,method: :any,path: path,app: app,route_options: {anchor: false},forward_match: !app.respond_to?(:inheritable_setting),for: self)endend# Defines a route that will be recognized# by the Grape API.## @param methods [HTTP Verb] One or more HTTP verbs that are accepted by this route. Set to `:any` if you want any verb to be accepted.# @param paths [String] One or more strings representing the URL segment(s) for this route.## @example Defining a basic route.# class MyAPI < Grape::API# route(:any, '/hello') do# {hello: 'world'}# end# enddefroute(methods,paths=['/'],route_options={},&block)methods='*'ifmethods==:anyendpoint_options={method: methods,path: paths,for: self,route_options: {params: namespace_stackable_with_hash(:params)||{}}.deep_merge(route_setting(:description)||{}).deep_merge(route_options||{})}new_endpoint=Grape::Endpoint.new(inheritable_setting,endpoint_options,&block)endpoints<<new_endpointunlessendpoints.any?{|e|e.equals?(new_endpoint)}route_endreset_validations!endGrape::Http::Headers::SUPPORTED_METHODS.eachdo|supported_method|define_methodsupported_method.downcasedo|*args,&block|options=args.extract_options!paths=args.first||['/']route(supported_method,paths,options,&block)endend# Declare a "namespace", which prefixes all subordinate routes with its# name. Any endpoints within a namespace, group, resource or segment,# etc., will share their parent context as well as any configuration# done in the namespace context.## @example## namespace :foo do# get 'bar' do# # defines the endpoint: GET /foo/bar# end# enddefnamespace(space=nil,options={},&block)@namespace_description=nilunlessinstance_variable_defined?(:@namespace_description)&&@namespace_descriptionifspace||blockwithin_namespacedoprevious_namespace_description=@namespace_description@namespace_description=(@namespace_description||{}).deep_merge(namespace_setting(:description)||{})nest(block)donamespace_stackable(:namespace,Namespace.new(space,**options))ifspaceend@namespace_description=previous_namespace_descriptionendelseNamespace.joined_space_path(namespace_stackable(:namespace))endendaliasgroupnamespacealiasresourcenamespacealiasresourcesnamespacealiassegmentnamespace# An array of API routes.defroutes@routes||=prepare_routesend# Remove all defined routes.defreset_routes!endpoints.each(&:reset_routes!)@routes=nilenddefreset_endpoints!@endpoints=[]end# This method allows you to quickly define a parameter route segment# in your API.## @param param [Symbol] The name of the parameter you wish to declare.# @option options [Regexp] You may supply a regular expression that the declared parameter must meet.defroute_param(param,options={},&block)options=options.dupoptions[:requirements]={param.to_sym=>options[:requirements]}ifoptions[:requirements].is_a?(Regexp)Grape::Validations::ParamsScope.new(api: self)dorequiresparam,type: options[:type]endifoptions.key?(:type)namespace(":#{param}",options,&block)end# @return array of defined versionsdefversions@versions||=[]endendendendend