monorail 0.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.
- data/README +37 -0
- data/RELEASE_NOTES +6 -0
- data/bin/monorail +8 -0
- data/ext/extconf.rb +33 -0
- data/ext/http.cpp +419 -0
- data/ext/http.h +154 -0
- data/ext/rubyhttp.cpp +165 -0
- data/lib/monorail.rb +137 -0
- data/lib/monorail/app.rb +132 -0
- data/lib/monorail/monorail_webd.rb +753 -0
- data/lib/monorail/monotreme.rb +40 -0
- data/tests/testem.rb +4 -0
- metadata +64 -0
data/ext/http.h
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
/*****************************************************************************
|
2
|
+
|
3
|
+
$Id: http.h 2357 2006-04-22 19:49:00Z francis $
|
4
|
+
|
5
|
+
File: http.h
|
6
|
+
Date: 21Apr06
|
7
|
+
|
8
|
+
Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
|
9
|
+
Gmail: garbagecat10
|
10
|
+
|
11
|
+
This program is free software; you can redistribute it and/or modify
|
12
|
+
it under the terms of the GNU General Public License as published by
|
13
|
+
the Free Software Foundation; either version 2 of the License, or
|
14
|
+
(at your option) any later version.
|
15
|
+
|
16
|
+
This program is distributed in the hope that it will be useful,
|
17
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
18
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
19
|
+
GNU General Public License for more details.
|
20
|
+
|
21
|
+
You should have received a copy of the GNU General Public License
|
22
|
+
along with this program; if not, write to the Free Software
|
23
|
+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
24
|
+
|
25
|
+
*****************************************************************************/
|
26
|
+
|
27
|
+
|
28
|
+
#ifndef __HttpPersonality__H_
|
29
|
+
#define __HttpPersonality__H_
|
30
|
+
|
31
|
+
|
32
|
+
/**********************
|
33
|
+
class HttpConnection_t
|
34
|
+
**********************/
|
35
|
+
|
36
|
+
class HttpConnection_t
|
37
|
+
{
|
38
|
+
public:
|
39
|
+
HttpConnection_t();
|
40
|
+
virtual ~HttpConnection_t();
|
41
|
+
|
42
|
+
void ConsumeData (const char*, int);
|
43
|
+
|
44
|
+
virtual void SendData (const char*, int);
|
45
|
+
virtual void CloseConnection (bool after_writing);
|
46
|
+
virtual void ProcessRequest();
|
47
|
+
|
48
|
+
private:
|
49
|
+
|
50
|
+
enum {
|
51
|
+
BaseState,
|
52
|
+
PreheaderState,
|
53
|
+
HeaderState,
|
54
|
+
ReadingContentState,
|
55
|
+
DispatchState,
|
56
|
+
EndState
|
57
|
+
} ProtocolState;
|
58
|
+
|
59
|
+
enum {
|
60
|
+
MaxLeadingBlanks = 12,
|
61
|
+
MaxHeaderLineLength = 8 * 1024,
|
62
|
+
MaxContentLength = 20 * 1024 * 1024
|
63
|
+
};
|
64
|
+
int nLeadingBlanks;
|
65
|
+
|
66
|
+
char HeaderLine [MaxHeaderLineLength];
|
67
|
+
int HeaderLinePos;
|
68
|
+
|
69
|
+
int ContentLength;
|
70
|
+
int ContentPos;
|
71
|
+
char *_Content;
|
72
|
+
|
73
|
+
bool bRequestSeen;
|
74
|
+
bool bContentLengthSeen;
|
75
|
+
|
76
|
+
|
77
|
+
private:
|
78
|
+
bool _InterpretHeaderLine (const char*);
|
79
|
+
bool _InterpretRequest (const char*);
|
80
|
+
bool _DetectVerbAndSetEnvString (const char*, int);
|
81
|
+
void _SendError (int);
|
82
|
+
};
|
83
|
+
|
84
|
+
#endif // __HttpPersonality__H_
|
85
|
+
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
//////////////////////////////////////////////////
|
90
|
+
#if 0
|
91
|
+
#ifndef __HttpPersonality__H_
|
92
|
+
#define __HttpPersonality__H_
|
93
|
+
|
94
|
+
|
95
|
+
void http_event_callback (const char*, int, const char*, int);
|
96
|
+
|
97
|
+
|
98
|
+
/**********************
|
99
|
+
class HttpConnection_t
|
100
|
+
**********************/
|
101
|
+
|
102
|
+
class HttpConnection_t
|
103
|
+
{
|
104
|
+
public:
|
105
|
+
static void SetRequestCallback (void(*)(const char*, int, const char*, int));
|
106
|
+
static void (*RequestCallback)(const char*, int, const char*, int);
|
107
|
+
|
108
|
+
|
109
|
+
public:
|
110
|
+
HttpConnection_t (string&);
|
111
|
+
virtual ~HttpConnection_t();
|
112
|
+
|
113
|
+
void ConsumeData (const char*, int);
|
114
|
+
|
115
|
+
private:
|
116
|
+
string Signifier;
|
117
|
+
|
118
|
+
enum {
|
119
|
+
BaseState,
|
120
|
+
PreheaderState,
|
121
|
+
HeaderState,
|
122
|
+
ReadingContentState,
|
123
|
+
DispatchState,
|
124
|
+
EndState
|
125
|
+
} ProtocolState;
|
126
|
+
|
127
|
+
enum {
|
128
|
+
MaxLeadingBlanks = 12,
|
129
|
+
MaxHeaderLineLength = 8 * 1024,
|
130
|
+
MaxContentLength = 20 * 1024 * 1024
|
131
|
+
};
|
132
|
+
int nLeadingBlanks;
|
133
|
+
|
134
|
+
char HeaderLine [MaxHeaderLineLength];
|
135
|
+
int HeaderLinePos;
|
136
|
+
|
137
|
+
int ContentLength;
|
138
|
+
int ContentPos;
|
139
|
+
char *_Content;
|
140
|
+
|
141
|
+
bool bRequestSeen;
|
142
|
+
bool bContentLengthSeen;
|
143
|
+
|
144
|
+
|
145
|
+
private:
|
146
|
+
bool _InterpretHeaderLine (const char*);
|
147
|
+
bool _InterpretRequest (const char*);
|
148
|
+
bool _DetectVerbAndSetEnvString (const char*, int);
|
149
|
+
void _SendError (int);
|
150
|
+
};
|
151
|
+
|
152
|
+
|
153
|
+
#endif // __HttpPersonality__H_
|
154
|
+
#endif
|
data/ext/rubyhttp.cpp
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
/*****************************************************************************
|
2
|
+
|
3
|
+
$Id: rubyhttp.cpp 2374 2006-04-24 02:51:49Z francis $
|
4
|
+
|
5
|
+
File: libmain.cpp
|
6
|
+
Date: 06Apr06
|
7
|
+
|
8
|
+
Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
|
9
|
+
Gmail: garbagecat10
|
10
|
+
|
11
|
+
This program is free software; you can redistribute it and/or modify
|
12
|
+
it under the terms of the GNU General Public License as published by
|
13
|
+
the Free Software Foundation; either version 2 of the License, or
|
14
|
+
(at your option) any later version.
|
15
|
+
|
16
|
+
This program is distributed in the hope that it will be useful,
|
17
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
18
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
19
|
+
GNU General Public License for more details.
|
20
|
+
|
21
|
+
You should have received a copy of the GNU General Public License
|
22
|
+
along with this program; if not, write to the Free Software
|
23
|
+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
24
|
+
|
25
|
+
*****************************************************************************/
|
26
|
+
|
27
|
+
#include <iostream>
|
28
|
+
#include <string>
|
29
|
+
#include <stdexcept>
|
30
|
+
|
31
|
+
using namespace std;
|
32
|
+
|
33
|
+
#include <ruby.h>
|
34
|
+
#include "http.h"
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
/**************************
|
39
|
+
class RubyHttpConnection_t
|
40
|
+
**************************/
|
41
|
+
|
42
|
+
class RubyHttpConnection_t: public HttpConnection_t
|
43
|
+
{
|
44
|
+
public:
|
45
|
+
RubyHttpConnection_t (VALUE v): Myself(v) {}
|
46
|
+
virtual ~RubyHttpConnection_t() {}
|
47
|
+
|
48
|
+
virtual void SendData (const char*, int);
|
49
|
+
virtual void CloseConnection (bool after_writing);
|
50
|
+
virtual void ProcessRequest();
|
51
|
+
|
52
|
+
private:
|
53
|
+
VALUE Myself;
|
54
|
+
};
|
55
|
+
|
56
|
+
|
57
|
+
/******************************
|
58
|
+
RubyHttpConnection_t::SendData
|
59
|
+
******************************/
|
60
|
+
|
61
|
+
void RubyHttpConnection_t::SendData (const char *data, int length)
|
62
|
+
{
|
63
|
+
rb_funcall (Myself, rb_intern ("send_data"), 1, rb_str_new (data, length));
|
64
|
+
}
|
65
|
+
|
66
|
+
|
67
|
+
/*************************************
|
68
|
+
RubyHttpConnection_t::CloseConnection
|
69
|
+
*************************************/
|
70
|
+
|
71
|
+
void RubyHttpConnection_t::CloseConnection (bool after_writing)
|
72
|
+
{
|
73
|
+
VALUE v = rb_intern (after_writing ? "close_connection_after_writing" : "close_connection");
|
74
|
+
rb_funcall (Myself, v, 0);
|
75
|
+
}
|
76
|
+
|
77
|
+
|
78
|
+
/************************************
|
79
|
+
RubyHttpConnection_t::ProcessRequest
|
80
|
+
************************************/
|
81
|
+
|
82
|
+
void RubyHttpConnection_t::ProcessRequest()
|
83
|
+
{
|
84
|
+
rb_funcall (Myself, rb_intern ("process_http_request"), 0);
|
85
|
+
}
|
86
|
+
|
87
|
+
|
88
|
+
/*******
|
89
|
+
Statics
|
90
|
+
*******/
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
/***********
|
95
|
+
t_post_init
|
96
|
+
***********/
|
97
|
+
|
98
|
+
static VALUE t_post_init (VALUE self)
|
99
|
+
{
|
100
|
+
RubyHttpConnection_t *hc = new RubyHttpConnection_t (self);
|
101
|
+
if (!hc)
|
102
|
+
throw std::runtime_error ("no http-connection object");
|
103
|
+
|
104
|
+
rb_ivar_set (self, rb_intern ("@http______conn"), INT2NUM ((int)hc));
|
105
|
+
return Qnil;
|
106
|
+
}
|
107
|
+
|
108
|
+
|
109
|
+
/**************
|
110
|
+
t_receive_data
|
111
|
+
**************/
|
112
|
+
|
113
|
+
static VALUE t_receive_data (VALUE self, VALUE data)
|
114
|
+
{
|
115
|
+
int length = NUM2INT (rb_funcall (data, rb_intern ("length"), 0));
|
116
|
+
RubyHttpConnection_t *hc = (RubyHttpConnection_t*)(NUM2INT (rb_ivar_get (self, rb_intern ("@http______conn"))));
|
117
|
+
if (hc)
|
118
|
+
hc->ConsumeData (StringValuePtr (data), length);
|
119
|
+
return Qnil;
|
120
|
+
}
|
121
|
+
|
122
|
+
|
123
|
+
/********
|
124
|
+
t_unbind
|
125
|
+
********/
|
126
|
+
|
127
|
+
static VALUE t_unbind (VALUE self)
|
128
|
+
{
|
129
|
+
RubyHttpConnection_t *hc = (RubyHttpConnection_t*)(NUM2INT (rb_ivar_get (self, rb_intern ("@http______conn"))));
|
130
|
+
if (hc)
|
131
|
+
delete hc;
|
132
|
+
return Qnil;
|
133
|
+
}
|
134
|
+
|
135
|
+
|
136
|
+
/**********************
|
137
|
+
t_process_http_request
|
138
|
+
**********************/
|
139
|
+
|
140
|
+
static VALUE t_process_http_request (VALUE self)
|
141
|
+
{
|
142
|
+
// This is a stub in case the caller doesn't define it.
|
143
|
+
rb_funcall (self, rb_intern ("send_data"), 1, rb_str_new2 ("HTTP/1.1 200 ...\r\nContent-type: text/plain\r\nContent-length: 8\r\n\r\nMonorail"));
|
144
|
+
return Qnil;
|
145
|
+
}
|
146
|
+
|
147
|
+
|
148
|
+
|
149
|
+
/********************
|
150
|
+
Init_rubyhttpmachine
|
151
|
+
********************/
|
152
|
+
|
153
|
+
extern "C" void Init_rubyhttpmachine()
|
154
|
+
{
|
155
|
+
// INCOMPLETE, we need to define class Connectons inside module EventMachine
|
156
|
+
|
157
|
+
VALUE Monorail = rb_define_module ("Monorail");
|
158
|
+
VALUE EmModule = rb_define_module_under (Monorail, "HttpEventMachine");
|
159
|
+
rb_define_method (EmModule, "post_init", (VALUE(*)(...))t_post_init, 0);
|
160
|
+
rb_define_method (EmModule, "receive_data", (VALUE(*)(...))t_receive_data, 1);
|
161
|
+
rb_define_method (EmModule, "unbind", (VALUE(*)(...))t_unbind, 0);
|
162
|
+
rb_define_method (EmModule, "process_http_request", (VALUE(*)(...))t_process_http_request, 0);
|
163
|
+
}
|
164
|
+
|
165
|
+
|
data/lib/monorail.rb
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
# $Id: monorail.rb 2374 2006-04-24 02:51:49Z francis $
|
2
|
+
#
|
3
|
+
# Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
|
4
|
+
# Monorail is written and maintained by Francis Cianfrocca.
|
5
|
+
# gmail: garbagecat10.
|
6
|
+
|
7
|
+
# Monorail is a lightweight web-application framework that emphasizes
|
8
|
+
# performance and security. It includes a native-code engine for
|
9
|
+
# fast network I/O that eliminates the need for an outboard web server.
|
10
|
+
#
|
11
|
+
#--
|
12
|
+
# This program is free software; you can redistribute it and/or modify
|
13
|
+
# it under the terms of the GNU General Public License as published by
|
14
|
+
# the Free Software Foundation; either version 2 of the License, or
|
15
|
+
# (at your option) any later version.
|
16
|
+
#
|
17
|
+
# This program is free software; you can redistribute it and/or modify
|
18
|
+
# it under the terms of the GNU General Public License as published by
|
19
|
+
# the Free Software Foundation; either version 2 of the License, or
|
20
|
+
# (at your option) any later version.
|
21
|
+
#
|
22
|
+
# This program is distributed in the hope that it will be useful,
|
23
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
24
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
25
|
+
# GNU General Public License for more details.
|
26
|
+
#
|
27
|
+
# You should have received a copy of the GNU General Public License
|
28
|
+
# along with this program; if not, write to the Free Software
|
29
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
30
|
+
#
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
require 'rubygems'
|
36
|
+
require 'eventmachine'
|
37
|
+
|
38
|
+
require 'rubyhttpmachine'
|
39
|
+
require 'monorail/app'
|
40
|
+
require 'monorail/monotreme'
|
41
|
+
require 'monorail/monorail_webd'
|
42
|
+
|
43
|
+
require 'stringio'
|
44
|
+
|
45
|
+
|
46
|
+
module Monorail
|
47
|
+
|
48
|
+
module HttpEventMachine
|
49
|
+
|
50
|
+
def process_http_request
|
51
|
+
send_data process_actual_request
|
52
|
+
close_connection_after_writing
|
53
|
+
end
|
54
|
+
|
55
|
+
def process_default
|
56
|
+
"Monorail default processor"
|
57
|
+
end
|
58
|
+
|
59
|
+
def process_rails_request
|
60
|
+
s = StringIO.new( "", "r+" )
|
61
|
+
Dispatcher.dispatch( nil, ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, s)
|
62
|
+
s.rewind
|
63
|
+
header = []
|
64
|
+
status = "HTTP/1.1 200 ...\r\n"
|
65
|
+
while line = s.gets and line.chomp! and line.length > 0
|
66
|
+
if line =~ /\AStatus:[\s]*([\d]{3})/i
|
67
|
+
status = "HTTP/1.1 #{$1} ...\r\n"
|
68
|
+
else
|
69
|
+
header << "#{line}\r\n"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
header.unshift status
|
73
|
+
content = s.read
|
74
|
+
header << "Content-length: #{content.length}\r\n"
|
75
|
+
header << "\r\n"
|
76
|
+
|
77
|
+
header.join + content
|
78
|
+
end
|
79
|
+
|
80
|
+
def process_monorail_request
|
81
|
+
Monotreme.run
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
end # module HttpEventMachine
|
86
|
+
|
87
|
+
|
88
|
+
class Monorail
|
89
|
+
|
90
|
+
def initialize args
|
91
|
+
@args = args
|
92
|
+
block_given? and yield self
|
93
|
+
|
94
|
+
if @args.rails
|
95
|
+
initialize_for_rails
|
96
|
+
elsif @args.monorail
|
97
|
+
initialize_for_monorail
|
98
|
+
else
|
99
|
+
initialize_default
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
def run
|
106
|
+
$>.puts "starting the run..."
|
107
|
+
EventMachine.run {
|
108
|
+
EventMachine.start_server @args.host, @args.port, HttpEventMachine
|
109
|
+
EventMachine.add_periodic_timer(30) {p Time.now}
|
110
|
+
}
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
def initialize_for_monorail
|
115
|
+
$>.puts "initializing monorail environment..."
|
116
|
+
require @args.monorail + "/config"
|
117
|
+
HttpEventMachine.module_eval "alias_method :process_actual_request, :process_monorail_request"
|
118
|
+
$>.puts "done initializing monorail environment"
|
119
|
+
end
|
120
|
+
|
121
|
+
def initialize_for_rails
|
122
|
+
$>.puts "initializing rails environment..."
|
123
|
+
require @args.rails + "/config/environment"
|
124
|
+
require "dispatcher"
|
125
|
+
$>.puts "done initializing rails environment"
|
126
|
+
HttpEventMachine.module_eval "alias_method :process_actual_request, :process_rails_request"
|
127
|
+
end
|
128
|
+
|
129
|
+
def initialize_default
|
130
|
+
HttpEventMachine.module_eval "alias_method :process_actual_request, :process_default"
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
end # class Monorail::Monorail
|
135
|
+
end # module Monorail
|
136
|
+
|
137
|
+
|