on 404 redirect for /owner/name paths on v1
This commit is contained in:
parent
a7d72beefc
commit
f8bd49e88b
|
@ -16,84 +16,93 @@ require 'newrelic_rpm'
|
|||
# run Travis::Api::App.new
|
||||
#
|
||||
# Requires TLS in production.
|
||||
class Travis::Api::App
|
||||
autoload :AccessToken, 'travis/api/app/access_token'
|
||||
autoload :Base, 'travis/api/app/base'
|
||||
autoload :Endpoint, 'travis/api/app/endpoint'
|
||||
autoload :Extensions, 'travis/api/app/extensions'
|
||||
autoload :Helpers, 'travis/api/app/helpers'
|
||||
autoload :Middleware, 'travis/api/app/middleware'
|
||||
autoload :Responders, 'travis/api/app/responders'
|
||||
module Travis::Api
|
||||
ACCEPT_VERSION = /vnd\.travis-ci\.(\d+)\+/
|
||||
DEFAULT_VERSION = 'v2'
|
||||
|
||||
Rack.autoload :SSL, 'rack/ssl'
|
||||
|
||||
# Used to track if setup already ran.
|
||||
def self.setup?
|
||||
@setup ||= false
|
||||
def version(string)
|
||||
string =~ ACCEPT_VERSION && "v#{$1}" || DEFAULT_VERSION
|
||||
end
|
||||
|
||||
# Loads all endpoints and middleware and hooks them up properly.
|
||||
# Calls #setup on any middleware and endpoint.
|
||||
#
|
||||
# This method is not threadsafe, but called when loading
|
||||
# the environment, so no biggy.
|
||||
def self.setup(options = {})
|
||||
setup! unless setup?
|
||||
Endpoint.set(options)
|
||||
end
|
||||
class App
|
||||
autoload :AccessToken, 'travis/api/app/access_token'
|
||||
autoload :Base, 'travis/api/app/base'
|
||||
autoload :Endpoint, 'travis/api/app/endpoint'
|
||||
autoload :Extensions, 'travis/api/app/extensions'
|
||||
autoload :Helpers, 'travis/api/app/helpers'
|
||||
autoload :Middleware, 'travis/api/app/middleware'
|
||||
autoload :Responders, 'travis/api/app/responders'
|
||||
|
||||
def self.new(options = {})
|
||||
setup(options) if options
|
||||
super()
|
||||
end
|
||||
Rack.autoload :SSL, 'rack/ssl'
|
||||
|
||||
attr_accessor :app
|
||||
# Used to track if setup already ran.
|
||||
def self.setup?
|
||||
@setup ||= false
|
||||
end
|
||||
|
||||
def initialize
|
||||
@app = Rack::Builder.app do
|
||||
use Hubble::Rescuer, env: Travis.env, codename: ENV['CODENAME'] if Endpoint.production? && ENV['HUBBLE_ENDPOINT']
|
||||
use Rack::Protection::PathTraversal
|
||||
use Rack::SSL if Endpoint.production?
|
||||
use Rack::Deflater
|
||||
use Rack::PostBodyContentTypeParser
|
||||
use Rack::JSONP
|
||||
use ActiveRecord::ConnectionAdapters::ConnectionManagement
|
||||
# Loads all endpoints and middleware and hooks them up properly.
|
||||
# Calls #setup on any middleware and endpoint.
|
||||
#
|
||||
# This method is not threadsafe, but called when loading
|
||||
# the environment, so no biggy.
|
||||
def self.setup(options = {})
|
||||
setup! unless setup?
|
||||
Endpoint.set(options)
|
||||
end
|
||||
|
||||
use Rack::Config do |env|
|
||||
env['travis.global_prefix'] = env['SCRIPT_NAME']
|
||||
def self.new(options = {})
|
||||
setup(options) if options
|
||||
super()
|
||||
end
|
||||
|
||||
attr_accessor :app
|
||||
|
||||
def initialize
|
||||
@app = Rack::Builder.app do
|
||||
use Hubble::Rescuer, env: Travis.env, codename: ENV['CODENAME'] if Endpoint.production? && ENV['HUBBLE_ENDPOINT']
|
||||
use Rack::Protection::PathTraversal
|
||||
use Rack::SSL if Endpoint.production?
|
||||
use Rack::Deflater
|
||||
use Rack::PostBodyContentTypeParser
|
||||
use Rack::JSONP
|
||||
use ActiveRecord::ConnectionAdapters::ConnectionManagement
|
||||
|
||||
use Rack::Config do |env|
|
||||
env['travis.global_prefix'] = env['SCRIPT_NAME']
|
||||
end
|
||||
|
||||
Middleware.subclasses.each { |m| use(m) }
|
||||
Endpoint.subclasses.each { |e| map(e.prefix) { run(e.new) } }
|
||||
end
|
||||
end
|
||||
|
||||
# Rack protocol
|
||||
def call(env)
|
||||
app.call(env)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.setup!
|
||||
setup_travis
|
||||
load_endpoints
|
||||
setup_endpoints
|
||||
@setup = true
|
||||
end
|
||||
|
||||
Middleware.subclasses.each { |m| use(m) }
|
||||
Endpoint.subclasses.each { |e| map(e.prefix) { run(e.new) } }
|
||||
end
|
||||
def self.setup_travis
|
||||
Travis::Amqp.config = Travis.config.amqp
|
||||
Travis::Database.connect
|
||||
Travis.services = Travis::Services
|
||||
end
|
||||
|
||||
def self.load_endpoints
|
||||
Backports.require_relative_dir 'app/middleware'
|
||||
Backports.require_relative_dir 'app/endpoint'
|
||||
end
|
||||
|
||||
def self.setup_endpoints
|
||||
Base.subclasses.each(&:setup)
|
||||
end
|
||||
end
|
||||
|
||||
# Rack protocol
|
||||
def call(env)
|
||||
app.call(env)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.setup!
|
||||
setup_travis
|
||||
load_endpoints
|
||||
setup_endpoints
|
||||
@setup = true
|
||||
end
|
||||
|
||||
def self.setup_travis
|
||||
Travis::Amqp.config = Travis.config.amqp
|
||||
Travis::Database.connect
|
||||
Travis.services = Travis::Services
|
||||
end
|
||||
|
||||
def self.load_endpoints
|
||||
Backports.require_relative_dir 'app/middleware'
|
||||
Backports.require_relative_dir 'app/endpoint'
|
||||
end
|
||||
|
||||
def self.setup_endpoints
|
||||
Base.subclasses.each(&:setup)
|
||||
end
|
||||
end
|
||||
|
|
30
lib/travis/api/app/middleware/rewrite.rb
Normal file
30
lib/travis/api/app/middleware/rewrite.rb
Normal file
|
@ -0,0 +1,30 @@
|
|||
require 'travis/api/app'
|
||||
|
||||
class Travis::Api::App
|
||||
class Middleware
|
||||
class Rewrite < Middleware
|
||||
V1_REPO_URL = %r(^(/[^/]+/[^/]+(?:/builds(?:/[\d]+)?|/cc\.xml)?)$)
|
||||
|
||||
set(:setup) { ActiveRecord::Base.logger = Travis.logger }
|
||||
|
||||
after do
|
||||
p not_found?
|
||||
force_redirect("/repositories#{$1}") if response.status == 404 && version == 'v1' && request.path =~ V1_REPO_URL
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def force_redirect(path)
|
||||
response.body = ''
|
||||
response['Content-Length'] = '0'
|
||||
response['Content-Type'] = ''
|
||||
redirect(path)
|
||||
end
|
||||
|
||||
def version
|
||||
API.version(request.accept.join)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,8 +1,5 @@
|
|||
module Travis::Api::App::Responders
|
||||
class Json < Base
|
||||
ACCEPT_VERSION = /vnd\.travis-ci\.(\d+)\+/
|
||||
DEFAULT_VERSION = 'v2'
|
||||
|
||||
def apply?
|
||||
options[:format] == 'json' && !resource.is_a?(String)
|
||||
end
|
||||
|
@ -22,7 +19,7 @@ module Travis::Api::App::Responders
|
|||
end
|
||||
|
||||
def version
|
||||
request.accept.join =~ ACCEPT_VERSION && "v#{$1}" || DEFAULT_VERSION
|
||||
API.version(request.accept.join)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -31,14 +31,14 @@ describe 'Repos' do
|
|||
response.should deliver_json_for(Repository.by_slug('svenfuchs/minimal').first, version: 'v1')
|
||||
end
|
||||
|
||||
xit 'GET /svenfuchs/minimal' do
|
||||
it 'GET /svenfuchs/minimal' do
|
||||
response = get '/svenfuchs/minimal', {}, headers
|
||||
response.should deliver_json_for(Repository.by_slug('svenfuchs/minimal').first, version: 'v1')
|
||||
response.should redirect_to('/repositories/svenfuchs/minimal')
|
||||
end
|
||||
|
||||
xit 'GET /svenfuchs/minimal/cc.xml' do # TODO wat.
|
||||
it 'GET /svenfuchs/minimal/cc.xml' do
|
||||
response = get '/svenfuchs/minimal/cc.xml'
|
||||
response.should deliver_xml_for()
|
||||
response.should redirect_to('/repositories/svenfuchs/minimal/cc.xml')
|
||||
end
|
||||
|
||||
describe 'GET /svenfuchs/minimal.png' do
|
||||
|
|
|
@ -10,44 +10,7 @@ require 'multi_json'
|
|||
require 'travis/api/app'
|
||||
require 'travis/testing/scenario'
|
||||
require 'travis/testing/factories'
|
||||
|
||||
RSpec::Matchers.define :deliver_json_for do |resource, options = {}|
|
||||
match do |response|
|
||||
actual = parse(response.body)
|
||||
expected = Travis::Api.data(resource, options)
|
||||
|
||||
failure_message_for_should do
|
||||
"expected\n\n#{actual}\n\nto equal\n\n#{expected}"
|
||||
end
|
||||
|
||||
actual == expected
|
||||
end
|
||||
|
||||
def parse(body)
|
||||
MultiJson.decode(body)
|
||||
end
|
||||
end
|
||||
|
||||
RSpec::Matchers.define :deliver_result_image_for do |name|
|
||||
match do |response|
|
||||
actual = files.detect do |(name, content)|
|
||||
response.body.force_encoding('ascii') == content.force_encoding('ascii') # TODO ummmmmmmm?
|
||||
end
|
||||
actual = actual && actual[0]
|
||||
|
||||
failure_message_for_should do
|
||||
"expected #{actual.inspect} to equal #{name.inspect}"
|
||||
end
|
||||
|
||||
actual == name
|
||||
end
|
||||
|
||||
def files
|
||||
files = Hash[*Dir['public/images/result/*.png'].map do |file|
|
||||
[File.basename(file, '.png'), File.read(file)]
|
||||
end.flatten]
|
||||
end
|
||||
end
|
||||
require 'support/matchers'
|
||||
|
||||
Travis.logger = Logger.new(StringIO.new)
|
||||
Travis::Api::App.setup
|
||||
|
|
62
spec/support/matchers.rb
Normal file
62
spec/support/matchers.rb
Normal file
|
@ -0,0 +1,62 @@
|
|||
# TODO move to travis-core?
|
||||
|
||||
RSpec::Matchers.define :deliver_json_for do |resource, options = {}|
|
||||
match do |response|
|
||||
if response.status == 200
|
||||
actual = parse(response.body)
|
||||
expected = Travis::Api.data(resource, options)
|
||||
|
||||
failure_message_for_should do
|
||||
"expected\n\n#{actual}\n\nto equal\n\n#{expected}"
|
||||
end
|
||||
|
||||
actual == expected
|
||||
else
|
||||
failure_message_for_should do
|
||||
"expected the request to be successful (200) but was #{response.status}"
|
||||
end
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def parse(body)
|
||||
MultiJson.decode(body)
|
||||
end
|
||||
end
|
||||
|
||||
RSpec::Matchers.define :deliver_result_image_for do |name|
|
||||
match do |response|
|
||||
actual = files.detect do |(name, content)|
|
||||
response.body.force_encoding('ascii') == content.force_encoding('ascii') # TODO ummmmmmmm?
|
||||
end
|
||||
actual = actual && actual[0]
|
||||
|
||||
failure_message_for_should do
|
||||
"expected #{actual.inspect} to equal #{name.inspect}"
|
||||
end
|
||||
|
||||
actual == name
|
||||
end
|
||||
|
||||
def files
|
||||
files = Hash[*Dir['public/images/result/*.png'].map do |file|
|
||||
[File.basename(file, '.png'), File.read(file)]
|
||||
end.flatten]
|
||||
end
|
||||
end
|
||||
|
||||
RSpec::Matchers.define :redirect_to do |expected|
|
||||
match do |response|
|
||||
actual = response.headers['location'].to_s.sub('http://example.org', '')
|
||||
|
||||
failure_message_for_should do
|
||||
"expected to be redirect to #{expected} but was not. status: #{response.status}, location: #{actual}"
|
||||
end
|
||||
|
||||
failure_message_for_should_not do
|
||||
"expected not to be redirect to #{expected} but was."
|
||||
end
|
||||
|
||||
actual == expected
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user