Permalink
Browse files

Bringing in a few ancillary changes from the gcd-ify branch

git-svn-id: http://svn.macosforge.org/repository/ruby/ControlTower/trunk@4269 23306eb0-4c56-4727-a40e-e92c0eb68959
  • Loading branch information...
1 parent 6f45330 commit bfbaccd0f808c4f45ab39c53e40e9662a1b23206 joshua.ballanco@apple.com committed Jun 23, 2010
Showing with 159 additions and 21 deletions.
  1. +1 −1 .gitignore
  2. +74 −0 HACKING.rdoc
  3. +0 −9 README
  4. +31 −0 README.rdoc
  5. +20 −0 TODO
  6. +4 −8 bin/control_tower
  7. +4 −2 ext/CTParser/CTParser.m
  8. +0 −1 lib/control_tower/rack_socket.rb
  9. +1 −0 lib/control_tower/server.rb
  10. +17 −0 sample/file_upload.ru
  11. +7 −0 sample/simple_hello.ru
View
@@ -1,3 +1,3 @@
*.bundle
*.o
-pkg/*
+pkg
View
@@ -0,0 +1,74 @@
+== Hacking Control Tower
+
+Control Tower is still in very early development. It is being developed as part
+of the MacRuby project, so be sure to familiarize yourself with MacRuby's
+HACKING.rdoc, as all guidelines there apply here as well. If you have any ideas
+or suggestions for improvements, please communicate them with the MacRuby
+developer's list at <macruby-devel@lists.macosforge.org>. You can also find more
+information at the MacRuby website (http://www.macruby.org/).
+
+
+== CAUTION! AVERTISSEMENT! VOORZICHTIG! 注意!
+
+DO NOT EDIT http11_parser.c! THIS FILE CONTAINS MACHINE GENERATED CODE.
+N'EDITEZ PAS http11_parser.c! Ce fichier a été généré automatiquement.
+WIJZIG http11_parser.c NIET! Dit bestand bevat MACHINE gegenereerde code.
+http11_parser.cを編集しないでください!このファイルが機械生成されいます。
+
+If you really must, you can recreate http11_parser.c from http11_parser.rl using
+Ragel (not included). It would also be acceptable to replace the parser all at
+once, but editing it is not likely to ever be a good idea.
+
+
+== Sample Code
+
+There are two samples that you can run to explore ControlTower's behavior on GET
+and POST requests located in the 'sample' directory. To use these samples, first
+build and install the Control Tower gem:
+
+> rake gem
+> sudo macgem install pkg/control_tower-0.1-universal-darwin-10.gem
+
+Then, to try a GET request, start the 'simple_hello.ru' rack-up config like so:
+
+> control_tower -R sample/simple_hello.ru
+
+and test it with a utility such as curl like so:
+
+> curl http://localhost:8080/
+
+This should reply with a very traditional string and a read-out of the rack
+environment generated by your request. To try a POST request, start the
+'file_upload.ru' config as above, then use curl (or similar tool) to send a post
+with some file content like so:
+
+> curl -F "file=@README.rdoc" http://localhost:8080/
+
+This command tells curl to send the file as a form parameter, and the reply
+should contain the content of the rack 'params' variable constructed from this
+parameter. In particular, when the parameter is named 'file', the
+'file_upload.ru' sample will return the contents of the file.
+
+
+== Debugging
+
+=== Environment variables
+
+Currently, there is only one environment variable specifically for debugging
+Control Tower:
+
+* CT_DEBUG: This will turn on debug logging until we get a better logger.
+
+
+== Known Issues
+
+* Error compiling Regular Expression in Rack::Request
+ Workaround: Modify line 150 in rack/request.rb like so
+- form_vars.sub!(/\0\z/, '')
++ form_vars.slice!(-1) if form_vars[-1] == "\0"
+
+* Problem with Sinatra > 1.0 using Rack.release
+ Workaround: Modify line 39 in sinatra/base.rb like so
+- if Rack.release < '1.1'
++ if Rack.version < '1.1'
+
View
9 README
@@ -1,9 +0,0 @@
-Control Tower
-
-Copyright (c) 2009-2010, Apple Inc
-Author: Joshua Ballanco
-
-SYNOPSIS
-Control Tower is a Web application server for Rack-based Ruby applications. It
-is (or will be) composed of three major components: a networking layer, an HTTP
-parser, and a Rack interface.
View
@@ -0,0 +1,31 @@
+== Control Tower
+Control Tower is a web application server for Rack-based MacRuby applications based on Apple's Grand Central Dispatch libraries.
+
+It is composed of three major components: A Grand Central Dispatch based networking layer, the Mongrel HTTP parser, and Rack web
+application interface. It is currently very much a work in progress!
+
+=== Installation
+From the root directory of the project, run:
+
+ $ rake package
+ $ sudo macgem install pkg/control_tower-0.1-universal-darwin-10.gem
+
+=== Usage
+There are currently only 4 supported command line options:
+
+* -R <rackup_config.ru> : Where you specify the Rackup config file to run
+* -h <hostname> : Hostname for the server (Control Tower will only respond to requests to this host)
+* -p <port> : Port # for the server
+* -c : Use this to enable serving requests to a GCD concurrent queue
+
+=== License
+Control Tower is covered by the Ruby license. See COPYING for more details.
+
+=== Credits
+Control Tower's parser was stolen Thin which stole it from Mongrel (http://mongrel.rubyforge.org) originially written by Zed Shaw.
+Mongrel Web Server (Mongrel) is copyrighted free software by Zed A. Shaw <zedshaw at zedshaw dot com> You can redistribute it and/or
+modify it under the terms of the GPL.
+
+Thin is copyright Marc-Andre Cournoyer <macournoyer@gmail.com>
+
+Control Tower is copyright (c) 2009-2010, Apple Inc
View
20 TODO
@@ -0,0 +1,20 @@
+For 0.1:
+
+[ ] Logging!
+ [ ] An ASL-based Logger class
+ [ ] Request logging (e.g. appache_access.log)
+ [ ] Error logging (e.g. appache_error.log)
+ [ ] Debug logging
+[ ] Testing!
+ [ ] Parser test cases
+ [ ] GET test cases
+ [ ] POST test cases
+ [ ] Concurrency testing
+[ ] Handle broken request pipes
+[ ] Don't reset peer connections
+[ ] Protect against malformed Content-Length in headers
+
+For future:
+
+[ ] Improve body loading
+[ ] Fully-async file upload
View
@@ -9,7 +9,8 @@ require 'optparse'
@options = {
:rackup => './config.ru',
:port => '8080',
- :host => 'localhost'
+ :host => 'localhost',
+ :concurrent => false
}
OptionParser.new do |opts|
@@ -25,7 +26,7 @@ OptionParser.new do |opts|
@options[:host] = host
end
- opts.on("-c", "--[no]-concurrency", "Handle requests concurrently") do |concurrent|
+ opts.on("-c", "--[no-]concurrency", "Handle requests concurrently") do |concurrent|
@options[:concurrent] = concurrent
end
end.parse!
@@ -35,16 +36,11 @@ unless File.exist? File.expand_path(@options[:rackup])
exit 1
end
-unless File.exist? File.expand_path(@options[:rackup])
- puts "We only know how to deal with Rack-up configs for now"
- exit 1
-end
-
# Under construction...everything is development!
ENV['RACK_ENV'] = 'development'
rackup_config = File.read(File.expand_path(@options[:rackup]))
-app = eval("Rack::Builder.new { #{rackup_config} }.to_app")
+app = eval("Rack::Builder.new { #{rackup_config} }").to_app
# Let's get to business!
server = ControlTower::Server.new(app, @options)
View
@@ -81,7 +81,8 @@ void header_done(void *env, const char *at, size_t length)
if (colon_pos.location != NSNotFound) {
serverName = [hostString substringToIndex:colon_pos.location];
serverPort = [hostString substringFromIndex:(colon_pos.location + 1)];
- } else {
+ }
+ else {
serverName = [NSString stringWithString:hostString];
serverPort = @"80";
}
@@ -104,7 +105,8 @@ void header_done(void *env, const char *at, size_t length)
NSMutableString *body = [environment objectForKey:@"rack.input"];
if (body != nil) {
[body appendString:[[NSString alloc] initWithBytes:at length:length encoding:NSASCIIStringEncoding]];
- } else {
+ }
+ else {
NSLog(@"Hmm...you seem to have body data but no where to put it. That's probably an error.");
}
@@ -14,7 +14,6 @@ def initialize(host, port, server, concurrent)
@server = server
@socket = TCPServer.new(host, port)
@status = :closed # Start closed and give the server time to start
- prepare_environment
#if concurrent
# @env['rack.multithread'] = true
@@ -20,6 +20,7 @@ def start
end
def handle_request(env)
+ env
wrap_output(*@app.call(env))
end
View
@@ -0,0 +1,17 @@
+require 'rack'
+
+class Uploader
+ def call(env)
+ params = Rack::Request.new(env).params
+ response = params.map do |k,v|
+ if k == 'file' && v[:tempfile]
+ "#{k} => File Contents: #{v[:tempfile].read}"
+ else
+ "#{k} => #{v.inspect}"
+ end
+ end.join("\n") + "\n"
+ [200, { 'Content-Type' => 'text/plain' }, response]
+ end
+end
+
+run Uploader.new
View
@@ -0,0 +1,7 @@
+class Hello
+ def call(env)
+ [200, { 'Content-Type' => 'text/plain' }, "Hello, world! Your environment is #{env}"]
+ end
+end
+
+run Hello.new

0 comments on commit bfbaccd

Please sign in to comment.