rack-for_now 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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