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.
Files changed (140) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +72 -0
  7. data/Rakefile +1 -0
  8. data/example/config.ru +9 -0
  9. data/example/hello_world.rb +17 -0
  10. data/example/rack.rb +11 -0
  11. data/example/ring.rb +31 -0
  12. data/example/sinatra/app.rb +9 -0
  13. data/example/sinatra/config.ru +8 -0
  14. data/example/webmachine/Gemfile +4 -0
  15. data/example/webmachine/Gemfile.lock +16 -0
  16. data/example/webmachine/app.rb +37 -0
  17. data/jruby-http-kit.gemspec +25 -0
  18. data/lib/http_kit/rack_handler.rb +139 -0
  19. data/lib/http_kit/server.rb +62 -0
  20. data/lib/http_kit/version.rb +3 -0
  21. data/lib/http_kit.rb +6 -0
  22. data/lib/java/clojure-1.5.1.jar +0 -0
  23. data/lib/java/http-kit.jar +0 -0
  24. data/lib/rack/handler/http_kit.rb +3 -0
  25. data/lib/rack/http_kit.rb +3 -0
  26. data/lib/webmachine/adapters/ring.rb +135 -0
  27. data/spec/spec_helper.rb +24 -0
  28. data/spec/support/test_resource.rb +75 -0
  29. data/spec/webmachine/ring_adapter_spec.rb +127 -0
  30. data/src/.classpath +7 -0
  31. data/src/.project +17 -0
  32. data/src/org/httpkit/BytesInputStream.class +0 -0
  33. data/src/org/httpkit/BytesInputStream.java +83 -0
  34. data/src/org/httpkit/DateFormatter.class +0 -0
  35. data/src/org/httpkit/DynamicBytes.class +0 -0
  36. data/src/org/httpkit/DynamicBytes.java +76 -0
  37. data/src/org/httpkit/HTTPException.class +0 -0
  38. data/src/org/httpkit/HTTPException.java +10 -0
  39. data/src/org/httpkit/HeaderMap.class +0 -0
  40. data/src/org/httpkit/HeaderMap.java +98 -0
  41. data/src/org/httpkit/HttpMethod.class +0 -0
  42. data/src/org/httpkit/HttpMethod.java +28 -0
  43. data/src/org/httpkit/HttpStatus.class +0 -0
  44. data/src/org/httpkit/HttpStatus.java +416 -0
  45. data/src/org/httpkit/HttpUtils.class +0 -0
  46. data/src/org/httpkit/HttpUtils.java +484 -0
  47. data/src/org/httpkit/HttpVersion.class +0 -0
  48. data/src/org/httpkit/HttpVersion.java +5 -0
  49. data/src/org/httpkit/LineReader.class +0 -0
  50. data/src/org/httpkit/LineReader.java +52 -0
  51. data/src/org/httpkit/LineTooLargeException.class +0 -0
  52. data/src/org/httpkit/LineTooLargeException.java +13 -0
  53. data/src/org/httpkit/PrefixThreadFactory.class +0 -0
  54. data/src/org/httpkit/PrefixThreadFactory.java +20 -0
  55. data/src/org/httpkit/PriorityQueue.class +0 -0
  56. data/src/org/httpkit/PriorityQueue.java +235 -0
  57. data/src/org/httpkit/ProtocolException.class +0 -0
  58. data/src/org/httpkit/ProtocolException.java +10 -0
  59. data/src/org/httpkit/RequestTooLargeException.class +0 -0
  60. data/src/org/httpkit/RequestTooLargeException.java +10 -0
  61. data/src/org/httpkit/client/AbortException.class +0 -0
  62. data/src/org/httpkit/client/AbortException.java +13 -0
  63. data/src/org/httpkit/client/Decoder.class +0 -0
  64. data/src/org/httpkit/client/Decoder.java +182 -0
  65. data/src/org/httpkit/client/Handler.class +0 -0
  66. data/src/org/httpkit/client/HttpClient.class +0 -0
  67. data/src/org/httpkit/client/HttpClient.java +393 -0
  68. data/src/org/httpkit/client/HttpsRequest.class +0 -0
  69. data/src/org/httpkit/client/HttpsRequest.java +141 -0
  70. data/src/org/httpkit/client/IFilter$1.class +0 -0
  71. data/src/org/httpkit/client/IFilter$MaxBodyFilter.class +0 -0
  72. data/src/org/httpkit/client/IFilter.class +0 -0
  73. data/src/org/httpkit/client/IFilter.java +53 -0
  74. data/src/org/httpkit/client/IRespListener.class +0 -0
  75. data/src/org/httpkit/client/IRespListener.java +30 -0
  76. data/src/org/httpkit/client/IResponseHandler.class +0 -0
  77. data/src/org/httpkit/client/IResponseHandler.java +18 -0
  78. data/src/org/httpkit/client/PersistentConn.class +0 -0
  79. data/src/org/httpkit/client/PersistentConn.java +33 -0
  80. data/src/org/httpkit/client/Request.class +0 -0
  81. data/src/org/httpkit/client/Request.java +74 -0
  82. data/src/org/httpkit/client/RequestConfig.class +0 -0
  83. data/src/org/httpkit/client/RequestConfig.java +28 -0
  84. data/src/org/httpkit/client/RespListener.class +0 -0
  85. data/src/org/httpkit/client/RespListener.java +160 -0
  86. data/src/org/httpkit/client/SslContextFactory.class +0 -0
  87. data/src/org/httpkit/client/SslContextFactory.java +79 -0
  88. data/src/org/httpkit/client/State.class +0 -0
  89. data/src/org/httpkit/client/TimeoutException.class +0 -0
  90. data/src/org/httpkit/client/TimeoutException.java +12 -0
  91. data/src/org/httpkit/client/TrustManagerFactory$1.class +0 -0
  92. data/src/org/httpkit/client/TrustManagerFactory.class +0 -0
  93. data/src/org/httpkit/server/AsyncChannel.class +0 -0
  94. data/src/org/httpkit/server/AsyncChannel.java +286 -0
  95. data/src/org/httpkit/server/ClojureRing.class +0 -0
  96. data/src/org/httpkit/server/Frame$BinaryFrame.class +0 -0
  97. data/src/org/httpkit/server/Frame$CloseFrame.class +0 -0
  98. data/src/org/httpkit/server/Frame$PingFrame.class +0 -0
  99. data/src/org/httpkit/server/Frame$TextFrame.class +0 -0
  100. data/src/org/httpkit/server/Frame.class +0 -0
  101. data/src/org/httpkit/server/Frame.java +73 -0
  102. data/src/org/httpkit/server/HttpAtta.class +0 -0
  103. data/src/org/httpkit/server/HttpAtta.java +10 -0
  104. data/src/org/httpkit/server/HttpDecoder$State.class +0 -0
  105. data/src/org/httpkit/server/HttpDecoder.class +0 -0
  106. data/src/org/httpkit/server/HttpDecoder.java +202 -0
  107. data/src/org/httpkit/server/HttpHandler.class +0 -0
  108. data/src/org/httpkit/server/HttpRequest.class +0 -0
  109. data/src/org/httpkit/server/HttpRequest.java +109 -0
  110. data/src/org/httpkit/server/HttpServer.class +0 -0
  111. data/src/org/httpkit/server/HttpServer.java +281 -0
  112. data/src/org/httpkit/server/IHandler.class +0 -0
  113. data/src/org/httpkit/server/IHandler.java +12 -0
  114. data/src/org/httpkit/server/LinkingRunnable.class +0 -0
  115. data/src/org/httpkit/server/Rack.class +0 -0
  116. data/src/org/httpkit/server/RackApplication.class +0 -0
  117. data/src/org/httpkit/server/RackApplication.java +10 -0
  118. data/src/org/httpkit/server/RackHandler$1.class +0 -0
  119. data/src/org/httpkit/server/RackHandler.class +0 -0
  120. data/src/org/httpkit/server/RackHandler.java +259 -0
  121. data/src/org/httpkit/server/RackHttpHandler.class +0 -0
  122. data/src/org/httpkit/server/RackHttpHandler.java +20 -0
  123. data/src/org/httpkit/server/RespCallback.class +0 -0
  124. data/src/org/httpkit/server/RespCallback.java +19 -0
  125. data/src/org/httpkit/server/RingHandler$1.class +0 -0
  126. data/src/org/httpkit/server/RingHandler.class +0 -0
  127. data/src/org/httpkit/server/RingHandler.java +222 -0
  128. data/src/org/httpkit/server/ServerAtta.class +0 -0
  129. data/src/org/httpkit/server/ServerAtta.java +22 -0
  130. data/src/org/httpkit/server/WSDecoder$State.class +0 -0
  131. data/src/org/httpkit/server/WSDecoder.class +0 -0
  132. data/src/org/httpkit/server/WSDecoder.java +181 -0
  133. data/src/org/httpkit/server/WSHandler.class +0 -0
  134. data/src/org/httpkit/server/WsAtta.class +0 -0
  135. data/src/org/httpkit/server/WsAtta.java +11 -0
  136. data/src/org/httpkit/timer/CancelableFutureTask.class +0 -0
  137. data/src/org/httpkit/timer/CancelableFutureTask.java +52 -0
  138. data/src/org/httpkit/timer/TimerService.class +0 -0
  139. data/src/org/httpkit/timer/TimerService.java +89 -0
  140. metadata +241 -0
