rack-for_now 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ff14352e01ff998dcfeb6ac9ced829b25310c092
4
+ data.tar.gz: e778bdcfcbf9ec1c6944c3d921de571da3afbda3
5
+ SHA512:
6
+ metadata.gz: 40c732fe933ab39c618009abc31befa2248ae09c5edd027046b13d48476e013db38144c818609542a382335a8d0232ca493fd1eb8522c5a3b8868db43cc6337c
7
+ data.tar.gz: ae1b3deff5069b1a791b257129b00ad1a32e243a8cd14246d39b6dc4571b594308db89cf1465930e95848277955e41a0eb85f6eec7a792f53d8b2137a6649f47
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.0
4
+ - 2.0.0
5
+ - 1.8.7
6
+ - jruby-19mode
7
+ - rbx
@@ -0,0 +1,2 @@
1
+ --markup markdown
2
+ --no-private
@@ -0,0 +1,121 @@
1
+ Creative Commons Legal Code
2
+
3
+ CC0 1.0 Universal
4
+
5
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
6
+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
7
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
8
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
9
+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
10
+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
11
+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
12
+ HEREUNDER.
13
+
14
+ Statement of Purpose
15
+
16
+ The laws of most jurisdictions throughout the world automatically confer
17
+ exclusive Copyright and Related Rights (defined below) upon the creator
18
+ and subsequent owner(s) (each and all, an "owner") of an original work of
19
+ authorship and/or a database (each, a "Work").
20
+
21
+ Certain owners wish to permanently relinquish those rights to a Work for
22
+ the purpose of contributing to a commons of creative, cultural and
23
+ scientific works ("Commons") that the public can reliably and without fear
24
+ of later claims of infringement build upon, modify, incorporate in other
25
+ works, reuse and redistribute as freely as possible in any form whatsoever
26
+ and for any purposes, including without limitation commercial purposes.
27
+ These owners may contribute to the Commons to promote the ideal of a free
28
+ culture and the further production of creative, cultural and scientific
29
+ works, or to gain reputation or greater distribution for their Work in
30
+ part through the use and efforts of others.
31
+
32
+ For these and/or other purposes and motivations, and without any
33
+ expectation of additional consideration or compensation, the person
34
+ associating CC0 with a Work (the "Affirmer"), to the extent that he or she
35
+ is an owner of Copyright and Related Rights in the Work, voluntarily
36
+ elects to apply CC0 to the Work and publicly distribute the Work under its
37
+ terms, with knowledge of his or her Copyright and Related Rights in the
38
+ Work and the meaning and intended legal effect of CC0 on those rights.
39
+
40
+ 1. Copyright and Related Rights. A Work made available under CC0 may be
41
+ protected by copyright and related or neighboring rights ("Copyright and
42
+ Related Rights"). Copyright and Related Rights include, but are not
43
+ limited to, the following:
44
+
45
+ i. the right to reproduce, adapt, distribute, perform, display,
46
+ communicate, and translate a Work;
47
+ ii. moral rights retained by the original author(s) and/or performer(s);
48
+ iii. publicity and privacy rights pertaining to a person's image or
49
+ likeness depicted in a Work;
50
+ iv. rights protecting against unfair competition in regards to a Work,
51
+ subject to the limitations in paragraph 4(a), below;
52
+ v. rights protecting the extraction, dissemination, use and reuse of data
53
+ in a Work;
54
+ vi. database rights (such as those arising under Directive 96/9/EC of the
55
+ European Parliament and of the Council of 11 March 1996 on the legal
56
+ protection of databases, and under any national implementation
57
+ thereof, including any amended or successor version of such
58
+ directive); and
59
+ vii. other similar, equivalent or corresponding rights throughout the
60
+ world based on applicable law or treaty, and any national
61
+ implementations thereof.
62
+
63
+ 2. Waiver. To the greatest extent permitted by, but not in contravention
64
+ of, applicable law, Affirmer hereby overtly, fully, permanently,
65
+ irrevocably and unconditionally waives, abandons, and surrenders all of
66
+ Affirmer's Copyright and Related Rights and associated claims and causes
67
+ of action, whether now known or unknown (including existing as well as
68
+ future claims and causes of action), in the Work (i) in all territories
69
+ worldwide, (ii) for the maximum duration provided by applicable law or
70
+ treaty (including future time extensions), (iii) in any current or future
71
+ medium and for any number of copies, and (iv) for any purpose whatsoever,
72
+ including without limitation commercial, advertising or promotional
73
+ purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
74
+ member of the public at large and to the detriment of Affirmer's heirs and
75
+ successors, fully intending that such Waiver shall not be subject to
76
+ revocation, rescission, cancellation, termination, or any other legal or
77
+ equitable action to disrupt the quiet enjoyment of the Work by the public
78
+ as contemplated by Affirmer's express Statement of Purpose.
79
+
80
+ 3. Public License Fallback. Should any part of the Waiver for any reason
81
+ be judged legally invalid or ineffective under applicable law, then the
82
+ Waiver shall be preserved to the maximum extent permitted taking into
83
+ account Affirmer's express Statement of Purpose. In addition, to the
84
+ extent the Waiver is so judged Affirmer hereby grants to each affected
85
+ person a royalty-free, non transferable, non sublicensable, non exclusive,
86
+ irrevocable and unconditional license to exercise Affirmer's Copyright and
87
+ Related Rights in the Work (i) in all territories worldwide, (ii) for the
88
+ maximum duration provided by applicable law or treaty (including future
89
+ time extensions), (iii) in any current or future medium and for any number
90
+ of copies, and (iv) for any purpose whatsoever, including without
91
+ limitation commercial, advertising or promotional purposes (the
92
+ "License"). The License shall be deemed effective as of the date CC0 was
93
+ applied by Affirmer to the Work. Should any part of the License for any
94
+ reason be judged legally invalid or ineffective under applicable law, such
95
+ partial invalidity or ineffectiveness shall not invalidate the remainder
96
+ of the License, and in such case Affirmer hereby affirms that he or she
97
+ will not (i) exercise any of his or her remaining Copyright and Related
98
+ Rights in the Work or (ii) assert any associated claims and causes of
99
+ action with respect to the Work, in either case contrary to Affirmer's
100
+ express Statement of Purpose.
101
+
102
+ 4. Limitations and Disclaimers.
103
+
104
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
105
+ surrendered, licensed or otherwise affected by this document.
106
+ b. Affirmer offers the Work as-is and makes no representations or
107
+ warranties of any kind concerning the Work, express, implied,
108
+ statutory or otherwise, including without limitation warranties of
109
+ title, merchantability, fitness for a particular purpose, non
110
+ infringement, or the absence of latent or other defects, accuracy, or
111
+ the present or absence of errors, whether or not discoverable, all to
112
+ the greatest extent permissible under applicable law.
113
+ c. Affirmer disclaims responsibility for clearing rights of other persons
114
+ that may apply to the Work or any use thereof, including without
115
+ limitation any person's Copyright and Related Rights in the Work.
116
+ Further, Affirmer disclaims responsibility for obtaining any necessary
117
+ consents, permissions or other rights required for any use of the
118
+ Work.
119
+ d. Affirmer understands and acknowledges that Creative Commons is not a
120
+ party to this document and has no duty or obligation with respect to
121
+ this CC0 or use of the Work.
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ # This is free software released into the public domain (CC0 license).
@@ -0,0 +1,98 @@
1
+ `rack-for_now`: use third-party services, publish your domain URL
2
+ =================================================================
3
+
4
+ > Yeah, this project will be a great success, I will need to set up
5
+ > my own git server. And an issue tracker. And a full data center
6
+ > to run it!
7
+ >
8
+ > Well, _for now_ GitHub will do.
9
+
10
+ `rack-for_now` is a Rack middleware component that redirects project
11
+ URLs to GitHub, Rubygems and other online service. It allows you to use your
12
+ domain as the permanent URL of your project while still using these handy
13
+ third-party services.
14
+
15
+
16
+ Examples
17
+ --------
18
+
19
+ The most basic way to use `rack-for_now` is to mount it in `config.ru`
20
+ or with `Rack::Builder`.
21
+
22
+ # let's create a redirect from `/othello` to GitHub, under
23
+ # the user `will`
24
+ map '/othello' do
25
+ run Rack::ForNow::GitHub.new('will', 'othello')
26
+ end
27
+
28
+ It is possible to omit the project name if it is the same as the
29
+ URL where `rack-for_now` is mounted.
30
+
31
+ # Rack::ForNow::GitHub will understand that the project name is `othello`
32
+ map '/othello' do
33
+ run Rack::ForNow::GitHub.new('will')
34
+ end
35
+
36
+ A more interesting use is to add additional subpaths for other
37
+ services using the `#with(*subservices)` method.
38
+
39
+ # this will redirect
40
+ # * `/romeo` to <https://github.com/will/romeo>,
41
+ # * `/romeo/docs` to <http://rubydoc.info/gems/romeo>,
42
+ # * `/romeo/issues` to <https://github.com/will/issues>
43
+ map '/romeo' do
44
+ run Rack::ForNow::GitHub.new('will').
45
+ with(Rack::ForNow::GHIssues,
46
+ Rack::ForNow::RubyDoc)
47
+ end
48
+
49
+ The services have their default mount point, for example `RubyDoc` will
50
+ automatically be mounted on `./docs`. It is possible to configure under
51
+ which path they are mounted on using `.on(mount_point)`.
52
+
53
+ # redirect to rubydocs.info when `/romeo/api-docs` is requested
54
+ map '/romeo' do
55
+ run Rack::ForNOw::GitHub.new('will').
56
+ with(Rack::ForNow::RubyDoc.on('api-docs'))
57
+ end
58
+
59
+
60
+ Requirements
61
+ ------------
62
+
63
+ `rack-for_now` requires a recent Rack but does not depend on any
64
+ other gem.
65
+
66
+
67
+ Install
68
+ -------
69
+
70
+ gem install rack-for_now
71
+
72
+
73
+ Author
74
+ ------
75
+
76
+ * Gioele Barabucci <http://svario.it/gioele> (initial author)
77
+
78
+
79
+ Development
80
+ -----------
81
+
82
+ Code
83
+ : <https://svario.it/rack-for_now>
84
+
85
+ Report issues
86
+ : <https://svario.it/rack-for_now/issues>
87
+
88
+ Documentation
89
+ : <https://svario.it/rack-for_now/docs>
90
+
91
+
92
+ License
93
+ -------
94
+
95
+ This is free software released into the public domain (CC0 license).
96
+
97
+ See the `COPYING.CC0` file or <http://creativecommons.org/publicdomain/zero/1.0/>
98
+ for more details.
@@ -0,0 +1,8 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
8
+ # This is free software released into the public domain (CC0 license).
@@ -0,0 +1,275 @@
1
+ require 'rack/builder'
2
+
3
+ module Rack::ForNow
4
+
5
+ # The `Service` class is the base classes for all the
6
+ # third-party services made available by `Rack::ForNow`.
7
+ #
8
+ # @abstract The `Service` class is not meant to be used directly.
9
+
10
+ class Service
11
+ # @return [String] the default path where the service will be mounted.
12
+
13
+ def default_subpath
14
+ self.class.const_get(:DEFAULT_SUBPATH)
15
+ end
16
+
17
+ # @return [String] the template URL for the service.
18
+
19
+ def template_url
20
+ self.class.const_get(:TEMPLATE_URL)
21
+ end
22
+
23
+ # Mounts a service on a subpath.
24
+ #
25
+ # @example Mount a GitHub Issues redirect under `/romeo/issues` (default path)
26
+ #
27
+ # map '/romeo' do
28
+ # run Rack::ForNow::GitHub.new('will').with(Rack::ForNow::GHIssues)
29
+ # end
30
+ #
31
+ # @example Mount a GitHub Issues redirect under `/romeo/bugs`
32
+ #
33
+ # map '/romeo' do
34
+ # run Rack::ForNow::GitHub.new('will').with(Rack::ForNow::GHIssues.on('bugs'))
35
+ # end
36
+ #
37
+ # @example Mount multiple services
38
+ #
39
+ # map '/romeo' do
40
+ # run Rack::ForNow::GitHub.new('will').
41
+ # with(Rack::ForNow::GHIssues, Rack::ForNow::Rubydoc).
42
+ # with(Rack::ForNow::GHPages.on('tutorial')).
43
+ # end
44
+ #
45
+ # @see .on
46
+ #
47
+ # @api public
48
+ #
49
+ # @param [Service, Class] subservices the services to mount
50
+ #
51
+ # @return [Service] the service itself
52
+
53
+ def with(*subservices)
54
+ subservices.each do |subservice|
55
+ subservice = subservice.new if subservice.is_a? Class
56
+
57
+ subservice.parent_service = self
58
+
59
+ @subservices ||= {}
60
+ @subservices[subservice.subpath] = subservice
61
+ end
62
+
63
+ return self
64
+ end
65
+
66
+ # Sets up a service to be installed on an arbitrary path
67
+ #
68
+ # @example
69
+ #
70
+ # map '/romeo' do
71
+ # run Rack::ForNow::GitHub.new('will').
72
+ # with(Rack::ForNow::Rubydoc). # this sets up `/romeo/docs`
73
+ # with(Rack::ForNow::Rubydoc.on('/documentation') # this sets up `/romeo/documentation`
74
+ # end
75
+ #
76
+ # @see #with
77
+ #
78
+ # @api public
79
+ #
80
+ # @param [String] path the path under which the service is to be installed
81
+ #
82
+ # @return [Service] the service, set up so to be installed on `path`
83
+
84
+ def self.on(path)
85
+ service = self.new
86
+ service.subpath = path
87
+
88
+ return service
89
+ end
90
+
91
+ # @api private
92
+ def call(env)
93
+ @app ||= app
94
+ @app.call(env)
95
+ end
96
+
97
+ # @api private
98
+ def app
99
+ builder = Rack::Builder.new
100
+
101
+ @subservices ||= {}
102
+ @subservices.each do |path, service|
103
+ builder.map('/' + path) { run service.main_app }
104
+ end
105
+
106
+ service = self
107
+ builder.map('/') { run service.main_app }
108
+
109
+ return builder.to_app
110
+ end
111
+
112
+ # @api private
113
+ def main_app
114
+ lambda do |env|
115
+ root_requested = env['PATH_INFO'].chomp('/').empty?
116
+ if !root_requested
117
+ return [404, {'Content-Type' => 'text/plain', 'X-Cascade' => 'pass'}, ["Not Found: #{env['PATH_INFO']}"]]
118
+ end
119
+
120
+ set_parameters
121
+ infer_runtime_parameters(env)
122
+
123
+ destination_url = personalized(template_url)
124
+
125
+ return [307, { 'Location' => destination_url }, [""]]
126
+ end
127
+ end
128
+
129
+ # @api private
130
+ def subpath
131
+ return @subpath || default_subpath
132
+ end
133
+ attr_writer :subpath
134
+
135
+ # @api private
136
+ def parent_service
137
+ return @parent_service || FakeService.new
138
+ end
139
+ attr_writer :parent_service
140
+
141
+ # Set the service parameters, inheriting from the parent service if needed.
142
+ #
143
+ # @api private
144
+ #
145
+ # @return void
146
+
147
+ def set_parameters
148
+ if parent_service.nil?
149
+ return
150
+ end
151
+
152
+ params = self.instance_variables.map(&:to_sym)
153
+ params -= [:@app, :@parent_service, :@subpath, :@subservices]
154
+ params.reject! { |param_name| !self.instance_variable_get(param_name).nil? }
155
+
156
+ methods = params.map { |param_name| param_name.to_s[1..-1].to_sym }
157
+
158
+ params.each_with_index do |param_name, idx|
159
+ value = parent_service.send(methods[idx])
160
+ self.instance_variable_set(param_name, value)
161
+ end
162
+ end
163
+
164
+ # Infer parameters from the Rack request.
165
+ #
166
+ # @api private
167
+ #
168
+ # @return void
169
+
170
+ def infer_runtime_parameters(env)
171
+ # TODO: provide a way to update also other parameters
172
+ params = self.instance_variables.map(&:to_sym)
173
+ if params.include?(:@project)
174
+ @project ||= last_URL_segment(env)
175
+ end
176
+ end
177
+
178
+ # @api private
179
+ def last_URL_segment(env)
180
+ path = env['SCRIPT_NAME'].to_s + env['PATH_NAME'].to_s
181
+ segments = path.split('/')
182
+
183
+ idx_last = (segments.last == subpath) ? -2 : -1
184
+ return segments[idx_last]
185
+ end
186
+
187
+ # @api private
188
+ def personalized(url_template)
189
+ placeholders = url_template.scan(/\%\{(.*?)\}/).to_a.flatten.uniq
190
+ values = Hash[placeholders.map { |placeholder| [placeholder, instance_variable_get("@#{placeholder}".to_sym)] }]
191
+
192
+ values.each do |placeholder, value|
193
+ if value.nil?
194
+ raise "Unset template variable #{placeholder} for #{self.class}"
195
+ end
196
+ end
197
+
198
+ url = url_template
199
+ values.each do |placeholder, value|
200
+ url = url.gsub("%{#{placeholder}}", value)
201
+ end
202
+
203
+ return url
204
+ end
205
+ end
206
+
207
+ # @private
208
+ class FakeService
209
+ def method_missing(m, *args, &block)
210
+ return nil
211
+ end
212
+ end
213
+
214
+ class GitHub < Service
215
+ DEFAULT_SUBPATH = 'code'
216
+ TEMPLATE_URL = 'https://github.com/%{user_name}/%{project}'
217
+
218
+ def initialize(user_name = nil, project = nil)
219
+ @user_name = user_name
220
+ @project = project
221
+ end
222
+
223
+ attr_reader :user_name
224
+ attr_reader :project
225
+ end
226
+
227
+ class GHIssues < GitHub
228
+ DEFAULT_SUBPATH = 'issues'
229
+ TEMPLATE_URL = 'https://github.com/%{user_name}/%{project}/issues'
230
+ end
231
+
232
+ class GHPages < GitHub
233
+ DEFAULT_SUBPATH = 'docs'
234
+ TEMPLATE_URL = 'http://%{user_name}.github.io/%{project}'
235
+ end
236
+
237
+ class RubyDoc < Service
238
+ DEFAULT_SUBPATH = 'docs'
239
+ TEMPLATE_URL = 'http://rubydoc.info/gems/%{project}'
240
+
241
+ def initialize(project = nil)
242
+ @project = project
243
+ end
244
+
245
+ attr_reader :project
246
+ end
247
+
248
+ class RubyDocGitHub < RubyDoc
249
+ DEFAULT_SUBPATH = 'docs'
250
+ TEMPLATE_URL = 'http://rubydoc.info/github/%{user_name}/%{project}'
251
+
252
+ def initialize(user_name = nil, project = nil)
253
+ @user_name = user_name
254
+ @project = project
255
+ end
256
+
257
+ attr_reader :user_name
258
+ attr_reader :project
259
+ end
260
+
261
+ class MavenCentral < Service
262
+ DEFAULT_SUBPATH = 'maven'
263
+ TEMPLATE_URL = 'http://search.maven.org/#search|ga|1|g%3A%22%{group_id}%22%20AND%20a%3A%22%{project}%22'
264
+
265
+ def initialize(group_id, project = nil)
266
+ @group_id = group_id
267
+ @project = project
268
+ end
269
+
270
+ attr_reader :group_id
271
+ attr_reader :project
272
+ end
273
+ end
274
+
275
+ # This is free software released into the public domain (CC0 license).
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'rack-for_now'
7
+ spec.version = '0.1'
8
+ spec.authors = ["Gioele Barabucci"]
9
+ spec.email = ["gioele@svario.it"]
10
+ spec.summary = %q{Use third-party services, publish your domain URL}
11
+ spec.description = %q{rack-for_now is a Rack middleware component that } +
12
+ %q{redirects project URLs to GitHub, Rubygems and } +
13
+ %q{other online service. It allows you to use your } +
14
+ %q{domain as the permanent URL of your project while } +
15
+ %q{still using these handy 3rd-party services.}
16
+
17
+ spec.homepage = 'http://svario.it/rack-for_now'
18
+ spec.license = 'CC0'
19
+
20
+ spec.files = `git ls-files`.split($/)
21
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
22
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
23
+ spec.require_paths = ['lib']
24
+
25
+ spec.add_dependency 'rack'
26
+
27
+ spec.add_development_dependency 'bundler', '~> 1.3'
28
+ spec.add_development_dependency 'rack-test'
29
+ spec.add_development_dependency 'rake'
30
+ spec.add_development_dependency 'rspec'
31
+ end
32
+
33
+ # This is free software released into the public domain (CC0 license).
@@ -0,0 +1,132 @@
1
+ require 'rack/test'
2
+
3
+ require 'rack/for_now'
4
+
5
+ APP = Rack::Builder.new do
6
+ map '/othello' do
7
+ run Rack::ForNow::GitHub.new('will')
8
+ end
9
+
10
+ map '/iago' do
11
+ run Rack::ForNow::GitHub.new('will', 'othello')
12
+ end
13
+
14
+ map '/romeo' do
15
+ run Rack::ForNow::GitHub.new('will').
16
+ with(Rack::ForNow::GHIssues, Rack::ForNow::GHPages).
17
+ with(Rack::ForNow::RubyDoc.on('documentation'))
18
+ end
19
+
20
+ map '/juliet' do
21
+ run Rack::ForNow::GitHub.new('will', 'romeo').
22
+ with(Rack::ForNow::RubyDoc)
23
+ end
24
+
25
+ map '/venice' do
26
+ run Rack::ForNow::RubyDoc.new
27
+ end
28
+
29
+ map '/midnight' do
30
+ run Rack::ForNow::GitHub.new('will').
31
+ with(Rack::ForNow::RubyDocGitHub)
32
+ end
33
+
34
+ map '/capuleti' do
35
+ run Rack::ForNow::MavenCentral.new('uk.shakespeare.william', 'romeo')
36
+ end
37
+
38
+ map '/' do
39
+ run Proc.new { |env| [200, { 'Content-Type' => 'text/plain' }, ["Default page"]] }
40
+ end
41
+ end.to_app
42
+
43
+ describe Rack::ForNow do
44
+ include Rack::Test::Methods
45
+
46
+ let(:app) { APP }
47
+
48
+ it "des not interfere with normal paths" do
49
+ get '/'
50
+
51
+ last_response.should be_ok
52
+ last_response.body.should == 'Default page'
53
+ end
54
+
55
+ it "redirects to GitHub" do
56
+ get '/iago'
57
+
58
+ last_response.status.should == 307
59
+ last_response.header['Location'].should == 'https://github.com/will/othello'
60
+ end
61
+
62
+ it "redirects to Rubydoc.info" do
63
+ get '/venice'
64
+
65
+ last_response.status.should == 307
66
+ last_response.header['Location'].should == 'http://rubydoc.info/gems/venice'
67
+ end
68
+
69
+ it "redirects to Rubydoc.info for GitHub repos" do
70
+ get '/midnight/docs'
71
+
72
+ last_response.status.should == 307
73
+ last_response.header['Location'].should == 'http://rubydoc.info/github/will/midnight'
74
+ end
75
+
76
+ it "redirects to GitHub Pages" do
77
+ get '/romeo/docs'
78
+
79
+ last_response.status.should == 307
80
+ last_response.header['Location'].should == 'http://will.github.io/romeo'
81
+ end
82
+
83
+ it "redirects to GitHub Issues" do
84
+ get '/romeo/issues'
85
+
86
+ last_response.status.should == 307
87
+ last_response.header['Location'].should == 'https://github.com/will/romeo/issues'
88
+ end
89
+
90
+ it "redirects to MavenCentral" do
91
+ get '/capuleti'
92
+
93
+ last_response.status.should == 307
94
+ last_response.header['Location']. should == 'http://search.maven.org/#search|ga|1|g%3A%22uk.shakespeare.william%22%20AND%20a%3A%22romeo%22'
95
+ end
96
+
97
+ it "redirects when the path ends with a slash" do
98
+ get '/venice/'
99
+
100
+ last_response.status.should == 307
101
+ last_response.header['Location'].should == 'http://rubydoc.info/gems/venice'
102
+ end
103
+
104
+ it "deduces the project's name from the path" do
105
+ get '/othello'
106
+
107
+ last_response.status.should == 307
108
+ last_response.header['Location'].should == 'https://github.com/will/othello'
109
+ end
110
+
111
+ it "allows composition with other services" do
112
+ get '/juliet/docs'
113
+
114
+ last_response.status.should == 307
115
+ last_response.header['Location'].should == 'http://rubydoc.info/gems/romeo'
116
+ end
117
+
118
+ it "allows composition with other services with arbitrary subpaths" do
119
+ get '/romeo/documentation'
120
+
121
+ last_response.status.should == 307
122
+ last_response.header['Location'].should == 'http://rubydoc.info/gems/romeo'
123
+ end
124
+
125
+ it "returns 404 for unknown subpaths" do
126
+ get '/juliet/others'
127
+
128
+ last_response.status.should == 404
129
+ end
130
+ end
131
+
132
+ # This is free software released into the public domain (CC0 license).
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-for_now
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ platform: ruby
6
+ authors:
7
+ - Gioele Barabucci
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rack-test
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: rack-for_now is a Rack middleware component that redirects project URLs
84
+ to GitHub, Rubygems and other online service. It allows you to use your domain as
85
+ the permanent URL of your project while still using these handy 3rd-party services.
86
+ email:
87
+ - gioele@svario.it
88
+ executables: []
89
+ extensions: []
90
+ extra_rdoc_files: []
91
+ files:
92
+ - ".gitignore"
93
+ - ".travis.yml"
94
+ - ".yardopts"
95
+ - COPYING.CC0
96
+ - Gemfile
97
+ - README.md
98
+ - Rakefile
99
+ - lib/rack/for_now.rb
100
+ - rack-for_now.gemspec
101
+ - spec/rack/for_now_spec.rb
102
+ homepage: http://svario.it/rack-for_now
103
+ licenses:
104
+ - CC0
105
+ metadata: {}
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ requirements: []
121
+ rubyforge_project:
122
+ rubygems_version: 2.1.11
123
+ signing_key:
124
+ specification_version: 4
125
+ summary: Use third-party services, publish your domain URL
126
+ test_files:
127
+ - spec/rack/for_now_spec.rb