Skip to content

Commit

Permalink
Bringing in a few ancillary changes from the gcd-ify branch
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.macosforge.org/repository/ruby/ControlTower/trunk@4269 23306eb0-4c56-4727-a40e-e92c0eb68959
  • Loading branch information
jballanc committed Jun 23, 2010
1 parent 9e3fb0f commit 4766b32
Show file tree
Hide file tree
Showing 11 changed files with 159 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
*.bundle
*.o
pkg/*
pkg
74 changes: 74 additions & 0 deletions HACKING.rdoc
Original file line number Diff line number Diff line change
@@ -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 <[email protected]>. 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 "[email protected]" 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'

9 changes: 0 additions & 9 deletions README

This file was deleted.

31 changes: 31 additions & 0 deletions README.rdoc
Original file line number Diff line number Diff line change
@@ -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 <[email protected]>

Control Tower is copyright (c) 2009-2010, Apple Inc
20 changes: 20 additions & 0 deletions TODO
Original file line number Diff line number Diff line change
@@ -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
12 changes: 4 additions & 8 deletions bin/control_tower
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ require 'optparse'
@options = {
:rackup => './config.ru',
:port => '8080',
:host => 'localhost'
:host => 'localhost',
:concurrent => false
}

OptionParser.new do |opts|
Expand All @@ -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!
Expand All @@ -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)
Expand Down
6 changes: 4 additions & 2 deletions ext/CTParser/CTParser.m
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
Expand All @@ -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.");
}

Expand Down
1 change: 0 additions & 1 deletion lib/control_tower/rack_socket.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions lib/control_tower/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def start
end

def handle_request(env)
env
wrap_output(*@app.call(env))
end

Expand Down
17 changes: 17 additions & 0 deletions sample/file_upload.ru
Original file line number Diff line number Diff line change
@@ -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
7 changes: 7 additions & 0 deletions sample/simple_hello.ru
Original file line number Diff line number Diff line change
@@ -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 4766b32

Please sign in to comment.