jruby-http-kit 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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +72 -0
- data/Rakefile +1 -0
- data/example/config.ru +9 -0
- data/example/hello_world.rb +17 -0
- data/example/rack.rb +11 -0
- data/example/ring.rb +31 -0
- data/example/sinatra/app.rb +9 -0
- data/example/sinatra/config.ru +8 -0
- data/example/webmachine/Gemfile +4 -0
- data/example/webmachine/Gemfile.lock +16 -0
- data/example/webmachine/app.rb +37 -0
- data/jruby-http-kit.gemspec +25 -0
- data/lib/http_kit/rack_handler.rb +139 -0
- data/lib/http_kit/server.rb +62 -0
- data/lib/http_kit/version.rb +3 -0
- data/lib/http_kit.rb +6 -0
- data/lib/java/clojure-1.5.1.jar +0 -0
- data/lib/java/http-kit.jar +0 -0
- data/lib/rack/handler/http_kit.rb +3 -0
- data/lib/rack/http_kit.rb +3 -0
- data/lib/webmachine/adapters/ring.rb +135 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/support/test_resource.rb +75 -0
- data/spec/webmachine/ring_adapter_spec.rb +127 -0
- data/src/.classpath +7 -0
- data/src/.project +17 -0
- data/src/org/httpkit/BytesInputStream.class +0 -0
- data/src/org/httpkit/BytesInputStream.java +83 -0
- data/src/org/httpkit/DateFormatter.class +0 -0
- data/src/org/httpkit/DynamicBytes.class +0 -0
- data/src/org/httpkit/DynamicBytes.java +76 -0
- data/src/org/httpkit/HTTPException.class +0 -0
- data/src/org/httpkit/HTTPException.java +10 -0
- data/src/org/httpkit/HeaderMap.class +0 -0
- data/src/org/httpkit/HeaderMap.java +98 -0
- data/src/org/httpkit/HttpMethod.class +0 -0
- data/src/org/httpkit/HttpMethod.java +28 -0
- data/src/org/httpkit/HttpStatus.class +0 -0
- data/src/org/httpkit/HttpStatus.java +416 -0
- data/src/org/httpkit/HttpUtils.class +0 -0
- data/src/org/httpkit/HttpUtils.java +484 -0
- data/src/org/httpkit/HttpVersion.class +0 -0
- data/src/org/httpkit/HttpVersion.java +5 -0
- data/src/org/httpkit/LineReader.class +0 -0
- data/src/org/httpkit/LineReader.java +52 -0
- data/src/org/httpkit/LineTooLargeException.class +0 -0
- data/src/org/httpkit/LineTooLargeException.java +13 -0
- data/src/org/httpkit/PrefixThreadFactory.class +0 -0
- data/src/org/httpkit/PrefixThreadFactory.java +20 -0
- data/src/org/httpkit/PriorityQueue.class +0 -0
- data/src/org/httpkit/PriorityQueue.java +235 -0
- data/src/org/httpkit/ProtocolException.class +0 -0
- data/src/org/httpkit/ProtocolException.java +10 -0
- data/src/org/httpkit/RequestTooLargeException.class +0 -0
- data/src/org/httpkit/RequestTooLargeException.java +10 -0
- data/src/org/httpkit/client/AbortException.class +0 -0
- data/src/org/httpkit/client/AbortException.java +13 -0
- data/src/org/httpkit/client/Decoder.class +0 -0
- data/src/org/httpkit/client/Decoder.java +182 -0
- data/src/org/httpkit/client/Handler.class +0 -0
- data/src/org/httpkit/client/HttpClient.class +0 -0
- data/src/org/httpkit/client/HttpClient.java +393 -0
- data/src/org/httpkit/client/HttpsRequest.class +0 -0
- data/src/org/httpkit/client/HttpsRequest.java +141 -0
- data/src/org/httpkit/client/IFilter$1.class +0 -0
- data/src/org/httpkit/client/IFilter$MaxBodyFilter.class +0 -0
- data/src/org/httpkit/client/IFilter.class +0 -0
- data/src/org/httpkit/client/IFilter.java +53 -0
- data/src/org/httpkit/client/IRespListener.class +0 -0
- data/src/org/httpkit/client/IRespListener.java +30 -0
- data/src/org/httpkit/client/IResponseHandler.class +0 -0
- data/src/org/httpkit/client/IResponseHandler.java +18 -0
- data/src/org/httpkit/client/PersistentConn.class +0 -0
- data/src/org/httpkit/client/PersistentConn.java +33 -0
- data/src/org/httpkit/client/Request.class +0 -0
- data/src/org/httpkit/client/Request.java +74 -0
- data/src/org/httpkit/client/RequestConfig.class +0 -0
- data/src/org/httpkit/client/RequestConfig.java +28 -0
- data/src/org/httpkit/client/RespListener.class +0 -0
- data/src/org/httpkit/client/RespListener.java +160 -0
- data/src/org/httpkit/client/SslContextFactory.class +0 -0
- data/src/org/httpkit/client/SslContextFactory.java +79 -0
- data/src/org/httpkit/client/State.class +0 -0
- data/src/org/httpkit/client/TimeoutException.class +0 -0
- data/src/org/httpkit/client/TimeoutException.java +12 -0
- data/src/org/httpkit/client/TrustManagerFactory$1.class +0 -0
- data/src/org/httpkit/client/TrustManagerFactory.class +0 -0
- data/src/org/httpkit/server/AsyncChannel.class +0 -0
- data/src/org/httpkit/server/AsyncChannel.java +286 -0
- data/src/org/httpkit/server/ClojureRing.class +0 -0
- data/src/org/httpkit/server/Frame$BinaryFrame.class +0 -0
- data/src/org/httpkit/server/Frame$CloseFrame.class +0 -0
- data/src/org/httpkit/server/Frame$PingFrame.class +0 -0
- data/src/org/httpkit/server/Frame$TextFrame.class +0 -0
- data/src/org/httpkit/server/Frame.class +0 -0
- data/src/org/httpkit/server/Frame.java +73 -0
- data/src/org/httpkit/server/HttpAtta.class +0 -0
- data/src/org/httpkit/server/HttpAtta.java +10 -0
- data/src/org/httpkit/server/HttpDecoder$State.class +0 -0
- data/src/org/httpkit/server/HttpDecoder.class +0 -0
- data/src/org/httpkit/server/HttpDecoder.java +202 -0
- data/src/org/httpkit/server/HttpHandler.class +0 -0
- data/src/org/httpkit/server/HttpRequest.class +0 -0
- data/src/org/httpkit/server/HttpRequest.java +109 -0
- data/src/org/httpkit/server/HttpServer.class +0 -0
- data/src/org/httpkit/server/HttpServer.java +281 -0
- data/src/org/httpkit/server/IHandler.class +0 -0
- data/src/org/httpkit/server/IHandler.java +12 -0
- data/src/org/httpkit/server/LinkingRunnable.class +0 -0
- data/src/org/httpkit/server/Rack.class +0 -0
- data/src/org/httpkit/server/RackApplication.class +0 -0
- data/src/org/httpkit/server/RackApplication.java +10 -0
- data/src/org/httpkit/server/RackHandler$1.class +0 -0
- data/src/org/httpkit/server/RackHandler.class +0 -0
- data/src/org/httpkit/server/RackHandler.java +259 -0
- data/src/org/httpkit/server/RackHttpHandler.class +0 -0
- data/src/org/httpkit/server/RackHttpHandler.java +20 -0
- data/src/org/httpkit/server/RespCallback.class +0 -0
- data/src/org/httpkit/server/RespCallback.java +19 -0
- data/src/org/httpkit/server/RingHandler$1.class +0 -0
- data/src/org/httpkit/server/RingHandler.class +0 -0
- data/src/org/httpkit/server/RingHandler.java +222 -0
- data/src/org/httpkit/server/ServerAtta.class +0 -0
- data/src/org/httpkit/server/ServerAtta.java +22 -0
- data/src/org/httpkit/server/WSDecoder$State.class +0 -0
- data/src/org/httpkit/server/WSDecoder.class +0 -0
- data/src/org/httpkit/server/WSDecoder.java +181 -0
- data/src/org/httpkit/server/WSHandler.class +0 -0
- data/src/org/httpkit/server/WsAtta.class +0 -0
- data/src/org/httpkit/server/WsAtta.java +11 -0
- data/src/org/httpkit/timer/CancelableFutureTask.class +0 -0
- data/src/org/httpkit/timer/CancelableFutureTask.java +52 -0
- data/src/org/httpkit/timer/TimerService.class +0 -0
- data/src/org/httpkit/timer/TimerService.java +89 -0
- metadata +241 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 56c70ef0759f2822347d81dbe2b63df5943b4b49
|
|
4
|
+
data.tar.gz: ec17992ca5cce5de410c8e82becb9139892fcd23
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 0f003e0b6387208e134bb99f411c501f0313ffe471898b51ee9c69444416e8fbcbc67dfdfaac7dff6fe36e9f710771b6f47042560c91b1b4f359937c4f6b0448
|
|
7
|
+
data.tar.gz: 61c684208b24f10fcb11ff71b7779f6fc2d87d070b2bf1f0f9d9f4bcbbd9c8a3d13668c69f292f94253a64c977c03cc1a9d20c735df366582877b47175a00a83
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2013 Dmitriy Rozhkov
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
jruby-http-kit
|
|
2
|
+
==============
|
|
3
|
+
|
|
4
|
+
JRuby wrapper for Clojure HTTP Kit library. Just a proof of a concept for now.
|
|
5
|
+
|
|
6
|
+
```
|
|
7
|
+
jruby -s ring_example.rb
|
|
8
|
+
|
|
9
|
+
curl -v 0.0.0.0:8089
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
MacBook Pro Retina 13" (2.5 GHz i5, 8GB RAM)
|
|
13
|
+
|
|
14
|
+
server runs in irb :)
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
λ ~/ wrk -t4 -c400 -d30 http://0.0.0.0:8089
|
|
18
|
+
Running 30s test @ http://0.0.0.0:8089
|
|
19
|
+
4 threads and 400 connections
|
|
20
|
+
|
|
21
|
+
Thread Stats Avg Stdev Max +/- Stdev
|
|
22
|
+
Latency 10.09ms 6.96ms 67.70ms 81.66%
|
|
23
|
+
Req/Sec 6.84k 1.99k 9.00k 82.93%
|
|
24
|
+
1000916 requests in 30.00s, 142.48MB read
|
|
25
|
+
Socket errors: connect 0, read 756, write 0, timeout 67
|
|
26
|
+
Requests/sec: 33367.54
|
|
27
|
+
Transfer/sec: 4.75MB
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
Add this line to your application's Gemfile:
|
|
33
|
+
|
|
34
|
+
gem 'jruby-http-kit'
|
|
35
|
+
|
|
36
|
+
And then execute:
|
|
37
|
+
|
|
38
|
+
$ bundle
|
|
39
|
+
|
|
40
|
+
Or install it yourself as:
|
|
41
|
+
|
|
42
|
+
$ gem install jruby-http-kit
|
|
43
|
+
|
|
44
|
+
## Contributing
|
|
45
|
+
|
|
46
|
+
1. Fork it
|
|
47
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
48
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
49
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
50
|
+
5. Create new Pull Request
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
## License
|
|
54
|
+
|
|
55
|
+
### JRuby HTTP Kit wrapper
|
|
56
|
+
|
|
57
|
+
Copyright (c) 2013 Dmitriy Rozhkov
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
### HTTP Kit
|
|
61
|
+
|
|
62
|
+
Copyright © 2012-2013 [Feng Shen](http://shenfeng.me/). Distributed under the [Apache License Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html).
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
### Clojure
|
|
66
|
+
|
|
67
|
+
Copyright (c) Rich Hickey. All rights reserved.
|
|
68
|
+
|
|
69
|
+
The use and distribution terms for this software are covered by the
|
|
70
|
+
|
|
71
|
+
Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
|
72
|
+
|
data/Rakefile
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
data/example/config.ru
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class HelloWorld
|
|
2
|
+
def call(request)
|
|
3
|
+
body = "<html><p>Hello!</p></html>"
|
|
4
|
+
|
|
5
|
+
# headers = ["Content-Type", "text/html"].to_java(:string)
|
|
6
|
+
# headers = Java::ClojureLang::PersistentHashMap.create(headers)
|
|
7
|
+
|
|
8
|
+
# resp = [
|
|
9
|
+
# Java::ClojureLang::Keyword.intern("status") , 200,
|
|
10
|
+
# Java::ClojureLang::Keyword.intern("headers") , headers,
|
|
11
|
+
# Java::ClojureLang::Keyword.intern("body") , body
|
|
12
|
+
# ].to_java
|
|
13
|
+
# return Java::ClojureLang::PersistentHashMap.create(resp)
|
|
14
|
+
|
|
15
|
+
return [200, {"Content-Type" => "text/html"}, [body]]
|
|
16
|
+
end
|
|
17
|
+
end
|
data/example/rack.rb
ADDED
data/example/ring.rb
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
$LOAD_PATH << '../lib'
|
|
2
|
+
|
|
3
|
+
require 'http_kit'
|
|
4
|
+
|
|
5
|
+
class HelloWorldHandler
|
|
6
|
+
include Java::ClojureLang::IFn
|
|
7
|
+
|
|
8
|
+
def invoke(request)
|
|
9
|
+
headers = ["Content-Type", "text/html"].to_java(:string)
|
|
10
|
+
headers = Java::clojure::lang::PersistentHashMap.create(headers)
|
|
11
|
+
|
|
12
|
+
resp = [
|
|
13
|
+
Java::ClojureLang::Keyword.intern("status") , 200,
|
|
14
|
+
Java::ClojureLang::Keyword.intern("headers") , headers,
|
|
15
|
+
Java::ClojureLang::Keyword.intern("body") , "hello HTTP! #{rand}"
|
|
16
|
+
].to_java
|
|
17
|
+
|
|
18
|
+
return Java::clojure::lang::PersistentHashMap.create(resp)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
req_handler = HelloWorldHandler.new()
|
|
23
|
+
ring_handler = Java::OrgHttpkitServer::RingHandler.new(100, req_handler, "prefix-", 1000)
|
|
24
|
+
server = Java::OrgHttpkitServer::HttpServer.new("0.0.0.0", 8089, ring_handler, 80000, 4000)
|
|
25
|
+
|
|
26
|
+
server.start()
|
|
27
|
+
|
|
28
|
+
Signal.trap("TERM") do
|
|
29
|
+
ring_handler.close()
|
|
30
|
+
server.stop()
|
|
31
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
$LOAD_PATH << File.expand_path('../../../lib', __FILE__)
|
|
2
|
+
|
|
3
|
+
require 'http_kit'
|
|
4
|
+
require 'webmachine'
|
|
5
|
+
require 'webmachine/adapters/ring'
|
|
6
|
+
|
|
7
|
+
class TestResource < Webmachine::Resource
|
|
8
|
+
def allowed_methods
|
|
9
|
+
%W{ GET HEAD OPTIONS POST PUT }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def content_types_provided
|
|
13
|
+
[['text/html', :render]]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def render
|
|
17
|
+
"Hello!"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def process_post
|
|
21
|
+
true
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
Service = Webmachine::Application.new do |app|
|
|
26
|
+
app.routes do
|
|
27
|
+
add ['*' ], TestResource
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
app.configure do |config|
|
|
31
|
+
config.ip = "0.0.0.0"
|
|
32
|
+
config.port = 9292
|
|
33
|
+
config.adapter = :Ring
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
Service.adapter.run
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'http_kit/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "jruby-http-kit"
|
|
8
|
+
spec.version = HttpKit::VERSION
|
|
9
|
+
spec.authors = ["Dmitriy Rozhkov"]
|
|
10
|
+
spec.email = ["rojkov.dmitry@gmail.com"]
|
|
11
|
+
spec.description = %q{}
|
|
12
|
+
spec.summary = %q{JRuby wrapper for Clojure HTTP Kit library.}
|
|
13
|
+
spec.homepage = "https://github.com/nLight/jruby-http-kit"
|
|
14
|
+
spec.license = ""
|
|
15
|
+
|
|
16
|
+
spec.files = `git ls-files`.split($/)
|
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
|
+
spec.require_paths = ["lib"]
|
|
20
|
+
|
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
|
22
|
+
spec.add_development_dependency "rake"
|
|
23
|
+
spec.add_development_dependency "rspec"
|
|
24
|
+
spec.add_development_dependency "webmachine"
|
|
25
|
+
end
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
require 'stringio'
|
|
2
|
+
require 'rack/rewindable_input'
|
|
3
|
+
|
|
4
|
+
module HttpKit
|
|
5
|
+
|
|
6
|
+
java_import java.nio.ByteBuffer
|
|
7
|
+
|
|
8
|
+
java_import org.httpkit.HttpUtils
|
|
9
|
+
java_import org.httpkit.HeaderMap
|
|
10
|
+
java_import org.httpkit.HttpVersion
|
|
11
|
+
java_import org.httpkit.DynamicBytes
|
|
12
|
+
java_import org.httpkit.server.RackHttpHandler
|
|
13
|
+
java_import org.httpkit.server.RingHandler
|
|
14
|
+
java_import org.httpkit.server.HttpRequest
|
|
15
|
+
java_import org.httpkit.server.RespCallback
|
|
16
|
+
java_import org.httpkit.server.AsyncChannel
|
|
17
|
+
|
|
18
|
+
class HttpHandler < RackHttpHandler
|
|
19
|
+
field_reader :req
|
|
20
|
+
field_reader :cb
|
|
21
|
+
field_reader :handler
|
|
22
|
+
|
|
23
|
+
def http_request_to_rack(req)
|
|
24
|
+
env = {}
|
|
25
|
+
|
|
26
|
+
body = req.getBody() || Rack::RewindableInput.new(StringIO.new(""))
|
|
27
|
+
|
|
28
|
+
env["SERVER_SOFTWARE"] = "HTTP Kit"
|
|
29
|
+
env["SERVER_NAME"] = req.serverName
|
|
30
|
+
env["rack.input"] = body
|
|
31
|
+
env["rack.version"] = [1, 0]
|
|
32
|
+
env["rack.errors"] = $stderr
|
|
33
|
+
env["rack.multithread"] = true
|
|
34
|
+
env["rack.multiprocess"] = false
|
|
35
|
+
env["rack.run_once"] = false
|
|
36
|
+
env["REQUEST_METHOD"] = req.method.KEY.to_s.gsub(':', '').upcase
|
|
37
|
+
env["REQUEST_PATH"] = req.uri
|
|
38
|
+
env["PATH_INFO"] = req.uri
|
|
39
|
+
env["REQUEST_URI"] = "http://%s:%s%s" % [req.serverName, req.serverPort.to_s, req.uri]
|
|
40
|
+
env["HTTP_VERSION"] = "HTTP/1.1"
|
|
41
|
+
env["HTTP_HOST"] = "%s:%s" % [req.serverName, req.serverPort.to_s]
|
|
42
|
+
env["HTTP_ACCEPT"] = "*/*"
|
|
43
|
+
env["SERVER_PORT"] = req.serverPort.to_s
|
|
44
|
+
env["QUERY_STRING"] = req.queryString || ""
|
|
45
|
+
env["SERVER_PROTOCOL"] = "HTTP/1.1"
|
|
46
|
+
env["rack.url_scheme"] = "http" # only http is supported
|
|
47
|
+
env["REMOTE_ADDR"] = req.getRemoteAddr()
|
|
48
|
+
|
|
49
|
+
env["CONTENT_TYPE"] = req.contentType || ""
|
|
50
|
+
env["CONTENT_LENGTH"] = req.contentLength.to_s
|
|
51
|
+
|
|
52
|
+
# // m.put(URI, req.uri);
|
|
53
|
+
# // m.put(ASYC_CHANNEL, req.channel);
|
|
54
|
+
# // m.put(WEBSOCKET, req.isWebSocket);
|
|
55
|
+
|
|
56
|
+
# // // key is already lower cased, required by ring spec
|
|
57
|
+
# // m.put(HEADERS, PersistentArrayMap.create(req.headers));
|
|
58
|
+
# // m.put(CONTENT_TYPE, req.contentType);
|
|
59
|
+
# // m.put(CONTENT_LENGTH, req.contentLength);
|
|
60
|
+
# // m.put(CHARACTER_ENCODING, req.charset);
|
|
61
|
+
# // m.put(BODY, req.getBody());
|
|
62
|
+
|
|
63
|
+
env
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def run
|
|
67
|
+
begin
|
|
68
|
+
resp = handler.call(http_request_to_rack(req))
|
|
69
|
+
if ! resp
|
|
70
|
+
cb.run(HttpUtils.HttpEncode(404, HeaderMap.new(), nil));
|
|
71
|
+
else
|
|
72
|
+
status, headers, body = resp
|
|
73
|
+
|
|
74
|
+
if ! body.is_a?(AsyncChannel)
|
|
75
|
+
b = DynamicBytes.new(512)
|
|
76
|
+
|
|
77
|
+
body.each do |chunk|
|
|
78
|
+
b.append(chunk.to_s)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
body = ByteBuffer.wrap(b.get(), 0, b.length())
|
|
82
|
+
|
|
83
|
+
headers = HeaderMap.camelCase(headers)
|
|
84
|
+
|
|
85
|
+
# In HTTP 1.1, all connections are considered persistent unless declared otherwise.
|
|
86
|
+
if req.version == HttpVersion::HTTP_1_0 && req.isKeepAlive
|
|
87
|
+
headers.put("Connection", "Keep-Alive")
|
|
88
|
+
end
|
|
89
|
+
cb.run(HttpUtils.HttpEncode(status.to_i, headers, body))
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
rescue => e
|
|
93
|
+
cb.run(HttpUtils.HttpEncode(500, HeaderMap.new(), e.message))
|
|
94
|
+
HttpUtils.printError(req.method + " " + req.uri, e);
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
class RackHandler < RingHandler
|
|
100
|
+
|
|
101
|
+
field_reader :execs
|
|
102
|
+
field_reader :handler
|
|
103
|
+
|
|
104
|
+
def handle(*args)
|
|
105
|
+
if args[0].is_a?(HttpRequest) && args[1].is_a?(RespCallback)
|
|
106
|
+
handle_http(args[0], args[1])
|
|
107
|
+
else
|
|
108
|
+
handle_async(args[0], args[1])
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# void handle(HttpRequest request, RespCallback callback)
|
|
113
|
+
def handle_http(request, callback)
|
|
114
|
+
begin
|
|
115
|
+
execs.submit( HttpKit::HttpHandler.new(request, callback, handler) )
|
|
116
|
+
rescue java.util.concurrent.RejectedExecutionException => e
|
|
117
|
+
HttpUtils.printError("increase :queue-size if this happens often", e);
|
|
118
|
+
callback.run(HttpUtils.HttpEncode(503, HeaderMap.new(), "Server is overloaded, please try later"));
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# void handle(AsyncChannel channel, Frame frame)
|
|
123
|
+
def handle_async(channel, frame)
|
|
124
|
+
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# java_signature %Q{ @override public void clientClose(AsyncChannel channel, int status) }
|
|
128
|
+
def client_close(channel, status)
|
|
129
|
+
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
# java_signature %Q{ @override void close() }
|
|
134
|
+
def close
|
|
135
|
+
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
require 'http_kit/rack_handler'
|
|
2
|
+
|
|
3
|
+
module HttpKit
|
|
4
|
+
class Server
|
|
5
|
+
|
|
6
|
+
@lock ||= Mutex.new
|
|
7
|
+
|
|
8
|
+
def Server.run(app, options = {})
|
|
9
|
+
@lock.synchronize do
|
|
10
|
+
return if @server
|
|
11
|
+
@server = new
|
|
12
|
+
@server.run(app, options)
|
|
13
|
+
|
|
14
|
+
@server
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def Server.stop
|
|
19
|
+
@lock.synchronize do
|
|
20
|
+
return unless @server
|
|
21
|
+
|
|
22
|
+
@server.stop
|
|
23
|
+
@handler = nil
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def run(app, options={})
|
|
28
|
+
options = {
|
|
29
|
+
:host => "0.0.0.0",
|
|
30
|
+
:port => 9292,
|
|
31
|
+
:threads => 50,
|
|
32
|
+
:queue => 1000,
|
|
33
|
+
}.merge(options)
|
|
34
|
+
|
|
35
|
+
@handler = HttpKit::RackHandler.new(options[:threads], app, "prefix-", options[:queue])
|
|
36
|
+
@http_kit = Java::OrgHttpkitServer::HttpServer.new(options[:host], options[:port], @handler, 80000, 4000)
|
|
37
|
+
|
|
38
|
+
@http_kit.start
|
|
39
|
+
|
|
40
|
+
$stdout.printf("HTTP Kit is listening on %s:%s\n", options[:host], options[:port])
|
|
41
|
+
|
|
42
|
+
trap("SIGINT") {
|
|
43
|
+
@http_kit.stop
|
|
44
|
+
exit
|
|
45
|
+
}
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def start
|
|
49
|
+
@http_kit.start
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def stop
|
|
53
|
+
return unless @http_kit
|
|
54
|
+
$stdout.print "Stopping Http kit..." unless @options[:quiet]
|
|
55
|
+
@http_kit.stop
|
|
56
|
+
$stdout.puts "done." unless @options[:quiet]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
alias_method :shutdown, :stop
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
end
|
data/lib/http_kit.rb
ADDED
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
module Webmachine
|
|
2
|
+
module Adapters
|
|
3
|
+
class Ring < Webmachine::Adapter
|
|
4
|
+
|
|
5
|
+
DEFAULT_OPTIONS = {
|
|
6
|
+
:port => 9292,
|
|
7
|
+
:host => "0.0.0.0",
|
|
8
|
+
:threads => 50,
|
|
9
|
+
:queue_size => 1000,
|
|
10
|
+
:worker_prefix => "wm-",
|
|
11
|
+
:max_body_size => 8388608,
|
|
12
|
+
:max_http_line => 4096
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
# Start the Rack adapter
|
|
16
|
+
def run
|
|
17
|
+
options = DEFAULT_OPTIONS.merge({
|
|
18
|
+
:port => configuration.port,
|
|
19
|
+
:host => configuration.ip
|
|
20
|
+
}).merge(configuration.adapter_options)
|
|
21
|
+
|
|
22
|
+
req_handler = Handler.new(dispatcher)
|
|
23
|
+
|
|
24
|
+
@ring_handler = Java::OrgHttpkitServer::RingHandler.new(options[:threads],
|
|
25
|
+
req_handler,
|
|
26
|
+
options[:worker_prefix],
|
|
27
|
+
options[:queue_size])
|
|
28
|
+
|
|
29
|
+
@server = Java::OrgHttpkitServer::HttpServer.new(options[:host],
|
|
30
|
+
options[:port].to_i,
|
|
31
|
+
@ring_handler,
|
|
32
|
+
options[:max_body_size],
|
|
33
|
+
options[:max_http_line])
|
|
34
|
+
|
|
35
|
+
@server.start()
|
|
36
|
+
|
|
37
|
+
$stdout.printf "Webmachine Http kit is listening on %s:%s\n\n",
|
|
38
|
+
options[:host], options[:port]
|
|
39
|
+
|
|
40
|
+
Signal.trap("INT") { shutdown }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def shutdown
|
|
44
|
+
@ring_handler.close()
|
|
45
|
+
@server.stop()
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class Handler
|
|
50
|
+
include Java::ClojureLang::IFn
|
|
51
|
+
|
|
52
|
+
attr_reader :dispatcher
|
|
53
|
+
|
|
54
|
+
def initialize(dispatcher)
|
|
55
|
+
@dispatcher = dispatcher
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def invoke(request)
|
|
59
|
+
ring_request = Ring::RingRequest.new(request)
|
|
60
|
+
|
|
61
|
+
request = Webmachine::Request.new(ring_request.method,
|
|
62
|
+
ring_request.url,
|
|
63
|
+
ring_request.headers,
|
|
64
|
+
ring_request.body)
|
|
65
|
+
|
|
66
|
+
response = Webmachine::Response.new
|
|
67
|
+
|
|
68
|
+
dispatcher.dispatch(request, response)
|
|
69
|
+
|
|
70
|
+
headers = Java::JavaUtil::HashMap.new(response.headers)
|
|
71
|
+
|
|
72
|
+
Ring::RingResponse.create(response.code, headers, response.body)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
class RingRequest
|
|
77
|
+
def initialize(request)
|
|
78
|
+
@request = request
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def headers
|
|
82
|
+
Webmachine::Headers.from_cgi(@request.get(Java::ClojureLang::Keyword.intern("headers")))
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def body
|
|
86
|
+
_body = @request.get( Java::ClojureLang::Keyword.intern("body") )
|
|
87
|
+
_body = _body.to_io if _body
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def url
|
|
91
|
+
uri = @request.get(Java::ClojureLang::Keyword.intern("uri"))
|
|
92
|
+
query_string = @request.get(Java::ClojureLang::Keyword.intern("query-string"))
|
|
93
|
+
|
|
94
|
+
URI.parse("#{uri}?#{query_string}")
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def method
|
|
98
|
+
@request.get(Java::ClojureLang::Keyword.intern("request-method")).to_s.delete(':').upcase
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Map<Object, Object> m = new TreeMap<Object, Object>();
|
|
102
|
+
# m.put(SERVER_PORT, req.serverPort);
|
|
103
|
+
# m.put(SERVER_NAME, req.serverName);
|
|
104
|
+
# m.put(REMOTE_ADDR, req.getRemoteAddr());
|
|
105
|
+
# m.put(URI, req.uri);
|
|
106
|
+
# m.put(SCHEME, HTTP); // only http is supported
|
|
107
|
+
# m.put(ASYC_CHANNEL, req.channel);
|
|
108
|
+
# m.put(WEBSOCKET, req.isWebSocket);
|
|
109
|
+
# m.put(REQUEST_METHOD, req.method.KEY);
|
|
110
|
+
|
|
111
|
+
# // key is already lower cased, required by ring spec
|
|
112
|
+
# m.put(HEADERS, PersistentArrayMap.create(req.headers));
|
|
113
|
+
# m.put(CONTENT_TYPE, req.contentType);
|
|
114
|
+
# m.put(CONTENT_LENGTH, req.contentLength);
|
|
115
|
+
# m.put(CHARACTER_ENCODING, req.charset);
|
|
116
|
+
# m.put(BODY, req.getBody());
|
|
117
|
+
# return PersistentArrayMap.create(m);
|
|
118
|
+
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
class RingResponse
|
|
122
|
+
def self.create(code, headers, body)
|
|
123
|
+
ring_response = [
|
|
124
|
+
Java::ClojureLang::Keyword.intern("status") , code,
|
|
125
|
+
Java::ClojureLang::Keyword.intern("headers") , headers,
|
|
126
|
+
Java::ClojureLang::Keyword.intern("body") , body
|
|
127
|
+
]
|
|
128
|
+
|
|
129
|
+
return Java::clojure::lang::PersistentHashMap.create(ring_response.to_java)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|