wildnet-server 0.0.1-java
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.txt +0 -0
- data/README.rdoc +0 -0
- data/lib/version.rb +5 -0
- data/lib/wildnet-server/http_handler.rb +147 -0
- data/lib/wildnet-server/http_response.rb +89 -0
- data/lib/wildnet-server/kernel.rb +36 -0
- data/lib/wildnet-server/pipe_line_factory.rb +45 -0
- data/lib/wildnet-server/request.rb +5 -0
- data/lib/wildnet-server.rb +10 -0
- data/wildnet-server.gemspec +45 -0
- metadata +99 -0
data/LICENSE.txt
ADDED
File without changes
|
data/README.rdoc
ADDED
File without changes
|
data/lib/version.rb
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
module Wildnet::Server
|
2
|
+
|
3
|
+
java_import "org.jboss.netty.channel.ChannelHandlerContext"
|
4
|
+
java_import "org.jboss.netty.channel.ExceptionEvent"
|
5
|
+
java_import "org.jboss.netty.channel.MessageEvent"
|
6
|
+
java_import "org.jboss.netty.channel.SimpleChannelUpstreamHandler"
|
7
|
+
java_import "org.jboss.netty.handler.codec.http.HttpChunk"
|
8
|
+
java_import "org.jboss.netty.handler.codec.http.HttpHeaders"
|
9
|
+
java_import "org.jboss.netty.handler.codec.http.HttpRequest"
|
10
|
+
java_import "org.jboss.netty.handler.codec.http.HttpResponseStatus"
|
11
|
+
java_import "org.jboss.netty.handler.codec.http.HttpVersion"
|
12
|
+
|
13
|
+
java_import "java.io.FileOutputStream"
|
14
|
+
|
15
|
+
class HttpHandler < SimpleChannelUpstreamHandler
|
16
|
+
|
17
|
+
attr_accessor :app
|
18
|
+
|
19
|
+
def message_received context, event
|
20
|
+
|
21
|
+
unless event.message.kind_of?(HttpRequest)
|
22
|
+
|
23
|
+
chunk = event.message
|
24
|
+
|
25
|
+
chunk.content.readBytes(@upload_stream, chunk.content.capacity)
|
26
|
+
|
27
|
+
if chunk.isLast
|
28
|
+
@upload_stream.close
|
29
|
+
handle
|
30
|
+
end
|
31
|
+
|
32
|
+
return
|
33
|
+
end
|
34
|
+
|
35
|
+
request = event.message
|
36
|
+
@request = Request.new
|
37
|
+
|
38
|
+
@request["REQUEST_METHOD"] = request.getMethod.getName
|
39
|
+
@request["SCRIPT_NAME"] = ""
|
40
|
+
@request["PATH_INFO"] = request.getUri
|
41
|
+
@request["QUERY_STRING"] = ""
|
42
|
+
@request["SERVER_NAME"] = HttpHeaders.getHost request, "localhost"
|
43
|
+
@request["SERVER_PORT"] = 80
|
44
|
+
|
45
|
+
@request["rack.url_scheme"] = "http"
|
46
|
+
@request["rack.input"] = File.new(java.io.File.createTempFile("wildnet.", ".request", java.io.File.new(File.join(Rails.root, "tmp"))).getAbsolutePath())
|
47
|
+
@request["rack.errors"] = $stderr
|
48
|
+
@request["rack.multithread"] = true
|
49
|
+
@request["rack.multiprocess"] = false
|
50
|
+
@request["rack.run_once"] = false
|
51
|
+
|
52
|
+
@upload_stream = FileOutputStream.new(java.io.File.new(@request["rack.input"].path))
|
53
|
+
unless request.isChunked
|
54
|
+
request.content.readBytes(@upload_stream, request.getContent.capacity)
|
55
|
+
@upload_stream.close
|
56
|
+
end
|
57
|
+
|
58
|
+
if request.containsHeader "X-For-Host"
|
59
|
+
@request["SERVER_NAME"] = request.getHeader "X-For-Host"
|
60
|
+
end
|
61
|
+
|
62
|
+
if request.containsHeader "X-For-Scheme"
|
63
|
+
@request["rack.url_scheme"] = request.getHeader "X-For-Scheme"
|
64
|
+
end
|
65
|
+
|
66
|
+
if server_name = %r{(.+):([0-9]+)}.match(@request["SERVER_NAME"])
|
67
|
+
@request["SERVER_NAME"] = server_name[1]
|
68
|
+
@request["SERVER_PORT"] = server_name[2].to_i
|
69
|
+
end
|
70
|
+
|
71
|
+
if path_info = %r{(.+)\?(.+)}.match(@request["PATH_INFO"])
|
72
|
+
@request["PATH_INFO"] = path_info[1]
|
73
|
+
@request["QUERY_STRING"] = path_info[2]
|
74
|
+
end
|
75
|
+
|
76
|
+
if (@request["SERVER_PORT"] != 80 and @request["rack.url_scheme"] != "http") and (@request["SERVER_PORT"] != 443 and @request["rack.url_scheme"] != "https")
|
77
|
+
request.removeHeader "Host"
|
78
|
+
request.addHeader "Host", @request["SERVER_NAME"] + ":" + @request["SERVER_PORT"]
|
79
|
+
else
|
80
|
+
request.removeHeader "Host"
|
81
|
+
request.addHeader "Host", @request["SERVER_NAME"]
|
82
|
+
end
|
83
|
+
|
84
|
+
request.getHeaderNames.each do |header|
|
85
|
+
name = header.gsub("-", "_").upcase
|
86
|
+
if (name != "CONTENT_TYPE" and name != "CONTENT_LENGTH")
|
87
|
+
name = "HTTP_#{name}"
|
88
|
+
end
|
89
|
+
@request[name] = request.getHeader(header)
|
90
|
+
end
|
91
|
+
|
92
|
+
@request["rack.version"] = ::Rack::VERSION
|
93
|
+
|
94
|
+
@request["wildnet.context"] = context
|
95
|
+
@request["wildnet.response"] = HttpResponse.new(@request["wildnet.context"])
|
96
|
+
|
97
|
+
unless request.isChunked
|
98
|
+
handle
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
def handle
|
104
|
+
|
105
|
+
public_file = File.join(Rails.root, "public", @request["PATH_INFO"])
|
106
|
+
if File.exists?(public_file) and not File.directory?(public_file)
|
107
|
+
respond [200, {"X-Wildnet-Send-File" => public_file, "Content-Type" => "wildnet/detect"}, nil]
|
108
|
+
else
|
109
|
+
respond @app.call(@request)
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
def respond response
|
115
|
+
|
116
|
+
status, headers, body = response
|
117
|
+
|
118
|
+
@request["wildnet.response"].status = status
|
119
|
+
|
120
|
+
complete = headers.delete("X-Wildnet-Complete")
|
121
|
+
send_file = headers.delete("X-Wildnet-Send-File")
|
122
|
+
|
123
|
+
headers.each_pair do |header, value|
|
124
|
+
@request["wildnet.response"][header] = value
|
125
|
+
end
|
126
|
+
|
127
|
+
if send_file
|
128
|
+
@request["wildnet.response"].send_file(send_file)
|
129
|
+
else
|
130
|
+
body.each do |line|
|
131
|
+
@request["wildnet.response"] << line
|
132
|
+
end
|
133
|
+
@request["wildnet.response"].flush
|
134
|
+
end
|
135
|
+
|
136
|
+
@request["wildnet.response"].close(complete)
|
137
|
+
|
138
|
+
@request["rack.input"].close
|
139
|
+
File.delete(@request["rack.input"].path)
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
alias_method :messageReceived, :message_received
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require "mime/types"
|
2
|
+
|
3
|
+
module Wildnet::Server
|
4
|
+
|
5
|
+
java_import "org.jboss.netty.handler.codec.http.DefaultHttpResponse"
|
6
|
+
java_import "org.jboss.netty.channel.ChannelFutureListener"
|
7
|
+
java_import "org.jboss.netty.buffer.ChannelBuffers"
|
8
|
+
java_import "org.jboss.netty.handler.codec.http.HttpResponseStatus"
|
9
|
+
java_import "org.jboss.netty.handler.codec.http.HttpVersion"
|
10
|
+
java_import "org.jboss.netty.channel.DefaultFileRegion"
|
11
|
+
java_import "java.io.RandomAccessFile"
|
12
|
+
java_import "org.jboss.netty.channel.ChannelFutureProgressListener"
|
13
|
+
|
14
|
+
class Finisher
|
15
|
+
|
16
|
+
import ChannelFutureProgressListener
|
17
|
+
|
18
|
+
def initialize proc
|
19
|
+
@proc = proc
|
20
|
+
end
|
21
|
+
|
22
|
+
def operationComplete future
|
23
|
+
@proc.call
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
class HttpResponse < DefaultHttpResponse
|
29
|
+
|
30
|
+
def initialize context
|
31
|
+
super(HttpVersion::HTTP_1_1, HttpResponseStatus.valueOf(200))
|
32
|
+
@buffer = ChannelBuffers.dynamicBuffer
|
33
|
+
@context = context
|
34
|
+
@future = nil
|
35
|
+
@headers_sent = false
|
36
|
+
@closed = false
|
37
|
+
end
|
38
|
+
|
39
|
+
def status
|
40
|
+
getStatus().getCode()
|
41
|
+
end
|
42
|
+
|
43
|
+
def status= code
|
44
|
+
setStatus(HttpResponseStatus.valueOf(code))
|
45
|
+
end
|
46
|
+
|
47
|
+
def [] name
|
48
|
+
getHeader(name)
|
49
|
+
end
|
50
|
+
|
51
|
+
def []= name, value
|
52
|
+
setHeader(name, value)
|
53
|
+
end
|
54
|
+
|
55
|
+
def send_file path
|
56
|
+
if getHeader("Content-Type") == "wildnet/detect"
|
57
|
+
ct = ::MIME::Types.type_for(path).first
|
58
|
+
self["Content-Type"] = "text/plain"
|
59
|
+
self["Content-Type"] = ct.content_type if ct
|
60
|
+
end
|
61
|
+
raf = RandomAccessFile.new(path, "r")
|
62
|
+
region = DefaultFileRegion.new(raf.channel, 0, raf.length)
|
63
|
+
HttpHeaders.setContentLength(self, raf.length)
|
64
|
+
@future = @context.channel.write(self)
|
65
|
+
@future = @context.channel.write(region)
|
66
|
+
end
|
67
|
+
|
68
|
+
def << data
|
69
|
+
@buffer.writeBytes(data.to_s.to_java_bytes)
|
70
|
+
end
|
71
|
+
|
72
|
+
def flush
|
73
|
+
unless @headers_sent
|
74
|
+
@future = @context.channel.write(self)
|
75
|
+
end
|
76
|
+
if @buffer.writerIndex > 0
|
77
|
+
@future = @context.channel.write(@buffer)
|
78
|
+
@buffer = ChannelBuffers.dynamicBuffer
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def close proc = nil
|
83
|
+
@future.addListener(Finisher.new(proc)) if proc
|
84
|
+
@future.addListener(ChannelFutureListener::CLOSE)
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Wildnet::Server
|
2
|
+
|
3
|
+
java_import "org.jboss.netty.bootstrap.ServerBootstrap"
|
4
|
+
java_import "org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory"
|
5
|
+
|
6
|
+
java_import "java.net.InetSocketAddress"
|
7
|
+
java_import "java.util.concurrent.Executors"
|
8
|
+
|
9
|
+
class Kernel
|
10
|
+
|
11
|
+
def self.run app, options = {}
|
12
|
+
options[:Port] ||= 3000
|
13
|
+
options[:Host] ||= "0.0.0.0"
|
14
|
+
@@server = self.new(app, options)
|
15
|
+
@@server.start
|
16
|
+
Thread.new do
|
17
|
+
while true
|
18
|
+
sleep 10
|
19
|
+
end
|
20
|
+
end.join
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize app, options = {}
|
24
|
+
@app = app
|
25
|
+
@options = options
|
26
|
+
end
|
27
|
+
|
28
|
+
def start
|
29
|
+
@bootstrap = ServerBootstrap.new(NioServerSocketChannelFactory.new(Executors.newCachedThreadPool, Executors.newCachedThreadPool))
|
30
|
+
@bootstrap.setPipelineFactory(PipeLineFactory.new(@app))
|
31
|
+
@bootstrap.bind(InetSocketAddress.new(@options[:Host], @options[:Port]))
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Wildnet::Server
|
2
|
+
|
3
|
+
java_import "org.jboss.netty.channel.ChannelPipeline"
|
4
|
+
java_import "org.jboss.netty.channel.ChannelPipelineFactory"
|
5
|
+
java_import "org.jboss.netty.channel.Channels"
|
6
|
+
java_import "org.jboss.netty.handler.codec.http.HttpRequestDecoder"
|
7
|
+
java_import "org.jboss.netty.handler.codec.http.HttpResponseEncoder"
|
8
|
+
java_import "org.jboss.netty.handler.execution.ExecutionHandler"
|
9
|
+
java_import "org.jboss.netty.handler.execution.OrderedMemoryAwareThreadPoolExecutor"
|
10
|
+
java_import "org.jboss.netty.handler.stream.ChunkedWriteHandler"
|
11
|
+
|
12
|
+
class PipeLineFactory
|
13
|
+
|
14
|
+
import ChannelPipelineFactory
|
15
|
+
|
16
|
+
def initialize app
|
17
|
+
@executor = OrderedMemoryAwareThreadPoolExecutor.new 16, 0, 0
|
18
|
+
@execution_handler = ExecutionHandler.new @executor
|
19
|
+
@app = app
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_pipeline
|
23
|
+
|
24
|
+
handler = HttpHandler.new
|
25
|
+
handler.app = @app
|
26
|
+
|
27
|
+
pipeline = Channels.pipeline
|
28
|
+
|
29
|
+
pipeline.addLast "decoder", HttpRequestDecoder.new
|
30
|
+
pipeline.addLast "encoder", HttpResponseEncoder.new
|
31
|
+
|
32
|
+
pipeline.addLast "executor", @execution_handler
|
33
|
+
pipeline.addLast "chunkedWriter", ChunkedWriteHandler.new
|
34
|
+
pipeline.addLast "handler", handler
|
35
|
+
|
36
|
+
pipeline
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
# getPipeline is not Ruby-friendly ... but it is required by Java interface
|
41
|
+
alias_method :getPipeline, :get_pipeline
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require "java"
|
2
|
+
|
3
|
+
require File.expand_path("../version.rb", __FILE__)
|
4
|
+
require File.expand_path("../wildnet-server/request.rb", __FILE__)
|
5
|
+
require File.expand_path("../wildnet-server/http_response.rb", __FILE__)
|
6
|
+
require File.expand_path("../wildnet-server/http_handler.rb", __FILE__)
|
7
|
+
require File.expand_path("../wildnet-server/pipe_line_factory.rb", __FILE__)
|
8
|
+
require File.expand_path("../wildnet-server/kernel.rb", __FILE__)
|
9
|
+
|
10
|
+
Rack::Handler.register "wildnet", "Wildnet::Server::Kernel"
|
@@ -0,0 +1,45 @@
|
|
1
|
+
|
2
|
+
require File.expand_path("../lib/version", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
|
6
|
+
s.name = "wildnet-server"
|
7
|
+
s.version = Wildnet::Server::VERSION
|
8
|
+
s.authors = ["Marek Jelen"]
|
9
|
+
s.summary = "Http server"
|
10
|
+
s.description = "Http server on top of Netty library"
|
11
|
+
s.email = "marek@jelen.biz"
|
12
|
+
s.homepage = "http://github.com/marekjelen/wildnet-server"
|
13
|
+
s.licenses = ["MIT"]
|
14
|
+
|
15
|
+
s.platform = "java"
|
16
|
+
s.required_rubygems_version = ">= 1.3.6"
|
17
|
+
|
18
|
+
s.extra_rdoc_files = [
|
19
|
+
"LICENSE.txt",
|
20
|
+
"README.rdoc"
|
21
|
+
]
|
22
|
+
|
23
|
+
s.files = [
|
24
|
+
"LICENSE.txt",
|
25
|
+
"README.rdoc",
|
26
|
+
"lib/wildnet-server/http_handler.rb",
|
27
|
+
"lib/wildnet-server/http_response.rb",
|
28
|
+
"lib/wildnet-server/kernel.rb",
|
29
|
+
"lib/wildnet-server/pipe_line_factory.rb",
|
30
|
+
"lib/wildnet-server/request.rb",
|
31
|
+
"lib/wildnet-server.rb",
|
32
|
+
"lib/version.rb",
|
33
|
+
"wildnet-server.gemspec"
|
34
|
+
]
|
35
|
+
|
36
|
+
s.require_paths = ["lib"]
|
37
|
+
|
38
|
+
s.test_files = [
|
39
|
+
]
|
40
|
+
|
41
|
+
s.add_runtime_dependency("rack", ["> 1.0"])
|
42
|
+
s.add_runtime_dependency("wildnet-netty", ["> 1.0"])
|
43
|
+
|
44
|
+
end
|
45
|
+
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wildnet-server
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: java
|
11
|
+
authors:
|
12
|
+
- Marek Jelen
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-02-21 00:00:00 +01:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rack
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 0
|
30
|
+
version: "1.0"
|
31
|
+
type: :runtime
|
32
|
+
version_requirements: *id001
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: wildnet-netty
|
35
|
+
prerelease: false
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
segments:
|
41
|
+
- 1
|
42
|
+
- 0
|
43
|
+
version: "1.0"
|
44
|
+
type: :runtime
|
45
|
+
version_requirements: *id002
|
46
|
+
description: Http server on top of Netty library
|
47
|
+
email: marek@jelen.biz
|
48
|
+
executables: []
|
49
|
+
|
50
|
+
extensions: []
|
51
|
+
|
52
|
+
extra_rdoc_files:
|
53
|
+
- LICENSE.txt
|
54
|
+
- README.rdoc
|
55
|
+
files:
|
56
|
+
- LICENSE.txt
|
57
|
+
- README.rdoc
|
58
|
+
- lib/wildnet-server/http_handler.rb
|
59
|
+
- lib/wildnet-server/http_response.rb
|
60
|
+
- lib/wildnet-server/kernel.rb
|
61
|
+
- lib/wildnet-server/pipe_line_factory.rb
|
62
|
+
- lib/wildnet-server/request.rb
|
63
|
+
- lib/wildnet-server.rb
|
64
|
+
- lib/version.rb
|
65
|
+
- wildnet-server.gemspec
|
66
|
+
has_rdoc: true
|
67
|
+
homepage: http://github.com/marekjelen/wildnet-server
|
68
|
+
licenses:
|
69
|
+
- MIT
|
70
|
+
post_install_message:
|
71
|
+
rdoc_options: []
|
72
|
+
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
segments:
|
80
|
+
- 0
|
81
|
+
version: "0"
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
segments:
|
87
|
+
- 1
|
88
|
+
- 3
|
89
|
+
- 6
|
90
|
+
version: 1.3.6
|
91
|
+
requirements: []
|
92
|
+
|
93
|
+
rubyforge_project:
|
94
|
+
rubygems_version: 1.3.6
|
95
|
+
signing_key:
|
96
|
+
specification_version: 3
|
97
|
+
summary: Http server
|
98
|
+
test_files: []
|
99
|
+
|