gopher2000 0.2.2 → 0.5.5

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
+ SHA256:
3
+ metadata.gz: 599d0bfe771be1795d77d08bd7fa8ef1df0b5c8ef89a6270d344aa9ad206e5ab
4
+ data.tar.gz: 64ee23ab4b4f63351c9572e19a995c5ca3da96919a79703e47a2830b9ddf6fba
5
+ SHA512:
6
+ metadata.gz: 7c16b9f80341276ad4f93aacbbf505d01b3aea5264da1e3119d43a10ea0037984b4d423ca51ff9f174a9af805daf8e079a71686296b9baee12607c0767706c59
7
+ data.tar.gz: 20adee6253ced84ab8d4a8c4c7413874b6f034a0b3ae12a86418336fa04acf16ca81ffc19fef41c6c4bdb28c348c7960a1214a4d9563274a80075a81d72fffae
@@ -0,0 +1 @@
1
+ 2.6.3
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - 2.1.1
5
+ - 2.3.3
6
+ - 2.4.2
7
+ # uncomment this line if your project needs to run something other than `rake`:
8
+ # script: bundle exec rspec spec
data/Gemfile CHANGED
@@ -1,27 +1,12 @@
1
- source "http://rubygems.org"
2
-
3
- # Specify your gem's dependencies in gopher.gemspec
1
+ source 'https://rubygems.org'
4
2
  gemspec
5
3
 
6
4
  gem "rake"
7
- gem "logging"
8
5
 
9
6
  # Add dependencies to develop your gem here.
10
7
  # Include everything needed to run rake, tests, features, etc.
11
8
  group :development do
12
- gem 'simplecov', :require => false, :group => :test
13
-
14
- gem "shoulda", ">= 0"
15
- gem "rspec"
16
-
17
- gem "bundler", "~> 1.0.0"
18
- gem "watchr"
19
9
 
20
10
  # There's a god example script stashed away in the repo
21
11
  gem "god"
22
-
23
- #
24
- # gems used in examples and for development.
25
- #
26
- gem "weather-underground"
27
12
  end
@@ -16,6 +16,8 @@ Gopher2000 - A Gopher server for the next millenium
16
16
  Gopher2000 is a ruby-based Gopher server. It is built for speedy, enjoyable development of
17
17
  all sorts of gopher sites.
18
18
 
