bossan 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +23 -0
- data/.travis.yml +4 -0
- data/Gemfile +6 -0
- data/README.md +52 -0
- data/Rakefile +22 -0
- data/bossan.gemspec +20 -0
- data/examples/blog/README.md +19 -0
- data/examples/blog/app.rb +77 -0
- data/examples/blog/config.ru +4 -0
- data/examples/blog/public/style.css +18 -0
- data/examples/blog/views/login.erb +23 -0
- data/examples/blog/views/show_entries.erb +38 -0
- data/examples/config.ru +19 -0
- data/examples/hello.rb +13 -0
- data/examples/sinatra_app.rb +11 -0
- data/examples/views/index.haml +10 -0
- data/examples/views_sample.rb +11 -0
- data/ext/bossan/bossan_ext.c +20 -222
- data/ext/bossan/buffer.c +74 -0
- data/ext/bossan/buffer.h +43 -0
- data/ext/bossan/client.h +35 -0
- data/ext/bossan/extconf.rb +11 -0
- data/ext/bossan/picoev_kqueue.c +209 -0
- data/ext/bossan/request.c +62 -0
- data/ext/bossan/request.h +54 -0
- data/lib/bossan/version.rb +1 -1
- data/lib/rack/handler/bossan.rb +1 -1
- data/test/test_rack_env_query.rb +57 -0
- data/test/test_rack_env_simple.rb +60 -0
- data/test/test_rack_spec.rb +65 -0
- metadata +35 -9
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.o
|
19
|
+
*.so
|
20
|
+
Makefile
|
21
|
+
*.log
|
22
|
+
*.db
|
23
|
+
TAGS
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# Bossan
|
2
|
+
|
3
|
+
[![Build Status](https://secure.travis-ci.org/kubo39/bossan.png?branch=master)](http://travis-ci.org/kubo39/bossan)
|
4
|
+
|
5
|
+
Bossan is a high performance asynchronous ruby's rack-compliant web server.
|
6
|
+
|
7
|
+
## Requirements
|
8
|
+
|
9
|
+
Bossan requires Ruby 1.9.2 or later.
|
10
|
+
|
11
|
+
Bossan supports Linux, FreeBSD and Mac OS X(need gcc>=4.2).
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
from rubygems
|
16
|
+
|
17
|
+
`gem install bossan`
|
18
|
+
|
19
|
+
or from source:
|
20
|
+
|
21
|
+
```
|
22
|
+
git clone git://github.com/kubo39/bossan.git
|
23
|
+
cd bossan
|
24
|
+
rake
|
25
|
+
```
|
26
|
+
|
27
|
+
## Usage
|
28
|
+
|
29
|
+
simple rack app:
|
30
|
+
|
31
|
+
``` ruby
|
32
|
+
require 'bossan'
|
33
|
+
|
34
|
+
Bossan.run('127.0.0.1', 8000, proc {|env|
|
35
|
+
[
|
36
|
+
200, # Status code
|
37
|
+
{ # Response headers
|
38
|
+
'Content-Type' => 'text/html',
|
39
|
+
'Content-Length' => '13',
|
40
|
+
},
|
41
|
+
['hello, world!'] # Response body
|
42
|
+
]
|
43
|
+
})
|
44
|
+
```
|
45
|
+
|
46
|
+
## Contributing
|
47
|
+
|
48
|
+
1. Fork it
|
49
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
50
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
51
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
52
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
require "rbconfig"
|
4
|
+
|
5
|
+
task :default => [:compile, :clean, :test]
|
6
|
+
|
7
|
+
task :compile do
|
8
|
+
Dir.chdir File.expand_path("../ext/bossan", __FILE__)
|
9
|
+
sh "ruby extconf.rb"
|
10
|
+
sh "make"
|
11
|
+
sh "mv bossan_ext.#{RbConfig::CONFIG['DLEXT']} ../../lib/bossan/"
|
12
|
+
end
|
13
|
+
|
14
|
+
task :clean do
|
15
|
+
Dir.chdir File.expand_path("../ext/bossan", __FILE__)
|
16
|
+
sh "rm -f *.o Makefile"
|
17
|
+
end
|
18
|
+
|
19
|
+
task :test do
|
20
|
+
Dir.chdir File.expand_path("../test", __FILE__)
|
21
|
+
sh "ruby test_rack_spec.rb"
|
22
|
+
end
|
data/bossan.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/bossan/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = "bossan"
|
6
|
+
gem.version = Bossan::VERSION
|
7
|
+
gem.authors = ["Hiroki Noda"]
|
8
|
+
gem.email = ["kubo39@gmail.com"]
|
9
|
+
gem.description = %q{high performance asynchronous rack web server}
|
10
|
+
gem.summary = gem.description
|
11
|
+
gem.homepage = "https://github.com/kubo39/bossan"
|
12
|
+
|
13
|
+
gem.files = `git ls-files`.split($/)
|
14
|
+
gem.extensions = ["ext/bossan/extconf.rb"]
|
15
|
+
gem.require_paths = ["lib", "ext"]
|
16
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split($/)
|
17
|
+
|
18
|
+
gem.required_ruby_version = ">= 1.9.2"
|
19
|
+
gem.add_dependency "rack", ["~> 1.2"]
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# This is a simple microblog powered by sqlite.
|
2
|
+
|
3
|
+
### Requirements some extension
|
4
|
+
|
5
|
+
* ActiveRecord (ORM)
|
6
|
+
* eRuby (Template)
|
7
|
+
* SQLite (Database)
|
8
|
+
|
9
|
+
|
10
|
+
#### fire up a irb(pry)
|
11
|
+
|
12
|
+
require './app'; init_db
|
13
|
+
|
14
|
+
|
15
|
+
### Run
|
16
|
+
|
17
|
+
rackup config.ru -s bossan
|
18
|
+
|
19
|
+
visit http://0.0.0.0:9292
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
require 'active_record'
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
enable :sessions
|
6
|
+
|
7
|
+
DATABASE = './db/sinatr.db'
|
8
|
+
SECRET_KEY = 'development_key'
|
9
|
+
USERNAME = 'admin'
|
10
|
+
PASSWORD = 'default'
|
11
|
+
|
12
|
+
ActiveRecord::Base.establish_connection(
|
13
|
+
:adapter => 'sqlite3',
|
14
|
+
:database => DATABASE
|
15
|
+
)
|
16
|
+
|
17
|
+
get '/' do
|
18
|
+
@entries = Entries.find(:all).map do |row|
|
19
|
+
{:title => row.title,
|
20
|
+
:text => row.text }
|
21
|
+
end
|
22
|
+
@entries ||= []
|
23
|
+
erb :show_entries
|
24
|
+
end
|
25
|
+
|
26
|
+
post '/add' do
|
27
|
+
halt(401) if session.include?([:logged_in])
|
28
|
+
Entries.create(:title => params[:title],
|
29
|
+
:text => params[:text])
|
30
|
+
redirect '/'
|
31
|
+
end
|
32
|
+
|
33
|
+
post '/login' do
|
34
|
+
@err = nil
|
35
|
+
if params[:username] != USERNAME
|
36
|
+
@err = "Invalid username #{params[:username]}"
|
37
|
+
elsif params[:password] != PASSWORD
|
38
|
+
@err = "Invalid password"
|
39
|
+
else
|
40
|
+
session[:logged_in] = params[:username]
|
41
|
+
redirect '/'
|
42
|
+
end
|
43
|
+
erb :login
|
44
|
+
end
|
45
|
+
|
46
|
+
get '/login' do
|
47
|
+
erb :login
|
48
|
+
end
|
49
|
+
|
50
|
+
get '/logout' do
|
51
|
+
session.delete :logged_in
|
52
|
+
erb :show_entries
|
53
|
+
end
|
54
|
+
|
55
|
+
class Schema < ActiveRecord::Migration
|
56
|
+
def self.up
|
57
|
+
create_table :entries do |t|
|
58
|
+
t.column :title, :string, :null => false
|
59
|
+
t.column :text, :string, :null => false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.down
|
64
|
+
drop_table :entries
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class Entries < ActiveRecord::Base
|
69
|
+
end
|
70
|
+
|
71
|
+
def init_db
|
72
|
+
Schema.migrate :up
|
73
|
+
end
|
74
|
+
|
75
|
+
def drop_db
|
76
|
+
Schema.migrate :down
|
77
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
body { font-family: sans-serif; background: #eee; }
|
2
|
+
a, h1, h2 { color: #377BA8; }
|
3
|
+
h1, h2 { font-family: 'Georgia', serif; margin: 0; }
|
4
|
+
h1 { border-bottom: 2px solid #eee; }
|
5
|
+
h2 { font-size: 1.2em; }
|
6
|
+
|
7
|
+
.page { margin: 2em auto; width: 35em; border: 5px solid #ccc;
|
8
|
+
padding: 0.8em; background: white; }
|
9
|
+
.entries { list-style: none; margin: 0; padding: 0; }
|
10
|
+
.entries li { margin: 0.8em 1.2em; }
|
11
|
+
.entries li h2 { margin-left: -1em; }
|
12
|
+
.add-entry { font-size: 0.9em; border-bottom: 1px solid #ccc; }
|
13
|
+
.add-entry dl { font-weight: bold; }
|
14
|
+
.metanav { text-align: right; font-size: 0.8em; padding: 0.3em;
|
15
|
+
margin-bottom: 1em; background: #fafafa; }
|
16
|
+
.flash { background: #CEE5F5; padding: 0.5em;
|
17
|
+
border: 1px solid #AACBE2; }
|
18
|
+
.error { background: #F0D6D6; padding: 0.5em; }
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Sinatr</title>
|
5
|
+
<link rel="stylesheet" type="text/css" href="/static/style.css">
|
6
|
+
</head>
|
7
|
+
<body>
|
8
|
+
<div class="page">
|
9
|
+
<h2>Login</h2>
|
10
|
+
<% if @err %>
|
11
|
+
<p class="error"><h2>Error:</h2>
|
12
|
+
<%= @err %>
|
13
|
+
<% end %>
|
14
|
+
<form action="/login" method="POST">
|
15
|
+
<h3>Username:</h3>
|
16
|
+
<input type="text" name="username">
|
17
|
+
<h3>Password:</h3>
|
18
|
+
<input type="password" name="password">
|
19
|
+
<input type="submit" value="Login">
|
20
|
+
</form>
|
21
|
+
</div>
|
22
|
+
</body>
|
23
|
+
</html>
|
@@ -0,0 +1,38 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Sinatr</title>
|
5
|
+
<link rel="stylesheet" type="text/css" href="/static/style.css"/>
|
6
|
+
</head>
|
7
|
+
<body>
|
8
|
+
<div class="page">
|
9
|
+
<h1>Sinatr</h1>
|
10
|
+
<div class="metanav">
|
11
|
+
<% unless session.include?(:logged_in) %>
|
12
|
+
<a href="/login">log in</a>
|
13
|
+
<% else %>
|
14
|
+
<a href="/logout">log out</a>
|
15
|
+
<% end %>
|
16
|
+
</div>
|
17
|
+
</div>
|
18
|
+
<% if session.include?(:logged_in) %>
|
19
|
+
<form action="/add" method="POST" class="add">
|
20
|
+
|
21
|
+
<h3>Title:</h3>
|
22
|
+
<input type="text" size="30" name="title">
|
23
|
+
<h3>Text:</h3>
|
24
|
+
<textarea name="text" rows="5" cols="40"></textarea>
|
25
|
+
<input type="submit" value="Share">
|
26
|
+
|
27
|
+
</form>
|
28
|
+
<% end %>
|
29
|
+
<ul class="entries">
|
30
|
+
<% unless (@entries == [] || @entries == nil) %>
|
31
|
+
<% @entries.each do |entry| %>
|
32
|
+
<h2><%= entry[:title] %></h2>
|
33
|
+
<%= entry[:text] %>
|
34
|
+
<% end %>
|
35
|
+
<% end %>
|
36
|
+
</ul>
|
37
|
+
</body>
|
38
|
+
<html>
|
data/examples/config.ru
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'bossan'
|
2
|
+
require 'pp'
|
3
|
+
|
4
|
+
class MyApp
|
5
|
+
def call env
|
6
|
+
body = ['hi!']
|
7
|
+
# pp env
|
8
|
+
[
|
9
|
+
200, # Status code
|
10
|
+
{ 'Content-Type' => 'text/html',
|
11
|
+
'Content-Length' => body.join.size.to_s,
|
12
|
+
}, # Reponse headers
|
13
|
+
body # Body of the response
|
14
|
+
]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Rack::Handler::Bossan.run MyApp.new
|
19
|
+
run MyApp.new
|
data/examples/hello.rb
ADDED
data/ext/bossan/bossan_ext.c
CHANGED
@@ -4,10 +4,6 @@
|
|
4
4
|
#include <stddef.h>
|
5
5
|
#include <unistd.h>
|
6
6
|
#include <errno.h>
|
7
|
-
#include <stdio.h>
|
8
|
-
#include <stdlib.h>
|
9
|
-
#include <string.h>
|
10
|
-
#include <inttypes.h>
|
11
7
|
#include <arpa/inet.h>
|
12
8
|
#include <signal.h>
|
13
9
|
#include <sys/socket.h>
|
@@ -24,9 +20,12 @@
|
|
24
20
|
#include <netinet/in.h>
|
25
21
|
#include <netinet/tcp.h>
|
26
22
|
#include <netdb.h>
|
23
|
+
|
27
24
|
#include "time_cache.h"
|
28
25
|
#include "http_parser.h"
|
29
26
|
#include "picoev.h"
|
27
|
+
#include "buffer.h"
|
28
|
+
#include "client.h"
|
30
29
|
|
31
30
|
#define MAX_FDS 1024 * 8
|
32
31
|
#define ACCEPT_TIMEOUT_SECS 1
|
@@ -38,18 +37,8 @@
|
|
38
37
|
#define MAX_BUFSIZE 1024 * 8
|
39
38
|
#define INPUT_BUF_SIZE 1024 * 8
|
40
39
|
|
41
|
-
#define LIMIT_MAX 1024 * 1024 * 1024
|
42
|
-
|
43
40
|
#define LIMIT_SIZE 1024 * 512
|
44
41
|
|
45
|
-
#define LIMIT_PATH 1024 * 4
|
46
|
-
#define LIMIT_FRAGMENT 1024
|
47
|
-
#define LIMIT_URI 1024 * 4
|
48
|
-
#define LIMIT_QUERY_STRING 1024 * 8
|
49
|
-
|
50
|
-
#define LIMIT_REQUEST_FIELDS 30
|
51
|
-
#define LIMIT_REQUEST_FIELD_SIZE 1024 * 8
|
52
|
-
|
53
42
|
#define CRLF "\r\n"
|
54
43
|
#define DELIM ": "
|
55
44
|
|
@@ -61,7 +50,7 @@
|
|
61
50
|
|
62
51
|
#define MSG_413 ("HTTP/1.0 413 Request Entity Too Large\r\nContent-Type: text/html\r\nServer: " SERVER "\r\n\r\n<html><head><title>Request Entity Too Large</title></head><body><p>Request Entity Too Large.</p></body></html>")
|
63
52
|
|
64
|
-
#define SERVER "bossan/0.1.
|
53
|
+
#define SERVER "bossan/0.1.7"
|
65
54
|
|
66
55
|
VALUE server; // Bossan
|
67
56
|
|
@@ -129,74 +118,6 @@ int max_content_length = 1024 * 1024 * 16; //max_content_length
|
|
129
118
|
|
130
119
|
static VALUE StringIO;
|
131
120
|
|
132
|
-
typedef enum {
|
133
|
-
WRITE_OK,
|
134
|
-
MEMORY_ERROR,
|
135
|
-
LIMIT_OVER,
|
136
|
-
} buffer_result;
|
137
|
-
|
138
|
-
typedef struct {
|
139
|
-
char *buf;
|
140
|
-
size_t buf_size;
|
141
|
-
size_t len;
|
142
|
-
size_t limit;
|
143
|
-
} buffer;
|
144
|
-
|
145
|
-
typedef enum {
|
146
|
-
FIELD,
|
147
|
-
VAL,
|
148
|
-
} field_type;
|
149
|
-
|
150
|
-
typedef struct {
|
151
|
-
buffer *field;
|
152
|
-
buffer *value;
|
153
|
-
} header;
|
154
|
-
|
155
|
-
typedef struct {
|
156
|
-
buffer *path;
|
157
|
-
buffer *uri;
|
158
|
-
buffer *query_string;
|
159
|
-
buffer *fragment;
|
160
|
-
header *headers[LIMIT_REQUEST_FIELDS];
|
161
|
-
uint32_t num_headers;
|
162
|
-
field_type last_header_element;
|
163
|
-
} request;
|
164
|
-
|
165
|
-
typedef enum {
|
166
|
-
BODY_TYPE_NONE,
|
167
|
-
BODY_TYPE_TMPFILE,
|
168
|
-
BODY_TYPE_BUFFER
|
169
|
-
} request_body_type;
|
170
|
-
|
171
|
-
typedef struct _client {
|
172
|
-
int fd;
|
173
|
-
char *remote_addr;
|
174
|
-
uint32_t remote_port;
|
175
|
-
uint8_t keep_alive;
|
176
|
-
request *req;
|
177
|
-
uint32_t body_length;
|
178
|
-
int body_readed;
|
179
|
-
void *body;
|
180
|
-
int bad_request_code;
|
181
|
-
request_body_type body_type;
|
182
|
-
uint8_t complete;
|
183
|
-
|
184
|
-
http_parser *http; // http req parser
|
185
|
-
VALUE environ; // rack environ
|
186
|
-
int status_code; // response status code
|
187
|
-
|
188
|
-
VALUE http_status; // response status line
|
189
|
-
VALUE headers; // http response headers
|
190
|
-
uint8_t header_done; // header write status
|
191
|
-
VALUE response; // rack response object
|
192
|
-
VALUE response_iter; // rack response object
|
193
|
-
uint8_t content_length_set; // content_length_set flag
|
194
|
-
uint32_t content_length; // content_length
|
195
|
-
uint32_t write_bytes; // send body length
|
196
|
-
void *bucket; //write_data
|
197
|
-
uint8_t response_closed; //response closed flag
|
198
|
-
} client_t;
|
199
|
-
|
200
121
|
typedef struct iovec iovec_t;
|
201
122
|
|
202
123
|
typedef struct {
|
@@ -209,78 +130,6 @@ typedef struct {
|
|
209
130
|
} write_bucket;
|
210
131
|
|
211
132
|
|
212
|
-
buffer *
|
213
|
-
new_buffer(size_t buf_size, size_t limit)
|
214
|
-
{
|
215
|
-
buffer *buf;
|
216
|
-
buf = ruby_xmalloc(sizeof(buffer));
|
217
|
-
memset(buf, 0, sizeof(buffer));
|
218
|
-
buf->buf = ruby_xmalloc(sizeof(char) * buf_size);
|
219
|
-
buf->buf_size = buf_size;
|
220
|
-
if(limit){
|
221
|
-
buf->limit = limit;
|
222
|
-
}else{
|
223
|
-
buf->limit = LIMIT_MAX;
|
224
|
-
}
|
225
|
-
return buf;
|
226
|
-
}
|
227
|
-
|
228
|
-
|
229
|
-
buffer_result
|
230
|
-
write2buf(buffer *buf, const char *c, size_t l)
|
231
|
-
{
|
232
|
-
size_t newl;
|
233
|
-
char *newbuf;
|
234
|
-
buffer_result ret = WRITE_OK;
|
235
|
-
newl = buf->len + l;
|
236
|
-
|
237
|
-
if (newl >= buf->buf_size) {
|
238
|
-
buf->buf_size *= 2;
|
239
|
-
if(buf->buf_size <= newl) {
|
240
|
-
buf->buf_size = (int)(newl + 1);
|
241
|
-
}
|
242
|
-
if(buf->buf_size > buf->limit){
|
243
|
-
buf->buf_size = buf->limit + 1;
|
244
|
-
}
|
245
|
-
newbuf = (char*)ruby_xrealloc(buf->buf, buf->buf_size);
|
246
|
-
buf->buf = newbuf;
|
247
|
-
}
|
248
|
-
if(newl >= buf->buf_size){
|
249
|
-
l = buf->buf_size - buf->len -1;
|
250
|
-
ret = LIMIT_OVER;
|
251
|
-
}
|
252
|
-
memcpy(buf->buf + buf->len, c , l);
|
253
|
-
buf->len += (int)l;
|
254
|
-
return ret;
|
255
|
-
}
|
256
|
-
|
257
|
-
|
258
|
-
void
|
259
|
-
free_buffer(buffer *buf)
|
260
|
-
{
|
261
|
-
ruby_xfree(buf->buf);
|
262
|
-
ruby_xfree(buf);
|
263
|
-
}
|
264
|
-
|
265
|
-
|
266
|
-
VALUE
|
267
|
-
getRbString(buffer *buf)
|
268
|
-
{
|
269
|
-
VALUE o;
|
270
|
-
o = rb_str_new(buf->buf, buf->len);
|
271
|
-
free_buffer(buf);
|
272
|
-
return o;
|
273
|
-
}
|
274
|
-
|
275
|
-
|
276
|
-
char *
|
277
|
-
getString(buffer *buf)
|
278
|
-
{
|
279
|
-
buf->buf[buf->len] = '\0';
|
280
|
-
return buf->buf;
|
281
|
-
}
|
282
|
-
|
283
|
-
|
284
133
|
int
|
285
134
|
open_log_file(const char *path)
|
286
135
|
{
|
@@ -858,67 +707,6 @@ response_start(client_t *client)
|
|
858
707
|
}
|
859
708
|
|
860
709
|
|
861
|
-
request *
|
862
|
-
new_request(void)
|
863
|
-
{
|
864
|
-
request *req = (request *)ruby_xmalloc(sizeof(request));
|
865
|
-
memset(req, 0, sizeof(request));
|
866
|
-
return req;
|
867
|
-
}
|
868
|
-
|
869
|
-
|
870
|
-
header *
|
871
|
-
new_header(size_t fsize, size_t flimit, size_t vsize, size_t vlimit)
|
872
|
-
{
|
873
|
-
header *h;
|
874
|
-
h = ruby_xmalloc(sizeof(header));
|
875
|
-
h->field = new_buffer(fsize, flimit);
|
876
|
-
h->value = new_buffer(vsize, vlimit);
|
877
|
-
return h;
|
878
|
-
}
|
879
|
-
|
880
|
-
|
881
|
-
void
|
882
|
-
free_header(header *h)
|
883
|
-
{
|
884
|
-
ruby_xfree(h);
|
885
|
-
}
|
886
|
-
|
887
|
-
|
888
|
-
void
|
889
|
-
free_request(request *req)
|
890
|
-
{
|
891
|
-
uint32_t i;
|
892
|
-
header *h;
|
893
|
-
if(req->path){
|
894
|
-
free_buffer(req->path);
|
895
|
-
req->path = NULL;
|
896
|
-
}
|
897
|
-
if(req->uri){
|
898
|
-
free_buffer(req->uri);
|
899
|
-
req->uri = NULL;
|
900
|
-
}
|
901
|
-
if(req->query_string){
|
902
|
-
free_buffer(req->query_string);
|
903
|
-
req->query_string = NULL;
|
904
|
-
}
|
905
|
-
if(req->fragment){
|
906
|
-
free_buffer(req->fragment);
|
907
|
-
req->fragment = NULL;
|
908
|
-
}
|
909
|
-
for(i = 0; i < req->num_headers+1; i++){
|
910
|
-
h = req->headers[i];
|
911
|
-
if(h){
|
912
|
-
free_buffer(h->field);
|
913
|
-
free_buffer(h->value);
|
914
|
-
free_header(h);
|
915
|
-
req->headers[i] = NULL;
|
916
|
-
}
|
917
|
-
}
|
918
|
-
ruby_xfree(req);
|
919
|
-
}
|
920
|
-
|
921
|
-
|
922
710
|
static void
|
923
711
|
key_upper(char *s, const char *key, size_t len)
|
924
712
|
{
|
@@ -955,9 +743,10 @@ write_body2file(client_t *client, const char *buffer, size_t buffer_len)
|
|
955
743
|
static int
|
956
744
|
write_body2mem(client_t *client, const char *buffer, size_t buffer_len)
|
957
745
|
{
|
746
|
+
VALUE obj;
|
958
747
|
/* printf("body2mem called\n"); */
|
959
|
-
|
960
|
-
|
748
|
+
|
749
|
+
rb_funcall((VALUE)client->body, rb_intern("write"), 1, rb_str_new(buffer, buffer_len));
|
961
750
|
client->body_readed += buffer_len;
|
962
751
|
#ifdef DEBUG
|
963
752
|
printf("write_body2mem %d bytes \n", buffer_len);
|
@@ -1234,6 +1023,7 @@ body_cb (http_parser *p, const char *buf, size_t len, char partial)
|
|
1234
1023
|
#ifdef DEBUG
|
1235
1024
|
printf("client->body_length %d \n", client->body_length);
|
1236
1025
|
#endif
|
1026
|
+
client->body = rb_funcall(StringIO, i_new, 1, rb_str_new2(""));
|
1237
1027
|
client->body_type = BODY_TYPE_BUFFER;
|
1238
1028
|
#ifdef DEBUG
|
1239
1029
|
printf("BODY_TYPE_BUFFER \n");
|
@@ -1723,10 +1513,18 @@ prepare_call_rack(client_t *client)
|
|
1723
1513
|
VALUE input, object, c;
|
1724
1514
|
char *val;
|
1725
1515
|
|
1726
|
-
|
1727
|
-
|
1728
|
-
|
1729
|
-
|
1516
|
+
if(client->body_type == BODY_TYPE_BUFFER) {
|
1517
|
+
/* rb_p( rb_funcall((VALUE)client->body, rb_intern("gets"), 0) ); */
|
1518
|
+
rb_p( rb_funcall((VALUE)client->body, rb_intern("seek"), 1, INT2NUM(0)) );
|
1519
|
+
rb_hash_aset(client->environ, rack_input, (VALUE)client->body);
|
1520
|
+
} else {
|
1521
|
+
object = rb_str_new2("");
|
1522
|
+
input = rb_funcall(StringIO, i_new, 1, object);
|
1523
|
+
rb_gc_register_address(&input);
|
1524
|
+
rb_hash_aset(client->environ, rack_input, input);
|
1525
|
+
/* client->body = object; */
|
1526
|
+
client->body = input;
|
1527
|
+
}
|
1730
1528
|
|
1731
1529
|
if(is_keep_alive){
|
1732
1530
|
//support keep-alive
|