gopher2000 0.1.0

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.
Files changed (47) hide show
  1. data/.gitignore +4 -0
  2. data/.rvmrc +1 -0
  3. data/Gemfile +27 -0
  4. data/LICENSE.txt +14 -0
  5. data/README.markdown +344 -0
  6. data/Rakefile +38 -0
  7. data/bin/gopher2000 +51 -0
  8. data/examples/default_route.rb +22 -0
  9. data/examples/nyan.rb +62 -0
  10. data/examples/simple.rb +147 -0
  11. data/examples/twitter.rb +61 -0
  12. data/examples/weather.rb +69 -0
  13. data/gopher2000.gemspec +35 -0
  14. data/lib/gopher2000/base.rb +552 -0
  15. data/lib/gopher2000/dispatcher.rb +81 -0
  16. data/lib/gopher2000/dsl.rb +128 -0
  17. data/lib/gopher2000/errors.rb +14 -0
  18. data/lib/gopher2000/handlers/base_handler.rb +18 -0
  19. data/lib/gopher2000/handlers/directory_handler.rb +125 -0
  20. data/lib/gopher2000/rendering/abstract_renderer.rb +10 -0
  21. data/lib/gopher2000/rendering/base.rb +174 -0
  22. data/lib/gopher2000/rendering/menu.rb +129 -0
  23. data/lib/gopher2000/rendering/text.rb +10 -0
  24. data/lib/gopher2000/request.rb +21 -0
  25. data/lib/gopher2000/response.rb +25 -0
  26. data/lib/gopher2000/server.rb +85 -0
  27. data/lib/gopher2000/version.rb +4 -0
  28. data/lib/gopher2000.rb +33 -0
  29. data/scripts/god.rb +8 -0
  30. data/spec/application_spec.rb +54 -0
  31. data/spec/dispatching_spec.rb +144 -0
  32. data/spec/dsl_spec.rb +116 -0
  33. data/spec/gopher_spec.rb +1 -0
  34. data/spec/handlers/directory_handler_spec.rb +116 -0
  35. data/spec/helpers_spec.rb +16 -0
  36. data/spec/rendering/base_spec.rb +59 -0
  37. data/spec/rendering/menu_spec.rb +109 -0
  38. data/spec/rendering_spec.rb +84 -0
  39. data/spec/request_spec.rb +30 -0
  40. data/spec/response_spec.rb +33 -0
  41. data/spec/routing_spec.rb +92 -0
  42. data/spec/sandbox/old/socks.txt +0 -0
  43. data/spec/sandbox/socks.txt +0 -0
  44. data/spec/server_spec.rb +127 -0
  45. data/spec/spec_helper.rb +52 -0
  46. data/specs.watchr +60 -0
  47. metadata +211 -0
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.2-head@gopherpedia
data/Gemfile ADDED
@@ -0,0 +1,27 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in gopher.gemspec
4
+ gemspec
5
+
6
+ gem "rake"
7
+ gem "logging"
8
+
9
+ # Add dependencies to develop your gem here.
10
+ # Include everything needed to run rake, tests, features, etc.
11
+ 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
+
20
+ # There's a god example script stashed away in the repo
21
+ gem "god"
22
+
23
+ #
24
+ # gems used in examples and for development.
25
+ #
26
+ gem "weather-underground"
27
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,14 @@
1
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
2
+ Version 2, December 2004
3
+
4
+ Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
5
+
6
+ Everyone is permitted to copy and distribute verbatim or modified
7
+ copies of this license document, and changing it is allowed as long
8
+ as the name is changed.
9
+
10
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
11
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
12
+
13
+ 0. You just DO WHAT THE FUCK YOU WANT TO.
14
+
data/README.markdown ADDED
@@ -0,0 +1,344 @@
1
+ It's...
2
+
3
+ _____ _ _____ _____ _____ _____
4
+ | __ \ | | / __ \| _ || _ || _ |
5
+ | | \/ ___ _ __ | |__ ___ _ __ `' / /'| |/' || |/' || |/' |
6
+ | | __ / _ \| '_ \| '_ \ / _ \ '__| / / | /| || /| || /| |
7
+ | |_\ \ (_) | |_) | | | | __/ | ./ /___\ |_/ /\ |_/ /\ |_/ /
8
+ \____/\___/| .__/|_| |_|\___|_| \_____/ \___/ \___/ \___/
9
+ | |
10
+ |_|
11
+
12
+
13
+ Gopher2000 - A Gopher server for the next millenium
14
+ ===================================================
15
+
16
+ Gopher2000 is a ruby-based Gopher server. It is built for speedy, enjoyable development of
17
+ all sorts of gopher sites.
18
+
19
+ Features
20
+ --------
21
+ * Simple, Sintra-inspired routing DSL.
22
+ * Dynamic requests via named parameters on request paths.
23
+ * built on Event Machine.
24
+ * Easy to mount directories and serve up files.
25
+ * built in logging and stats.
26
+ * Runs on Ruby 1.9.2 with all the modern conveniences.
27
+
28
+ Requirements
29
+ ------------
30
+ * Ruby 1.9.2 or greater
31
+ * Nerves of steel
32
+
33
+ Examples
34
+ --------
35
+
36
+ Writing a functional Gopher app is as simple as:
37
+
38
+ ```rb
39
+ route '/simple' do
40
+ "hi" # You can output any text you want here
41
+ end
42
+ ```
43
+
44
+
45
+ Or, if you want to provide more interactivity, you can do something like:
46
+
47
+ ```rb
48
+ route '/' do
49
+ render :index
50
+ end
51
+
52
+ menu :index do
53
+ # output a text entry in the menu
54
+ text 'simple gopher example'
55
+
56
+ # use br(x) to add x space between lines
57
+ br(2)
58
+
59
+ # link somewhere
60
+ link 'current time', '/time'
61
+ br
62
+ end
63
+
64
+ route '/time' do
65
+ "It is currently #{Time.now}"
66
+ end
67
+ ```
68
+
69
+ You can see more working examples in the examples/ folder
70
+
71
+ Running a script
72
+ ----------------
73
+
74
+ You can use the supplied wrapper script
75
+
76
+ ```
77
+ gopher2000 -d examples/simple.rb
78
+
79
+ ==> *start server at 0.0.0.0 7070*
80
+ ```
81
+
82
+ Or, if you include gopher in your file, you can just run the script itself:
83
+
84
+ ```rb
85
+ # scriptname.rb
86
+ require 'gopher2000'
87
+
88
+ # ...
89
+ # write some code here
90
+ # ...
91
+
92
+ # Then, run 'ruby scriptname.rb'
93
+
94
+ ==> *start server at 0.0.0.0 7070*
95
+ ```
96
+ There are several command-line options:
97
+
98
+ * -d -- run in debug mode
99
+ * -p [port] -- which port to listen on
100
+ * -o [addr] -- what IP/host to listen on
101
+ * -e [env] -- what 'environment' to use -- this isn't really used by
102
+ Gopher2000, but you could use it when writing your app to determine
103
+ how you behave in production vs development, etc.
104
+
105
+ Command line options will override defaults specified in your script
106
+ -- so you can try out things on a different port/address if needed.
107
+
108
+
109
+ Developing Gopher Sites
110
+ -----------------------
111
+
112
+ Gopher2000 makes developing sites easy! Any time you change your
113
+ script, Gopher2000 will reload it. This way, you can make tweaks and
114
+ your site will be refreshed immediately. NOTE -- this is an
115
+ experimental feature, and might need some work.
116
+
117
+ Serving Files and Directories
118
+ -----------------------------
119
+
120
+ If you just want to serve up some files, there's a command for that:
121
+
122
+ ```rb
123
+ mount '/files' => '/home/username/files', :filter => '*.jpg'
124
+ ```
125
+
126
+ This will display a list of all the JPGs in the files directory.
127
+
128
+ Outputting Gopher Menus
129
+ -----------------------
130
+
131
+ There are a collection of commands to output Gopher menus (see
132
+ rendering/menu.rb for the code). The commands are:
133
+
134
+ **line(type, text, selector)** - output a line of type 'type' -- see
135
+ the RFC for the different types of links you can have.
136
+
137
+ **text** - output a line of text with no action on it.
138
+
139
+ **br(x)** - output x blank lines.
140
+
141
+ **error** - output an error message.
142
+
143
+ **directory** - (aliased as menu) output a link to a 'directory' -- this could be an
144
+ actual directory if you're building some sort of filesystem tree, or
145
+ a sub-menu for other actions in your app.
146
+
147
+ **link(text, selector)** - output a menu link to to the /selector path.
148
+
149
+ **search(text, selector)** -- output a link to a search action at
150
+ /selector.
151
+
152
+ Outputting Text
153
+ ---------------
154
+
155
+ If you would like to output text, but have the ability to format it
156
+ nicely, you can use a 'text' block like this:
157
+
158
+ ```rb
159
+ route '/prettytext' do
160
+ render :prettytext
161
+ end
162
+
163
+ #
164
+ # special text output rendering
165
+ #
166
+ text :prettytext do
167
+ @text = "A really long chunk of text. Lorem ipsum dolor sit amet ... nec massa."
168
+
169
+ # nicely wrapped text
170
+ block @text
171
+
172
+ # spacing
173
+ br(2)
174
+
175
+ # smaller line-width
176
+ block @text, 30
177
+ end
178
+
179
+ ```
180
+
181
+ A call to:
182
+
183
+ ```
184
+ echo "/prettytext" | ncat -C localhost 7070
185
+ ```
186
+
187
+ Will return your text, but with nice wrapping, etc.
188
+
189
+ @todo headers, etc.
190
+
191
+
192
+ Making It Pretty
193
+ ----------------
194
+
195
+ There are several helpers which you can call within render blocks to
196
+ help make your output a little shinier:
197
+
198
+ **width(x)** will set the width of your output. The default is 80
199
+ characters. You can change this to make your output wider or
200
+ thinner. This setting is used by **block** and also by the methods
201
+ described below.
202
+
203
+ **header(text, style='=')** will generate a very simple 'header', which is
204
+ basically the text you specify with an underline of the character
205
+ you specify. It will be centered in your output width, and will look
206
+ something like this:
207
+
208
+ Hello There!
209
+ =====================
210
+
211
+ **big_header** is the same as header, except it is bigger and better!
212
+
213
+ =====================
214
+ = Hello There! =
215
+ =====================
216
+
217
+ **underline** can be used to just output plain old lines, if you're
218
+ into that sort of thing.
219
+
220
+
221
+ Testing
222
+ -------
223
+
224
+ Here's some simple ways to test your server. First, you can always
225
+ just install a
226
+ [gopher client](http://lmgtfy.com/?q=gopher+clients). Or, if you like
227
+ to live on the edge, there's a few commands worth learning. First, you
228
+ can use [netcat](http://netcat.sourceforge.net/) to achieve
229
+ awesomeness. Here's some examples, assuming you're running the example
230
+ script on port 7070:
231
+
232
+
233
+ ```
234
+ #
235
+ # getting a menu listing
236
+ #
237
+
238
+ ~/Projects/gopher2000: echo "/" | nc localhost 7070
239
+ isimple gopher example null (FALSE) 0
240
+ i null (FALSE) 0
241
+ i null (FALSE) 0
242
+ 0current time /time 0.0.0.0 7070
243
+ i null (FALSE) 0
244
+ 0about /about 0.0.0.0 7070
245
+ i null (FALSE) 0
246
+ 7Hey, what is your name? /hello 0.0.0.0 7070
247
+ i null (FALSE) 0
248
+ 7echo test /echo_test 0.0.0.0 7070
249
+ i null (FALSE) 0
250
+ 1filez /files 0.0.0.0 7070
251
+
252
+ #
253
+ # getting a simple text response
254
+ #
255
+ ~/Projects/gopher2000: echo "/about" | nc localhost 7070
256
+ Gopher 2000 -- World Domination via Text Protocols
257
+ .
258
+ ```
259
+
260
+
261
+ Or, you can use the equally awesome [ncat](http://nmap.org/ncat/),
262
+ which is basically the successor to netcat. In general, I find that
263
+ ncat works better, particularly if you're using non-blocking
264
+ operations. Here's an example of it in operation:
265
+
266
+
267
+ ```
268
+ #
269
+ # Testing text output
270
+ #
271
+
272
+ ~/Projects/gopher2000: echo "/about" | ncat -C localhost 7070
273
+ Gopher 2000 -- World Domination via Text Protocols
274
+ .
275
+
276
+ #
277
+ # testing a route with some input
278
+ #
279
+
280
+ ~/Projects/gopher2000: echo "/hello\tcolin" | ncat -C localhost 7070
281
+ iHello, colin! null (FALSE) 0
282
+
283
+ .
284
+
285
+ ```
286
+
287
+
288
+
289
+ Logging
290
+ -------
291
+
292
+ Logging is pretty basic at the moment. Right now debug messages are
293
+ dumped to stderr. There's also an apache-esque access log, which can
294
+ be written to a file specified like this:
295
+
296
+ ```rb
297
+ set :access_log, "/tmp/access.log"
298
+ ```
299
+
300
+ The log will rollover daily, so your million hits per day won't
301
+ accumulate into an unmanageable file.
302
+
303
+ The format is a pretty basic tab-delimited file:
304
+
305
+ timestamp ip_address request_url result_code response_size
306
+ 2012-04-05 19:14:01 127.0.0.1 /lookup success 46
307
+
308
+ Non-Blocking Requests
309
+ ---------------------
310
+
311
+ When not running in debug mode, Gopher2000 will handle requests
312
+ without blocking -- this way, if you have an app that handles slow
313
+ requests, your users aren't held up waiting for other requests to
314
+ finish. However, this is somewhat experimental, so you can turn it off
315
+ by setting :non_blocking to be false in your script:
316
+
317
+ ```rb
318
+ set :non_blocking, false
319
+ ```
320
+
321
+ Also, non-blocking is always off in debug mode.
322
+
323
+ You probably need to be wary of this feature if you're actually
324
+ running a Gopher server that needs to be non-blocking. Read up on
325
+ EventMachine's defer feature if you need to learn more.
326
+
327
+
328
+ TODO
329
+ ----
330
+ * More examples
331
+ * Work on putting routing/rendering/etc into same context, and making
332
+ instance variables/methods generally available.
333
+ * Documentation
334
+ * clean up/improve EventMachine usage
335
+ * stats generation
336
+
337
+ References
338
+ ----------
339
+
340
+ * http://www.ietf.org/rfc/rfc1436.txt -- the original RFC for the
341
+ Gopher Protocol
342
+ * https://github.com/sinatra/sinatra -- almost everything good in this
343
+ library was taken or influenced by something in Sinatra. RUN don't
344
+ walk to the code and take a look.
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ require 'bundler'
2
+ Bundler.setup :default, :test, :development
3
+
4
+ require "bundler/gem_tasks"
5
+ require 'rdoc/task'
6
+
7
+ require "gopher2000/version"
8
+
9
+ require 'rspec/core'
10
+ require 'rspec/core/rake_task'
11
+ RSpec::Core::RakeTask.new(:spec) do |spec|
12
+ spec.pattern = FileList['spec/**/*_spec.rb']
13
+ end
14
+
15
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
16
+ spec.pattern = 'spec/**/*_spec.rb'
17
+ spec.rcov_opts = %w{--exclude .bundler,.rvm}
18
+ spec.rcov = true
19
+ end
20
+
21
+ task :default => :spec
22
+
23
+ Bundler::GemHelper.install_tasks
24
+
25
+ begin
26
+ require 'yard'
27
+ YARD_OPTS = ['-m', 'markdown', '-M', 'redcarpet']
28
+ DOC_FILES = ['lib/**/*.rb', 'README.markdown']
29
+
30
+ YARD::Rake::YardocTask.new(:doc) do |t|
31
+ t.files = DOC_FILES
32
+ #t.options = YARD_OPTS
33
+
34
+ puts t.inspect
35
+ end
36
+ rescue LoadError
37
+ puts "You need to install YARD."
38
+ end
data/bin/gopher2000 ADDED
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #
4
+ # get rid of errors when running via bundle
5
+ # @see https://github.com/ddollar/foreman/issues/94
6
+ #
7
+ $stdout.sync = true
8
+
9
+ require 'optparse'
10
+ require 'gopher2000'
11
+
12
+ #
13
+ # pull in any arguments and set them as env variables
14
+ #
15
+ opts = OptionParser.new
16
+ opts.banner = <<-EOS
17
+
18
+ Run a gopher server!
19
+
20
+ Usage: #{File.basename($0)} [options] [scriptname]
21
+
22
+ EOS
23
+
24
+ opts.separator ""
25
+ opts.separator "Options:"
26
+
27
+ params = {
28
+ :debug => false,
29
+ :env => :production
30
+ }
31
+
32
+ opts.on('-d', '--debug', "run in debug mode") { params[:debug] = true }
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 }
35
+ opts.on('-e env', 'set the environment (default is development)') { |val| params[:env] = val.to_sym }
36
+
37
+ opts.on_tail("-h", "--help", "Show this message") do
38
+ puts opts
39
+ exit!
40
+ end
41
+
42
+ extra = opts.parse!(ARGV)
43
+
44
+ script = extra.shift
45
+
46
+ if script.nil?
47
+ puts "Sorry, you need to specify a script to run"
48
+ exit!
49
+ end
50
+
51
+ run script, params
@@ -0,0 +1,22 @@
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
+ # you can specify a destination for access log, for stats/etc
14
+ set :access_log, "/tmp/access.log"
15
+
16
+ route '/gopher' do
17
+ "Greetings from Gopher 2000!" # You can output any text you want here
18
+ end
19
+
20
+ default_route do
21
+ "I AM HERE"
22
+ end
data/examples/nyan.rb ADDED
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #
5
+ # NYAN cat in gopherspace
6
+ #
7
+
8
+ require 'gopher2000'
9
+
10
+ set :host, '0.0.0.0'
11
+ set :port, 7070
12
+
13
+ route '/nyan' do
14
+
15
+ @cats = [
16
+ " + o + o
17
+ + o + +
18
+ o +
19
+ o + + +
20
+ + o o + o
21
+ -_-_-_-_-_-_-_,------, o
22
+ _-_-_-_-_-_-_-| /\\_/\\
23
+ -_-_-_-_-_-_-~|__( ^ .^) + +
24
+ _-_-_-_-_-_-_-\"\" \"\"
25
+ + o o + o
26
+ + +
27
+ o o o o +
28
+ o +
29
+ + + o o + ",
30
+
31
+ " o + + +
32
+ o + o
33
+ o +
34
+ + o + o
35
+ o + o +
36
+ _-_-_-_-_-_-_-,------, o +
37
+ -_-_-_-_-_-_-_| /\\_/\\ +
38
+ _-_-_-_-_-_-_~|__( ^ .^) o
39
+ -_-_-_-_-_-_-_ \"\" \"\"
40
+ + + o o +
41
+ o + o +
42
+ + o + + o
43
+ + +
44
+ + o + ",
45
+
46
+ "░░▓▓░░░░░░░░▓▓░░
47
+ ░▓▒▒▓░░░░░░▓▒▒▓░
48
+ ░▓▒▒▒▓░░░░▓▒▒▒▓░
49
+ ░▓▒▒▒▒▓▓▓▓▒▒▒▒▓░
50
+ ░▓▒▒▒▒▒▒▒▒▒▒▒▒▒▓
51
+ ▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓
52
+ ▓▒▒▒░▓▒▒▒▒▒░▓▒▒▓
53
+ ▓▒▒▒▓▓▒▒▒▓▒▓▓▒▒▓
54
+ ▓▒░░▒▒▒▒▒▒▒▒▒░░▓
55
+ ▓▒░░▒▓▒▒▓▒▒▓▒░░▓
56
+ ░▓▒▒▒▓▓▓▓▓▓▓▒▒▓░
57
+ ░░▓▒▒▒▒▒▒▒▒▒▒▓░░
58
+ ░░░▓▓▓▓▓▓▓▓▓▓░░░"
59
+ ]
60
+
61
+ @cats.sample
62
+ end