19
+ [![Build Status](https://travis-ci.org/muffinista/gopher2000.svg?branch=master)](https://travis-ci.org/muffinista/gopher2000)
20
+
19
21
  Features
20
22
  --------
21
23
  * Simple, Sintra-inspired routing DSL.
@@ -57,7 +59,7 @@ menu :index do
57
59
  br(2)
58
60
 
59
61
  # link somewhere
60
- link 'current time', '/time'
62
+ text_link 'current time', '/time'
61
63
  br
62
64
  end
63
65
 
@@ -31,7 +31,7 @@ params = {
31
31
 
32
32
  opts.on('-d', '--debug', "run in debug mode") { params[:debug] = true }
33
33
  opts.on('-p port', 'set the port (default is 70)') { |val| params[:port] = Integer(val) }
34
- opts.on('-o addr', 'set the host (default is 0.0.0.0)') { |val| params[host] = val }
34
+ opts.on('-o addr', 'set the host (default is 0.0.0.0)') { |val| params[:host] = val }
35
35
  opts.on('-e env', 'set the environment (default is development)') { |val| params[:env] = val.to_sym }
36
36
 
37
37
  opts.on_tail("-h", "--help", "Show this message") do
File without changes
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #
5
+ # Simple gopher example
6
+ #
7
+
8
+ require 'gopher2000'
9
+
10
+ set :host, '0.0.0.0'
11
+ set :port, 7070
12
+
13
+ route '/figlet' do
14
+ render :figlet
15
+ end
16
+
17
+ #
18
+ # special text output rendering
19
+ #
20
+ text :figlet do
21
+ @text = "Hello!"
22
+
23
+ # nicely wrapped text
24
+ figlet @text
25
+
26
+ # spacing
27
+ br(2)
28
+ end
File without changes
@@ -57,11 +57,11 @@ menu :index do
57
57
  br(2)
58
58
 
59
59
  # link somewhere
60
- link 'current time', '/time'
60
+ text_link 'current time', '/time'
61
61
  br
62
62
 
63
63
  # another link
64
- link 'about', '/about'
64
+ text_link 'about', '/about'
65
65
  br
66
66
 
67
67
  # ask for some input
File without changes
File without changes
@@ -12,7 +12,6 @@ Gem::Specification.new do |s|
12
12
  s.summary = %q{Gopher2000 - A Gopher server for the next millenium}
13
13
  s.description = %q{Gopher2000 is a ruby-based Gopher server. It is built for speedy, enjoyable development of all sorts of gopher sites.}
14
14
 
15
- s.rubyforge_project = "gopher2000"
16
15
  s.licenses = ["WTFPL"]
17
16
 
18
17
  s.files = `git ls-files`.split("\n")
@@ -26,10 +25,11 @@ Gem::Specification.new do |s|
26
25
  s.add_development_dependency "yard"
27
26
  s.add_development_dependency "shoulda"
28
27
  s.add_development_dependency "rdoc"
29
- s.add_development_dependency "simplecov"
28
+ s.add_development_dependency "simplecov", "~> 0.16.1"
30
29
  s.add_development_dependency "watchr"
31
- s.add_development_dependency "eventmachine"
32
30
 
33
- s.add_runtime_dependency "eventmachine"
34
- s.add_runtime_dependency "logger"
31
+ s.add_runtime_dependency "artii", ">= 2.0.1"
32
+ s.add_runtime_dependency "eventmachine", "~> 1.2.5"
33
+ s.add_runtime_dependency "logging"
34
+ s.add_runtime_dependency "mimemagic"
35
35
  end
@@ -1,6 +1,6 @@
1
1
  require 'eventmachine'
2
2
  require 'stringio'
3
-
3
+ require 'logging'
4
4
 
5
5
  #
6
6
  # Define everything needed to run a gopher server
@@ -54,6 +54,13 @@ module Gopher
54
54
  config[:port] ||= 70
55
55
  end
56
56
 
57
+ #
58
+ # return the application environment
59
+ #
60
+ def env
61
+ config[:env] ||= 'development'
62
+ end
63
+
57
64
  #
58
65
  # are we in debugging mode?
59
66
  #
@@ -91,9 +98,9 @@ module Gopher
91
98
  #
92
99
  # mount a directory for browsing via gopher
93
100
  #
94
- # @param [Hash] A hash specifying the path your route will answer to, and the filesystem path to use '/route' => '/home/path/etc'
95
- #
96
- # @param [Hash] a hash of options for the mount. Primarily this is a filter, which will restrict the list files outputted. example: :filter => '*.jpg'
101
+ # @param [Hash] path A hash specifying the path your route will answer to, and the filesystem path to use '/route' => '/home/path/etc'
102
+ # @param [Hash] opts a hash of options for the mount. Primarily this is a filter, which will restrict the list files outputted. example: :filter => '*.jpg'
103
+ # @param [Class] klass The class that should be used to handle this mount. You could write and use a custom handler if desired
97
104
  #
98
105
  # @example mount the directory '/home/user/foo' at the gopher path '/files', and only show JPG files:
99
106
  # mount '/files' => '/home/user/foo', :filter => '*.jpg'
@@ -118,8 +125,7 @@ module Gopher
118
125
 
119
126
  #
120
127
  # define a route.
121
- # @param [String] the path your route will answer to. This is
122
- # basically a URI path
128
+ # @param [String] path the path your route will answer to. This is basically a URI path
123
129
  # @yield a block that handles your route
124
130
  #
125
131
  # @example respond with a simple string
@@ -133,7 +139,7 @@ module Gopher
133
139
  # end
134
140
  #
135
141
  def route(path, &block)
136
- selector = sanitize_selector(path)
142
+ selector = Gopher::Application.sanitize_selector(path)
137
143
  sig = compile!(selector, &block)
138
144
 
139
145
  debug_log("Add route for #{selector}")
@@ -145,6 +151,7 @@ module Gopher
145
151
 
146
152
  #
147
153
  # specify a default route to handle requests if no other route exists
154
+ # @yield a block to handle the default route
148
155
  #
149
156
  # @example render a template
150
157
  # default_route do
@@ -158,16 +165,15 @@ module Gopher
158
165
  #
159
166
  # lookup an incoming path
160
167
  #
161
- # @param [String] the selector path of the incoming request
168
+ # @param [String] selector the selector path of the incoming request
162
169
  #
163
170
  def lookup(selector)
164
171
  unless routes.nil?
165
- routes.each do |pattern, keys, block|
166
-
172
+ routes.each do |pattern, keys, block|
167
173
  if match = pattern.match(selector)
168
174
  match = match.to_a
169
175
  url = match.shift
170
-
176
+
171
177
  params = to_params_hash(keys, match)
172
178
 
173
179
  #
@@ -190,7 +196,7 @@ module Gopher
190
196
 
191
197
  #
192
198
  # find and run the first route which matches the incoming request
193
- # @param [Request] Gopher::Request object
199
+ # @param [Request] req Gopher::Request object
194
200
  #
195
201
  def dispatch(req)
196
202
  debug_log(req)
@@ -201,6 +207,9 @@ module Gopher
201
207
  if ! @request.valid?
202
208
  response.body = handle_invalid_request
203
209
  response.code = :error
210
+ elsif @request.url?
211
+ response.body = handle_url(@request)
212
+ response.code = :success
204
213
  else
205
214
  begin
206
215
  debug_log("do lookup for #{@request.selector}")
@@ -233,11 +242,11 @@ module Gopher
233
242
  # define a template which will be used to render a gopher-style
234
243
  # menu.
235
244
  #
236
- # @param [String/Symbol] -- the name of the template. This is what
237
- # identifies the template when making a call to render
245
+ # @param [String/Symbol] name the name of the template. This is what
246
+ # identifies the template when making a call to render
238
247
  # @yield a block which will output the menu. This block is
239
- # executed within an instance of Gopher::Rendering::Menu and will
240
- # have access to all of its methods.
248
+ # executed within an instance of Gopher::Rendering::Menu and will
249
+ # have access to all of its methods.
241
250
  #
242
251
  # @example a simple menu:
243
252
  # menu :index do
@@ -273,7 +282,7 @@ module Gopher
273
282
  # access to the methods defined in Gopher::Rendering::Text for
274
283
  # wrapping strings, adding simple headers, etc.
275
284
  #
276
- # @param [String/Symbol] -- the name of the template. This is what identifies the template when making a call to render
285
+ # @param [String/Symbol] name the name of the template. This is what identifies the template when making a call to render
277
286
  #
278
287
  # @yield a block which will output the menu. This block is executed within an instance of Gopher::Rendering::Text and will have access to all of its methods.
279
288
  # @example simple example
@@ -295,7 +304,7 @@ module Gopher
295
304
 
296
305
  #
297
306
  # find a template
298
- # @param [String/Symbol] name of the template
307
+ # @param [String/Symbol] t name of the template
299
308
  # @return template block and the class context it should use
300
309
  #
301
310
  def find_template(t)
@@ -311,8 +320,8 @@ module Gopher
311
320
 
312
321
  #
313
322
  # Find the desired template and call it within the proper context
314
- # @param [String/Symbol] name of the template to render
315
- # @param [Array] optional arguments to be passed to template
323
+ # @param [String/Symbol] template name of the template to render
324
+ # @param [Array] arguments optional arguments to be passed to template
316
325
  # @return result of rendering
317
326
  #
318
327
  def render(template, *arguments)
@@ -347,6 +356,15 @@ module Gopher
347
356
  menus.include?(:error) ? :error : :'internal/error'
348
357
  end
349
358
 
359
+
360
+ #
361
+ # get the id of the template that will be used when rendering an html page
362
+ # @return name of error template
363
+ #
364
+ def url_template
365
+ menus.include?(:html) ? :html : :'internal/url'
366
+ end
367
+
350
368
  #
351
369
  # get the id of the template that will be used when rendering an
352
370
  # invalid request
@@ -385,7 +403,7 @@ module Gopher
385
403
  # Gopher servers in production)
386
404
  #
387
405
  def non_blocking?
388
- config[:non_blocking] ||= ! debug_mode?
406
+ config.key?(:non_blocking) ? config[:non_blocking] : ! debug_mode?
389
407
  end
390
408
 
391
409
 
@@ -411,7 +429,7 @@ module Gopher
411
429
  # turn a path string with optional keys (/foo/:bar/:boo) into a
412
430
  # regexp which will be used when searching for a route
413
431
  #
414
- # @param [String] the path to compile
432
+ # @param [String] path the path to compile
415
433
  #
416
434
  def compile(path)
417
435
  keys = []
@@ -428,23 +446,25 @@ module Gopher
428
446
  [/^#{pattern}$/, keys]
429
447
  end
430
448
 
431
- #
432
- # Sanitizes a gopher selector
433
- #
434
- def sanitize_selector(raw)
435
- raw.to_s.dup.
436
- strip. # Strip whitespace
437
- sub(/\/$/, ''). # Strip last rslash
438
- sub(/^\/*/, '/'). # Strip extra lslashes
439
- gsub(/\.+/, '.') # Don't want consecutive dots!
440
- end
441
449
 
442
450
  class << self
443
- #
451
+
452
+ #
453
+ # Sanitizes a gopher selector
454
+ #
455
+ def sanitize_selector(raw)
456
+ "/#{raw}".dup.
457
+ strip. # Strip whitespace
458
+ sub(/\/$/, ''). # Strip last rslash
459
+ sub(/^\/*/, '/'). # Strip extra lslashes
460
+ gsub(/\.+/, '.') # Don't want consecutive dots!
461
+ end
462
+
463
+ #
444
464
  # generate a method which we will use to run routes. this is
445
465
  # based on #generate_method as used by sinatra.
446
466
  # @see https://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb
447
- # @param [String] name to use for the method
467
+ # @param [String] method_name name to use for the method
448
468
  # @yield block to use for the method
449
469
  def generate_method(method_name, &block)
450
470
  define_method(method_name, &block)
@@ -453,7 +473,7 @@ module Gopher
453
473
  method
454
474
  end
455
475
  end
456
-
476
+
457
477
  #
458
478
  # output a debugging message
459
479
  #
@@ -470,15 +490,37 @@ module Gopher
470
490
  #
471
491
  def register_defaults
472
492
  menu :'internal/not_found' do
473
- text "Sorry, #{@request.selector} was not found"
493
+ error "Sorry, #{@request.selector} was not found"
474
494
  end
475
495
 
476
496
  menu :'internal/error' do |details|
477
- text "Sorry, there was an error #{details}"
497
+ error "Sorry, there was an error #{details}"
478
498
  end
479
499
 
480
500
  menu :'internal/invalid_request' do
481
- text "invalid request"
501
+ error "invalid request"
502
+ end
503
+
504
+ menu :'internal/url' do
505
+ output = <<-EOHTML
506
+ <html>
507
+ <head>
508
+ <meta http-equiv="refresh" content="5;URL=#{@request.url}">
509
+ </head>
510
+ <body>
511
+ <p>
512
+ You are following a link from gopher to a website. If your browser supports it, you will be
513
+ automatically taken to the web site shortly. If you do not get
514
+ sent there, please click <a href="#{@request.url}">here</a>.
515
+ </p>
516
+ <p>
517
+ The URL linked is: <a href="#{@request.url}">#{@request.url}</a>.
518
+ </p>
519
+ <p>Have a nice day!</p>
520
+ </body>
521
+ </html>
522
+ EOHTML
523
+ output
482
524
  end
483
525
  end
484
526
 
@@ -486,6 +528,10 @@ module Gopher
486
528
  render not_found_template
487
529
  end
488
530
 
531
+ def handle_url(request)
532
+ render url_template, request
533
+ end
534
+
489
535
  def handle_error(e)
490
536
  render error_template, e
491
537
  end
@@ -22,16 +22,25 @@ module Gopher
22
22
  #
23
23
  # called by EventMachine when there's an incoming request
24
24
  #
25
- # @param [String] incoming selector
25
+ # @param [String] selector incoming selector
26
26
  # @return Response object
27
27
  #
28
- def receive_data(selector)
29
- call! Request.new(selector, remote_ip)
28
+ def receive_data data
29
+ (@buf ||= '') << data
30
+
31
+ while line = @buf.slice!(/(.*)\r?\n/)
32
+ receive_line(line)
33
+ end
30
34
  end
31
35
 
36
+ # Invoked with lines received over the network
37
+ def receive_line(line)
38
+ call! Request.new(line, remote_ip)
39
+ end
40
+
32
41
  #
33
42
  # generate a request object from an incoming selector, and dispatch it to the app
34
- # @param [String] incoming selector
43
+ # @param [Request] request Request object to handle
35
44
  # @return Response object
36
45
  #
37
46
  def call!(request)