require'action_dispatch/http/request'require'active_support/core_ext/uri'require'active_support/core_ext/array/extract_options'require'rack/utils'require'action_controller/metal/exceptions'require'action_dispatch/routing/endpoint'moduleActionDispatchmoduleRoutingclassRedirect<Endpoint# :nodoc:attr_reader:status,:blockdefinitialize(status,block)@status=status@block=blockenddefredirect?;true;enddefcall(env)serveRequest.newenvenddefserve(req)uri=URI.parse(path(req.path_parameters,req))unlessuri.hostifrelative_path?(uri.path)uri.path="#{req.script_name}/#{uri.path}"elsifuri.path.empty?uri.path=req.script_name.empty??"/":req.script_nameendenduri.scheme||=req.schemeuri.host||=req.hosturi.port||=req.portunlessreq.standard_port?req.commit_flashbody=%(<html><body>You are being <a href="#{ERB::Util.unwrapped_html_escape(uri.to_s)}">redirected</a>.</body></html>)headers={'Location'=>uri.to_s,'Content-Type'=>'text/html','Content-Length'=>body.length.to_s}[status,headers,[body]]enddefpath(params,request)block.callparams,requestenddefinspect"redirect(#{status})"endprivatedefrelative_path?(path)path&&!path.empty?&&path[0]!='/'enddefescape(params)Hash[params.map{|k,v|[k,Rack::Utils.escape(v)]}]enddefescape_fragment(params)Hash[params.map{|k,v|[k,Journey::Router::Utils.escape_fragment(v)]}]enddefescape_path(params)Hash[params.map{|k,v|[k,Journey::Router::Utils.escape_path(v)]}]endendclassPathRedirect<RedirectURL_PARTS=/\A([^?]+)?(\?[^#]+)?(#.+)?\z/defpath(params,request)ifblock.match(URL_PARTS)path=interpolation_required?($1,params)?$1%escape_path(params):$1query=interpolation_required?($2,params)?$2%escape(params):$2fragment=interpolation_required?($3,params)?$3%escape_fragment(params):$3"#{path}#{query}#{fragment}"elseinterpolation_required?(block,params)?block%escape(params):blockendenddefinspect"redirect(#{status}, #{block})"endprivatedefinterpolation_required?(string,params)!params.empty?&&string&&string.match(/%\{\w*\}/)endendclassOptionRedirect<Redirect# :nodoc:alias:options:blockdefpath(params,request)url_options={:protocol=>request.protocol,:host=>request.host,:port=>request.optional_port,:path=>request.path,:params=>request.query_parameters}.merge!optionsif!params.empty?&&url_options[:path].match(/%\{\w*\}/)url_options[:path]=(url_options[:path]%escape_path(params))endunlessoptions[:host]||options[:domain]ifrelative_path?(url_options[:path])url_options[:path]="/#{url_options[:path]}"url_options[:script_name]=request.script_nameelsifurl_options[:path].empty?url_options[:path]=request.script_name.empty??"/":""url_options[:script_name]=request.script_nameendendActionDispatch::Http::URL.url_forurl_optionsenddefinspect"redirect(#{status}, #{options.map{|k,v|"#{k}: #{v}"}.join(', ')})"endendmoduleRedirection# Redirect any path to another path:## get "/stories" => redirect("/posts")## You can also use interpolation in the supplied redirect argument:## get 'docs/:article', to: redirect('/wiki/%{article}')## Note that if you return a path without a leading slash then the url is prefixed with the# current SCRIPT_NAME environment variable. This is typically '/' but may be different in# a mounted engine or where the application is deployed to a subdirectory of a website.## Alternatively you can use one of the other syntaxes:## The block version of redirect allows for the easy encapsulation of any logic associated with# the redirect in question. Either the params and request are supplied as arguments, or just# params, depending of how many arguments your block accepts. A string is required as a# return value.## get 'jokes/:number', to: redirect { |params, request|# path = (params[:number].to_i.even? ? "wheres-the-beef" : "i-love-lamp")# "http://#{request.host_with_port}/#{path}"# }## Note that the +do end+ syntax for the redirect block wouldn't work, as Ruby would pass# the block to +get+ instead of +redirect+. Use <tt>{ ... }</tt> instead.## The options version of redirect allows you to supply only the parts of the url which need# to change, it also supports interpolation of the path similar to the first example.## get 'stores/:name', to: redirect(subdomain: 'stores', path: '/%{name}')# get 'stores/:name(*all)', to: redirect(subdomain: 'stores', path: '/%{name}%{all}')## Finally, an object which responds to call can be supplied to redirect, allowing you to reuse# common redirect routes. The call method must accept two arguments, params and request, and return# a string.## get 'accounts/:name' => redirect(SubdomainRedirector.new('api'))#defredirect(*args,&block)options=args.extract_options!status=options.delete(:status)||301path=args.shiftreturnOptionRedirect.new(status,options)ifoptions.any?returnPathRedirect.new(status,path)ifString===pathblock=pathifpath.respond_to?:callraiseArgumentError,"redirection argument not supported"unlessblockRedirect.newstatus,blockendendendend