@@ -0,0 +1,24 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+
8
+ require 'rubygems'
9
+ require 'webmachine'
10
+ require 'http_kit'
11
+ require 'rspec'
12
+ require 'logger'
13
+
14
+ RSpec.configure do |config|
15
+ config.treat_symbols_as_metadata_keys_with_true_values = true
16
+ config.run_all_when_everything_filtered = true
17
+ config.filter_run :focus
18
+
19
+ # Run specs in random order to surface order dependencies. If you find an
20
+ # order dependency and want to debug it, you can fix the order by providing
21
+ # the seed, which is printed after each run.
22
+ # --seed 1234
23
+ config.order = 'random'
24
+ end
@@ -0,0 +1,75 @@
1
+ require "webmachine"
2
+
3
+ module Test
4
+ class Resource < ::Webmachine::Resource
5
+ def allowed_methods
6
+ ["GET", "PUT", "POST"]
7
+ end
8
+
9
+ def content_types_accepted
10
+ [
11
+ ["test/request.stringbody", :from_string],
12
+ ["test/request.enumbody", :from_enum]
13
+ ]
14
+ end
15
+
16
+ def content_types_provided
17
+ [
18
+ ["test/response.stringbody", :to_string],
19
+ ["test/response.enumbody", :to_enum],
20
+ ["test/response.procbody", :to_proc],
21
+ ["test/response.fiberbody", :to_fiber],
22
+ ["test/response.iobody", :to_io],
23
+ ["test/response.cookies", :to_cookies]
24
+ ]
25
+ end
26
+
27
+ def from_string
28
+ response.body = "String: #{request.body.to_s}"
29
+ end
30
+
31
+ def from_enum
32
+ response.body = "Enum: "
33
+ request.body.each do |part|
34
+ response.body += part
35
+ end
36
+ end
37
+
38
+ # Response intentionally left blank to test 204 support
39
+ def process_post
40
+ true
41
+ end
42
+
43
+ def to_string
44
+ "String response body"
45
+ end
46
+
47
+ def to_enum
48
+ ["Enumerable ", "response " "body"]
49
+ end
50
+
51
+ def to_proc
52
+ Proc.new { "Proc response body" }
53
+ end
54
+
55
+ def to_fiber
56
+ Fiber.new do
57
+ Fiber.yield "Fiber "
58
+ Fiber.yield "response "
59
+ "body"
60
+ end
61
+ end
62
+
63
+ def to_io
64
+ StringIO.new("IO response body")
65
+ end
66
+
67
+ def to_cookies
68
+ response.set_cookie("cookie", "monster")
69
+ response.set_cookie("rodeo", "clown")
70
+ # FIXME: Mongrel/WEBrick fail if this method returns nil
71
+ # Might be a net/http issue. Is this a bug?
72
+ request.cookies["echo"] || ""
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,127 @@
1
+ require "spec_helper"
2
+ require "webmachine/adapters/ring"
3
+ require "support/test_resource"
4
+ require "net/http"
5
+
6
+ describe "Webmachine::Adapters::Ring" do
7
+ attr_accessor :client
8
+
9
+ before(:all) do
10
+ configuration = Webmachine::Configuration.default
11
+ dispatcher = Webmachine::Dispatcher.new
12
+ dispatcher.add_route ["test"], Test::Resource
13
+
14
+ @adapter = Webmachine::Adapters::Ring.new(configuration, dispatcher)
15
+ @client = Net::HTTP.new(configuration.ip, configuration.port)
16
+
17
+ Thread.abort_on_exception = true
18
+ @server_thread = Thread.new { @adapter.run }
19
+
20
+ # Wait until the server is responsive
21
+ timeout(5) do
22
+ begin
23
+ client.start
24
+ rescue Errno::ECONNREFUSED
25
+ sleep(0.1)
26
+ retry
27
+ end
28
+ end
29
+ end
30
+
31
+ after(:all) do
32
+ @adapter.shutdown
33
+ @client.finish
34
+ @server_thread.join
35
+ end
36
+
37
+ it "provides a string-like request body" do
38
+ request = Net::HTTP::Put.new("/test")
39
+ request.body = "Hello, World!"
40
+ request["Content-Type"] = "test/request.stringbody"
41
+ response = client.request(request)
42
+ response["Content-Length"].should eq("21")
43
+ response.body.should eq("String: Hello, World!")
44
+ end
45
+
46
+ it "provides an enumerable request body" do
47
+ request = Net::HTTP::Put.new("/test")
48
+ request.body = "Hello, World!"
49
+ request["Content-Type"] = "test/request.enumbody"
50
+ response = client.request(request)
51
+ response["Content-Length"].should eq("19")
52
+ response.body.should eq("Enum: Hello, World!")
53
+ end
54
+
55
+ it "handles missing pages" do
56
+ request = Net::HTTP::Get.new("/missing")
57
+ response = client.request(request)
58
+ response.code.should eq("404")
59
+ response["Content-Type"].should eq("text/html")
60
+ end
61
+
62
+ it "handles empty response bodies" do
63
+ request = Net::HTTP::Post.new("/test")
64
+ request.body = ""
65
+ response = client.request(request)
66
+ response.code.should eq("204")
67
+ # FIXME: Mongrel/WEBrick fail this test. Is there a bug?
68
+ #response["Content-Type"].should be_nil
69
+ response["Content-Length"].should be_nil
70
+ response.body.should be_nil
71
+ end
72
+
73
+ it "handles string response bodies" do
74
+ request = Net::HTTP::Get.new("/test")
75
+ request["Accept"] = "test/response.stringbody"
76
+ response = client.request(request)
77
+ response["Content-Length"].should eq("20")
78
+ response.body.should eq("String response body")
79
+ end
80
+
81
+ it "handles enumerable response bodies" do
82
+ request = Net::HTTP::Get.new("/test")
83
+ request["Accept"] = "test/response.enumbody"
84
+ response = client.request(request)
85
+ response["Transfer-Encoding"].should eq("chunked")
86
+ response.body.should eq("Enumerable response body")
87
+ end
88
+
89
+ it "handles proc response bodies" do
90
+ request = Net::HTTP::Get.new("/test")
91
+ request["Accept"] = "test/response.procbody"
92
+ response = client.request(request)
93
+ response["Transfer-Encoding"].should eq("chunked")
94
+ response.body.should eq("Proc response body")
95
+ end
96
+
97
+ it "handles fiber response bodies" do
98
+ request = Net::HTTP::Get.new("/test")
99
+ request["Accept"] = "test/response.fiberbody"
100
+ response = client.request(request)
101
+ response["Transfer-Encoding"].should eq("chunked")
102
+ response.body.should eq("Fiber response body")
103
+ end
104
+
105
+ it "handles io response bodies" do
106
+ request = Net::HTTP::Get.new("/test")
107
+ request["Accept"] = "test/response.iobody"
108
+ response = client.request(request)
109
+ response["Content-Length"].should eq("16")
110
+ response.body.should eq("IO response body")
111
+ end
112
+
113
+ it "handles request cookies" do
114
+ request = Net::HTTP::Get.new("/test")
115
+ request["Accept"] = "test/response.cookies"
116
+ request["Cookie"] = "echo=echocookie"
117
+ response = client.request(request)
118
+ response.body.should eq("echocookie")
119
+ end
120
+
121
+ it "handles response cookies" do
122
+ request = Net::HTTP::Get.new("/test")
123
+ request["Accept"] = "test/response.cookies"
124
+ response = client.request(request)
125
+ response["Set-Cookie"].should eq("cookie=monster, rodeo=clown")
126
+ end
127
+ end
data/src/.classpath ADDED
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <classpath>
3
+ <classpathentry kind="src" path=""/>
4
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
5
+ <classpathentry kind="lib" path="/Users/drozhkov/Downloads/clojure-1.5.1/clojure-1.5.1.jar"/>
6
+ <classpathentry kind="output" path=""/>
7
+ </classpath>
data/src/.project ADDED
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <projectDescription>
3
+ <name>httpkit</name>
4
+ <comment></comment>
5
+ <projects>
6
+ </projects>
7
+ <buildSpec>
8
+ <buildCommand>
9
+ <name>org.eclipse.jdt.core.javabuilder</name>
10
+ <arguments>
11
+ </arguments>
12
+ </buildCommand>
13
+ </buildSpec>
14
+ <natures>
15
+ <nature>org.eclipse.jdt.core.javanature</nature>
16
+ </natures>
17
+ </projectDescription>
@@ -0,0 +1,83 @@
1
+ package org.httpkit;
2
+
3
+ import java.io.IOException;
4
+ import java.io.InputStream;
5
+ import java.util.Arrays;
6
+
7
+ /**
8
+ * No synchronization, better toString
9
+ */
10
+ public class BytesInputStream extends InputStream {
11
+ private final byte[] buf;
12
+ private final int count;
13
+ private int mark = 0;
14
+
15
+ private int pos;
16
+
17
+ public BytesInputStream(byte[] data, int length) {
18
+ this.buf = data;
19
+ this.count = length;
20
+ this.pos = 0;
21
+ }
22
+
23
+ /**
24
+ * get the underlying bytes, copied
25
+ *
26
+ * @return
27
+ */
28
+ public byte[] bytes() {
29
+ return Arrays.copyOf(buf, count);
30
+ }
31
+
32
+ public int read() throws IOException {
33
+ return (pos < count) ? (buf[pos++] & 0xff) : -1;
34
+ }
35
+
36
+ public int read(byte[] b) throws IOException {
37
+ return read(b, 0, b.length);
38
+ }
39
+
40
+ public int read(byte[] b, int off, int len) throws IOException {
41
+ if (pos >= count) {
42
+ return -1;
43
+ }
44
+
45
+ int avail = count - pos;
46
+ if (len > avail) {
47
+ len = avail;
48
+ }
49
+
50
+ System.arraycopy(buf, pos, b, off, len);
51
+ pos += len;
52
+ return len;
53
+ }
54
+
55
+ public String toString() {
56
+ return "BytesInputStream[len=" + count + "]";
57
+ }
58
+
59
+ public long skip(long n) throws IOException {
60
+ long k = count - pos;
61
+ if (n < k) {
62
+ k = n < 0 ? 0 : n;
63
+ }
64
+ pos += k;
65
+ return k;
66
+ }
67
+
68
+ public int available() {
69
+ return count - pos;
70
+ }
71
+
72
+ public boolean markSupported() {
73
+ return true;
74
+ }
75
+
76
+ public void mark(int readAheadLimit) {
77
+ mark = pos;
78
+ }
79
+
80
+ public void reset() {
81
+ pos = mark;
82
+ }
83
+ }
Binary file
Binary file
@@ -0,0 +1,76 @@
1
+ package org.httpkit;
2
+
3
+ import java.nio.charset.Charset;
4
+ import java.util.Arrays;
5
+
6
+ public class DynamicBytes {
7
+ private byte[] data;
8
+ private int idx = 0;
9
+
10
+ public DynamicBytes(int size) {
11
+ data = new byte[size];
12
+ }
13
+
14
+ private void expandIfNeeded(int more) {
15
+ if (idx + more > data.length) {
16
+ int after = (int) ((idx + more) * 1.33);
17
+ // String msg = "expand memory, from " + data.length + " to " +
18
+ // after + "; need " + more;
19
+ // System.out.println(msg);
20
+ data = Arrays.copyOf(data, after);
21
+ }
22
+ }
23
+
24
+ public byte[] get() {
25
+ return data;
26
+ }
27
+
28
+ public int length() {
29
+ return idx;
30
+ }
31
+
32
+ public DynamicBytes append(byte b) {
33
+ expandIfNeeded(1);
34
+ data[idx++] = b;
35
+ return this;
36
+ }
37
+
38
+ public void append(byte b1, byte b2) {
39
+ expandIfNeeded(2);
40
+ data[idx++] = b1;
41
+ data[idx++] = b2;
42
+ }
43
+
44
+ @Override
45
+ public String toString() {
46
+ return "DynamicBytes[len=" + idx + ", cap=" + data.length + ']';
47
+ }
48
+
49
+ public DynamicBytes append(byte[] d, int length) {
50
+ expandIfNeeded(length);
51
+ System.arraycopy(d, 0, data, idx, length);
52
+ idx += length;
53
+ return this;
54
+ }
55
+
56
+ public DynamicBytes append(String str) {
57
+ // ISO-8859-1. much faster than String.getBytes("ISO-8859-1")
58
+ // less copy. 620ms vs 190ms
59
+ int length = str.length();
60
+ expandIfNeeded(length);
61
+ for (int i = 0; i < length; i++) {
62
+ char c = str.charAt(i);
63
+ if (c < 128) {
64
+ data[idx++] = (byte) c;
65
+ } else {
66
+ data[idx++] = (byte) '?'; // JDK uses ? to represent non ASCII
67
+ }
68
+ }
69
+ return this;
70
+ }
71
+
72
+ public DynamicBytes append(String str, Charset c) {
73
+ byte[] bs = str.getBytes(c);
74
+ return append(bs, bs.length);
75
+ }
76
+ }
Binary file
@@ -0,0 +1,10 @@
1
+ package org.httpkit;
2
+
3
+ public class HTTPException extends Exception {
4
+
5
+ private static final long serialVersionUID = 1L;
6
+
7
+ public HTTPException(String msg) {
8
+ super(msg);
9
+ }
10
+ }
Binary file
@@ -0,0 +1,98 @@
1
+ package org.httpkit;
2
+
3
+ import clojure.lang.ISeq;
4
+ import clojure.lang.Seqable;
5
+
6
+ import java.util.Arrays;
7
+ import java.util.Map;
8
+
9
+ import static org.httpkit.HttpUtils.*;
10
+
11
+ /**
12
+ * Save a few bytes of memory => No Map.Entry, and a little faster
13
+ * Date: 4/23/13
14
+ *
15
+ * @author feng <shenedu@gmail.com>
16
+ * @since 2.0.2
17
+ */
18
+ public class HeaderMap {
19
+ public boolean isEmpty() {
20
+ return size == 0;
21
+ }
22
+
23
+ public final int INIT_SIZE = 8;
24
+
25
+ private int size = 0;
26
+ private Object arrays[] = new Object[INIT_SIZE * 2];
27
+
28
+ public void put(String key, Object obj) {
29
+ final int total = size << 1;
30
+ if (total == arrays.length) {
31
+ arrays = Arrays.copyOf(arrays, arrays.length * 2);
32
+ }
33
+ arrays[total] = key;
34
+ arrays[total + 1] = obj;
35
+ size += 1;
36
+ }
37
+
38
+ public Object get(String key) {
39
+ final int total = size << 1; // * 2
40
+ for (int i = 0; i < total; i += 2) {
41
+ if (key.equals(arrays[i])) {
42
+ return arrays[i + 1];
43
+ }
44
+ }
45
+ return null;
46
+ }
47
+
48
+ public boolean containsKey(String key) {
49
+ final int total = size << 1; // * 2
50
+ for (int i = 0; i < total; i += 2) {
51
+ if (key.equals(arrays[i])) {
52
+ return true;
53
+ }
54
+ }
55
+ return false;
56
+ }
57
+
58
+ public void clear() {
59
+ this.size = 0;
60
+ }
61
+
62
+ public static HeaderMap camelCase(Map<String, Object> map) {
63
+ HeaderMap tmp = new HeaderMap();
64
+ if (map != null) {
65
+ for (Map.Entry<String, Object> e : map.entrySet()) {
66
+ tmp.put(HttpUtils.camelCase(e.getKey()), e.getValue());
67
+ }
68
+ }
69
+ return tmp;
70
+ }
71
+
72
+ public void encodeHeaders(DynamicBytes bytes) {
73
+ final int total = size << 1;
74
+ for (int i = 0; i < total; i += 2) {
75
+ String k = (String) arrays[i];
76
+ Object v = arrays[i + 1];
77
+ if (v instanceof String) {
78
+ bytes.append(k);
79
+ bytes.append(COLON, SP);
80
+ // supposed to be ISO-8859-1, but utf-8 is compatible.
81
+ // filename in Content-Disposition can be utf8
82
+ bytes.append((String) v, HttpUtils.UTF_8);
83
+ bytes.append(CR, LF);
84
+ // ring spec says it could be a seq
85
+ } else if (v instanceof Seqable) {
86
+ ISeq seq = ((Seqable) v).seq();
87
+ while (seq != null) {
88
+ bytes.append(k);
89
+ bytes.append(COLON, SP);
90
+ bytes.append(seq.first().toString(), HttpUtils.UTF_8);
91
+ bytes.append(CR, LF);
92
+ seq = seq.next();
93
+ }
94
+ }
95
+ }
96
+ bytes.append(CR, LF);
97
+ }
98
+ }
Binary file
@@ -0,0 +1,28 @@
1
+ package org.httpkit;
2
+
3
+ import clojure.lang.Keyword;
4
+
5
+ import static clojure.lang.Keyword.intern;
6
+
7
+ public enum HttpMethod {
8
+
9
+ GET(intern("get")), HEAD(intern("head")), POST(intern("post")), PUT(intern("put")),
10
+ DELETE(intern("delete")), TRACE(intern("trace")), OPTIONS(intern("options")),
11
+ CONNECT(intern("connect")), PATCH(intern("patch"));
12
+
13
+ public final Keyword KEY;
14
+
15
+ private HttpMethod(Keyword key) {
16
+ this.KEY = key;
17
+ }
18
+
19
+ public static HttpMethod fromKeyword(Keyword k) {
20
+ HttpMethod[] values = HttpMethod.values();
21
+ for (HttpMethod m : values) {
22
+ if (m.KEY.equals(k)) {
23
+ return m;
24
+ }
25
+ }
26
+ throw new RuntimeException("unsupported method " + k);
27
+ }
28
+ }
Binary file