httpkit 0.6.0.pre.5 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +8 -8
  2. data/.gitignore +0 -2
  3. data/.travis.yml +1 -1
  4. data/Gemfile +2 -0
  5. data/README.md +32 -25
  6. data/Rakefile +5 -0
  7. data/config/flay.yml +1 -1
  8. data/doc/api/httpkit.html +50 -0
  9. data/doc/api/httpkit/body.html +149 -0
  10. data/doc/api/httpkit/client.html +50 -0
  11. data/doc/api/httpkit/client/body_handler.html +50 -0
  12. data/doc/api/httpkit/client/keep_alive_handler.html +79 -0
  13. data/doc/api/httpkit/client/mandatory_handler.html +50 -0
  14. data/doc/api/httpkit/client/timeouts_handler.html +82 -0
  15. data/doc/api/httpkit/connection/eventmachine.html +157 -0
  16. data/doc/api/httpkit/connection/status.html +50 -0
  17. data/doc/api/httpkit/promise.html +50 -0
  18. data/doc/api/httpkit/request.html +123 -0
  19. data/doc/api/httpkit/response.html +209 -0
  20. data/doc/api/httpkit/serializer.html +150 -0
  21. data/doc/api/httpkit/server.html +50 -0
  22. data/doc/api/httpkit/server/block_handler.html +50 -0
  23. data/doc/api/httpkit/server/body_handler.html +50 -0
  24. data/doc/api/httpkit/server/keep_alive_handler.html +145 -0
  25. data/doc/api/httpkit/server/mandatory_handler.html +50 -0
  26. data/doc/api/httpkit/server/timeouts_handler.html +81 -0
  27. data/doc/api/httpkit/support/handler_manager.html +95 -0
  28. data/doc/api/httpkit/support/message.html +50 -0
  29. data/doc/api/httpkit/version.html +50 -0
  30. data/doc/examples/echo_server.html +101 -0
  31. data/doc/examples/error_handling.html +176 -0
  32. data/doc/examples/getting_started.html +161 -0
  33. data/doc/examples/streaming.html +108 -0
  34. data/doc/index.html +165 -0
  35. data/examples/echo_server.rb +14 -6
  36. data/examples/error_handling.rb +56 -0
  37. data/examples/getting_started.rb +10 -18
  38. data/examples/streaming.rb +41 -0
  39. data/lib/httpkit.rb +22 -0
  40. data/lib/httpkit/body.rb +4 -0
  41. data/lib/httpkit/client.rb +1 -9
  42. data/lib/httpkit/client/keep_alive_handler.rb +1 -0
  43. data/lib/httpkit/connection/eventmachine.rb +2 -1
  44. data/lib/httpkit/server/block_handler.rb +13 -0
  45. data/lib/httpkit/server/keep_alive_handler.rb +1 -0
  46. data/lib/httpkit/version.rb +1 -1
  47. data/spec/integration/timeouts_spec.rb +3 -2
  48. data/spec/support/helper.rb +1 -8
  49. data/spec/unit/client_spec.rb +2 -21
  50. data/spec/unit/server_spec.rb +11 -1
  51. metadata +34 -5
  52. data/Procfile +0 -1
@@ -0,0 +1,108 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html;charset=utf-8">
5
+ <title>streaming.rb</title>
6
+ <link rel="stylesheet" href="http://jashkenas.github.io/docco/resources/linear/docco.css">
7
+ </head>
8
+ <body>
9
+ <div id='container'>
10
+ <div id="background"></div>
11
+ <div id="jump_to">
12
+ Jump To &hellip;
13
+ <div id="jump_wrapper">
14
+ <div id="jump_page">
15
+ <a class="source" href="echo_server.html">echo_server.rb</a>
16
+ <a class="source" href="error_handling.html">error_handling.rb</a>
17
+ <a class="source" href="getting_started.html">getting_started.rb</a>
18
+ <a class="source" href="streaming.html">streaming.rb</a>
19
+ </div>
20
+ </div>
21
+ </div>
22
+ <table cellspacing=0 cellpadding=0>
23
+ <thead>
24
+ <tr>
25
+ <th class=docs><h1>streaming.rb</h1></th>
26
+ <th class=code></th>
27
+ </tr>
28
+ </thead>
29
+ <tbody>
30
+ <tr id='section-1'>
31
+ <td class=docs>
32
+ <div class="pilwrap">
33
+ <a class="pilcrow" href="#section-1">&#182;</a>
34
+ </div>
35
+
36
+ </td>
37
+ <td class=code>
38
+ <div class='highlight'><pre><span class="nb">require</span> <span class="s1">&#39;httpkit&#39;</span>
39
+
40
+ <span class="k">class</span> <span class="nc">Streaming</span>
41
+ <span class="k">def</span> <span class="nf">serve</span><span class="p">(</span><span class="n">_request</span><span class="p">,</span> <span class="n">served</span><span class="p">)</span>
42
+ <span class="n">response</span> <span class="o">=</span> <span class="n">streaming_response</span>
43
+ <span class="n">served</span><span class="o">.</span><span class="n">fulfill</span><span class="p">(</span><span class="n">response</span><span class="p">)</span>
44
+
45
+ <span class="n">response</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">&#39;Doing stuff...&#39;</span><span class="p">)</span>
46
+ <span class="no">EM</span><span class="o">.</span><span class="n">add_timer</span><span class="p">(</span><span class="mi">1</span><span class="o">.</span><span class="mi">0</span><span class="p">)</span> <span class="p">{</span> <span class="n">response</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">&#39;More stuff...&#39;</span><span class="p">)</span> <span class="p">}</span>
47
+ <span class="no">EM</span><span class="o">.</span><span class="n">add_timer</span><span class="p">(</span><span class="mi">2</span><span class="o">.</span><span class="mi">0</span><span class="p">)</span> <span class="p">{</span> <span class="n">response</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">&#39;Done!&#39;</span><span class="p">)</span> <span class="p">}</span>
48
+ <span class="no">EM</span><span class="o">.</span><span class="n">add_timer</span><span class="p">(</span><span class="mi">3</span><span class="o">.</span><span class="mi">0</span><span class="p">)</span> <span class="p">{</span> <span class="n">response</span><span class="o">.</span><span class="n">close</span> <span class="p">}</span>
49
+ <span class="k">end</span>
50
+
51
+ <span class="kp">private</span></pre></div>
52
+ </td>
53
+ </tr>
54
+ <tr id='section-2'>
55
+ <td class=docs>
56
+ <div class="pilwrap">
57
+ <a class="pilcrow" href="#section-2">&#182;</a>
58
+ </div>
59
+ <p>When passing a Body without source, i.e. nil, the response is being kept
60
+ open for further body chunks.</p>
61
+ </td>
62
+ <td class=code>
63
+ <div class='highlight'><pre> <span class="k">def</span> <span class="nf">streaming_response</span>
64
+ <span class="ss">HTTPkit</span><span class="p">:</span><span class="ss">:Response</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="mi">200</span><span class="p">,</span>
65
+ <span class="p">{</span> <span class="s1">&#39;Content-Type&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;application/octet-stream&#39;</span> <span class="p">},</span>
66
+ <span class="ss">HTTPkit</span><span class="p">:</span><span class="ss">:Body</span><span class="o">.</span><span class="n">new</span><span class="p">)</span>
67
+ <span class="k">end</span>
68
+ <span class="k">end</span>
69
+
70
+ <span class="no">HTTPkit</span><span class="o">.</span><span class="n">run</span> <span class="k">do</span>
71
+ <span class="n">address</span> <span class="o">=</span> <span class="s1">&#39;127.0.0.1&#39;</span>
72
+ <span class="n">port</span> <span class="o">=</span> <span class="no">HTTPkit</span><span class="o">.</span><span class="n">random_port</span><span class="p">(</span><span class="n">address</span><span class="p">)</span>
73
+
74
+ <span class="ss">HTTPkit</span><span class="p">:</span><span class="ss">:Server</span><span class="o">.</span><span class="n">start</span><span class="p">(</span><span class="ss">address</span><span class="p">:</span> <span class="n">address</span><span class="p">,</span> <span class="ss">port</span><span class="p">:</span> <span class="n">port</span><span class="p">,</span>
75
+ <span class="ss">handlers</span><span class="p">:</span> <span class="o">[</span><span class="no">Streaming</span><span class="o">.</span><span class="n">new</span><span class="o">]</span><span class="p">)</span>
76
+
77
+ <span class="n">response</span> <span class="o">=</span> <span class="no">HTTPkit</span><span class="o">.</span><span class="n">request</span><span class="p">(</span><span class="ss">:get</span><span class="p">,</span> <span class="s2">&quot;http://</span><span class="si">#{</span><span class="n">address</span><span class="si">}</span><span class="s2">:</span><span class="si">#{</span><span class="n">port</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span></pre></div>
78
+ </td>
79
+ </tr>
80
+ <tr id='section-3'>
81
+ <td class=docs>
82
+ <div class="pilwrap">
83
+ <a class="pilcrow" href="#section-3">&#182;</a>
84
+ </div>
85
+ <p>Yields in the Fiber that wrote the chunk, does not block, a.k.a. async.
86
+ Only yields for future chunks, so we need to explicitly grab past ones.</p>
87
+ </td>
88
+ <td class=code>
89
+ <div class='highlight'><pre> <span class="nb">puts</span> <span class="n">response</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">chunks</span>
90
+ <span class="n">response</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">closed</span><span class="o">.</span><span class="n">on_progress</span> <span class="p">{</span> <span class="o">|</span><span class="n">chunk</span><span class="o">|</span> <span class="nb">puts</span> <span class="n">chunk</span> <span class="p">}</span></pre></div>
91
+ </td>
92
+ </tr>
93
+ <tr id='section-4'>
94
+ <td class=docs>
95
+ <div class="pilwrap">
96
+ <a class="pilcrow" href="#section-4">&#182;</a>
97
+ </div>
98
+ <p>Yields all past and future chunks here, blocks.</p>
99
+
100
+ </td>
101
+ <td class=code>
102
+ <div class='highlight'><pre> <span class="n">response</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">chunk</span><span class="o">|</span> <span class="nb">puts</span> <span class="n">chunk</span> <span class="p">}</span>
103
+ <span class="k">end</span></pre></div>
104
+ </td>
105
+ </tr>
106
+ </table>
107
+ </div>
108
+ </body>
@@ -0,0 +1,165 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html;charset=utf-8">
5
+ <title>README.md</title>
6
+ <link rel="stylesheet" href="https://raw.githubusercontent.com/jashkenas/docco/master/resources/linear/docco.css">
7
+ </head>
8
+ <body>
9
+ <div id='container'>
10
+ <div id="background"></div>
11
+ <table cellspacing=0 cellpadding=0>
12
+ <thead>
13
+ <tr>
14
+ <th class=docs><h1>README.md</h1></th>
15
+ <th class=code></th>
16
+ </tr>
17
+ </thead>
18
+ <tbody>
19
+ <tr id='section-1'>
20
+ <td class=docs>
21
+ <div class="pilwrap">
22
+ <a class="pilcrow" href="#section-1">&#182;</a>
23
+ </div>
24
+ <p>The HTTP toolkit for Ruby</p>
25
+ </td>
26
+ <td class=code>
27
+ <div class='highlight'><pre><span class="n">HTTPkit</span> <span class="k">is</span> <span class="n">a</span> <span class="n">Ruby</span> <span class="n">toolkit</span> <span class="k">for</span> <span class="n">building</span> <span class="n">HTTP</span> <span class="n">clients</span> <span class="n">and</span> <span class="n">servers</span><span class="p">,</span>
28
+ <span class="k">as</span> <span class="n">well</span> <span class="k">as</span> <span class="n">compositions</span> <span class="n">of</span> <span class="n">them</span><span class="p">.</span>
29
+
30
+ <span class="p">[![</span><span class="n">Build</span> <span class="n">Status</span><span class="p">](</span><span class="n">https</span><span class="p">:</span><span class="c1">//travis-ci.org/lgierth/httpkit.png?branch=master)](https://travis-ci.org/lgierth/httpkit) [![Code Climate](https://codeclimate.com/github/lgierth/httpkit.png)](https://codeclimate.com/github/lgierth/httpkit) [![Coverage Status](https://coveralls.io/repos/lgierth/httpkit/badge.png?branch=master)](https://coveralls.io/r/lgierth/httpkit?branch=master)</span>
31
+
32
+ <span class="p">-</span> <span class="p">\#</span><span class="mi">1</span> <span class="n">feature</span><span class="p">:</span> <span class="n">consistent</span><span class="p">,</span> <span class="n">high</span><span class="p">-</span><span class="n">quality</span><span class="p">,</span> <span class="n">extendable</span> <span class="n">codebase</span> <span class="k">with</span> <span class="mf">71.88</span><span class="p">%</span> <span class="n">mutation</span> <span class="n">coverage</span> <span class="p">(</span><span class="n">wip</span><span class="p">)</span>
33
+ <span class="p">-</span> <span class="p">\#</span><span class="mi">2</span> <span class="n">feature</span><span class="p">:</span> <span class="n">sophisticated</span> <span class="n">request</span> <span class="n">and</span> <span class="n">response</span> <span class="n">streaming</span>
34
+ <span class="p">-</span> <span class="p">\#</span><span class="mi">3</span> <span class="n">feature</span><span class="p">:</span> <span class="n">compatible</span> <span class="k">with</span> <span class="n">Rack</span><span class="p">,</span> <span class="n">Faraday</span><span class="p">,</span> <span class="n">and</span> <span class="n">VCR</span> <span class="p">(</span><span class="n">all</span> <span class="n">todo</span><span class="p">),</span> <span class="n">and</span> <span class="n">Webmachine</span> <span class="k">for</span> <span class="n">Ruby</span>
35
+ <span class="p">-</span> <span class="p">\#</span><span class="mi">4</span> <span class="n">feature</span><span class="p">:</span> <span class="n">backed</span> <span class="n">by</span> <span class="n">Celluloid</span> <span class="p">(</span><span class="n">wip</span><span class="p">)</span> <span class="n">or</span> <span class="n">Eventmachine</span>
36
+ <span class="p">-</span> <span class="p">\#</span><span class="mi">5</span> <span class="n">feature</span><span class="p">:</span> <span class="n">compatible</span> <span class="k">with</span> <span class="n">MRuby</span> <span class="p">(</span><span class="n">todo</span><span class="p">)</span>
37
+
38
+ <span class="n">Before</span> <span class="n">v0</span><span class="p">.</span><span class="mf">6.0</span><span class="p">,</span> <span class="n">HTTPkit</span> <span class="n">was</span> <span class="n">called</span> <span class="n">Hatetepe</span> <span class="n">and</span> <span class="n">then</span> <span class="n">underwent</span> <span class="n">a</span> <span class="n">ground</span><span class="p">-</span><span class="n">up</span> <span class="n">rewrite</span><span class="p">.</span> <span class="n">Look</span> <span class="n">at</span> <span class="n">the</span> <span class="p">[</span><span class="mf">0.5</span><span class="p">.</span><span class="n">x</span> <span class="n">branch</span><span class="p">](</span><span class="n">https</span><span class="p">:</span><span class="c1">//github.com/lgierth/httpkit/tree/0.5.x) for the old code.</span>
39
+
40
+
41
+ <span class="p">#</span> <span class="n">DIVIDER</span>
42
+
43
+
44
+ <span class="n">Add</span> <span class="k">this</span> <span class="n">line</span> <span class="n">to</span> <span class="n">your</span> <span class="n">application</span><span class="err">&#39;</span><span class="n">s</span> <span class="n">Gemfile</span><span class="p">:</span>
45
+
46
+ <span class="n">gem</span> <span class="err">&#39;</span><span class="n">httpkit</span><span class="err">&#39;</span><span class="p">,</span> <span class="err">&#39;</span><span class="mf">0.6</span><span class="p">.</span><span class="mf">0</span><span class="p">.</span><span class="n">pre</span><span class="p">.</span><span class="mi">3</span><span class="err">&#39;</span>
47
+
48
+ <span class="n">And</span> <span class="n">then</span> <span class="n">execute</span><span class="p">:</span>
49
+
50
+ <span class="p">$</span> <span class="n">bundle</span>
51
+
52
+ <span class="n">Or</span> <span class="n">install</span> <span class="n">it</span> <span class="n">yourself</span> <span class="k">as</span><span class="p">:</span>
53
+
54
+ <span class="p">$</span> <span class="n">gem</span> <span class="n">install</span> <span class="n">httpkit</span> <span class="p">--</span><span class="n">pre</span>
55
+
56
+
57
+ <span class="p">#</span> <span class="n">DIVIDER</span>
58
+
59
+
60
+ <span class="n">Code</span> <span class="n">examples</span>
61
+
62
+ <span class="p">-</span> <span class="p">[</span><span class="n">Getting</span> <span class="n">started</span><span class="p">](</span><span class="n">http</span><span class="p">:</span><span class="c1">//rubydoc.info/github/lgierth/httpkit/master/file/examples/getting_started.rb)</span>
63
+ <span class="p">-</span> <span class="p">[</span><span class="n">HTTP</span> <span class="n">echo</span> <span class="n">server</span><span class="p">](</span><span class="n">http</span><span class="p">:</span><span class="c1">//rubydoc.info/github/lgierth/httpkit/master/file/examples/echo_server.rb)</span>
64
+ <span class="p">-</span> <span class="p">[</span><span class="n">Streaming</span><span class="p">](</span><span class="n">http</span><span class="p">:</span><span class="c1">//rubydoc.info/github/lgierth/httpkit/master/file/examples/streaming.rb)</span>
65
+ <span class="p">-</span> <span class="p">[</span><span class="n">Error</span> <span class="n">handling</span><span class="p">](</span><span class="n">http</span><span class="p">:</span><span class="c1">//rubydoc.info/github/lgierth/httpkit/master/file/examples/error_handling.rb)</span>
66
+ <span class="p">-</span> <span class="p">[</span><span class="n">Connection</span> <span class="n">status</span><span class="p">]()</span>
67
+ <span class="p">-</span> <span class="p">[</span><span class="n">Custom</span> <span class="n">handlers</span><span class="p">]()</span>
68
+
69
+ <span class="n">API</span> <span class="n">Reference</span>
70
+
71
+ <span class="p">-</span> <span class="p">[</span><span class="n">HTTPkit</span><span class="p">](</span><span class="n">http</span><span class="p">:</span><span class="c1">//rubydoc.info/github/lgierth/httpkit/master/HTTPkit)</span>
72
+ <span class="p">-</span> <span class="p">[</span><span class="n">HTTPkit</span><span class="p">::</span><span class="n">Request</span><span class="p">](</span><span class="n">http</span><span class="p">:</span><span class="c1">//rubydoc.info/github/lgierth/httpkit/master/HTTPkit/Request)</span>
73
+ <span class="p">-</span> <span class="p">[</span><span class="n">HTTPkit</span><span class="p">::</span><span class="n">Response</span><span class="p">](</span><span class="n">http</span><span class="p">:</span><span class="c1">//rubydoc.info/github/lgierth/httpkit/master/HTTPkit/Response)</span>
74
+ <span class="p">-</span> <span class="p">[</span><span class="n">HTTPkit</span><span class="p">::</span><span class="n">Body</span><span class="p">](</span><span class="n">http</span><span class="p">:</span><span class="c1">//rubydoc.info/github/lgierth/httpkit/master/HTTPkit/Body)</span>
75
+ <span class="p">-</span> <span class="p">[</span><span class="n">HTTPkit</span><span class="p">::</span><span class="n">Client</span><span class="p">](</span><span class="n">http</span><span class="p">:</span><span class="c1">//rubydoc.info/github/lgierth/httpkit/master/HTTPkit/Client)</span>
76
+ <span class="p">-</span> <span class="p">[</span><span class="n">HTTPkit</span><span class="p">::</span><span class="n">Server</span><span class="p">](</span><span class="n">http</span><span class="p">:</span><span class="c1">//rubydoc.info/github/lgierth/httpkit/master/HTTPkit/Server)</span>
77
+ <span class="p">-</span> <span class="p">[</span><span class="n">HTTPkit</span><span class="p">::</span><span class="n">Promise</span><span class="p">](</span><span class="n">http</span><span class="p">:</span><span class="c1">//rubydoc.info/github/lgierth/httpkit/master/HTTPkit/Promise)</span>
78
+ <span class="p">-</span> <span class="p">[</span><span class="n">HTTPkit</span><span class="p">::</span><span class="n">Serializer</span><span class="p">](</span><span class="n">http</span><span class="p">:</span><span class="c1">//rubydoc.info/github/lgierth/httpkit/master/HTTPkit/Serializer)</span>
79
+ <span class="p">-</span> <span class="p">[</span><span class="n">HTTPkit</span><span class="p">::</span><span class="n">ClientHandler</span><span class="p">](</span><span class="n">http</span><span class="p">:</span><span class="c1">//rubydoc.info/github/lgierth/httpkit/master/HTTPkit/Client/Handler)</span>
80
+ <span class="p">-</span> <span class="p">[</span><span class="n">HTTPkit</span><span class="p">::</span><span class="n">ServerHandler</span><span class="p">](</span><span class="n">http</span><span class="p">:</span><span class="c1">//rubydoc.info/github/lgierth/httpkit/master/HTTPkit/Server/Handler)</span>
81
+
82
+
83
+ <span class="p">#</span> <span class="n">DIVIDER</span>
84
+
85
+
86
+ <span class="n">Here</span><span class="p">:</span> <span class="n">https</span><span class="p">:</span><span class="c1">//trello.com/b/OoxEq1ze/httpkit</span>
87
+
88
+
89
+ <span class="p">#</span> <span class="n">DIVIDER</span>
90
+
91
+
92
+ <span class="n">HTTPkit</span> <span class="k">is</span> <span class="n">free</span> <span class="n">and</span> <span class="n">unencumbered</span> <span class="n">public</span> <span class="n">domain</span> <span class="n">software</span><span class="p">.</span> <span class="n">For</span> <span class="n">more</span>
93
+ <span class="n">information</span><span class="p">,</span> <span class="n">see</span> <span class="p">[</span><span class="n">unlicense</span><span class="p">.</span><span class="n">org</span><span class="p">](</span><span class="n">http</span><span class="p">:</span><span class="c1">//unlicense.org/) or the accompanying</span>
94
+ <span class="n">UNLICENSE</span> <span class="n">file</span><span class="p">.</span>
95
+
96
+
97
+ <span class="p">#</span> <span class="n">DIVIDER</span>
98
+
99
+
100
+ <span class="mf">1</span><span class="p">.</span> <span class="n">Fork</span> <span class="n">it</span>
101
+ <span class="mf">2</span><span class="p">.</span> <span class="n">Create</span> <span class="n">your</span> <span class="n">feature</span> <span class="n">branch</span> <span class="p">(</span><span class="err">`</span><span class="n">git</span> <span class="n">checkout</span> <span class="p">-</span><span class="n">b</span> <span class="n">my</span><span class="p">-</span><span class="n">new</span><span class="p">-</span><span class="n">feature</span><span class="err">`</span><span class="p">)</span>
102
+ <span class="mf">3</span><span class="p">.</span> <span class="n">Commit</span> <span class="n">your</span> <span class="n">changes</span> <span class="p">(</span><span class="err">`</span><span class="n">git</span> <span class="n">commit</span> <span class="p">-</span><span class="n">am</span> <span class="err">&#39;</span><span class="n">Add</span> <span class="n">some</span> <span class="n">feature</span><span class="err">&#39;`</span><span class="p">)</span>
103
+ <span class="mf">4</span><span class="p">.</span> <span class="n">Push</span> <span class="n">to</span> <span class="n">the</span> <span class="n">branch</span> <span class="p">(</span><span class="err">`</span><span class="n">git</span> <span class="n">push</span> <span class="n">origin</span> <span class="n">my</span><span class="p">-</span><span class="n">new</span><span class="p">-</span><span class="n">feature</span><span class="err">`</span><span class="p">)</span>
104
+ <span class="mf">5</span><span class="p">.</span> <span class="n">Create</span> <span class="n">new</span> <span class="n">Pull</span> <span class="n">Request</span></pre></div>
105
+ </td>
106
+ </tr>
107
+ <tr id='section-Installation'>
108
+ <td class=docs>
109
+ <div class="pilwrap">
110
+ <a class="pilcrow" href="#section-Installation">&#182;</a>
111
+ </div>
112
+ <h1>Installation</h1>
113
+ </td>
114
+ <td class=code>
115
+ <div class='highlight'><pre></pre></div>
116
+ </td>
117
+ </tr>
118
+ <tr id='section-Usage'>
119
+ <td class=docs>
120
+ <div class="pilwrap">
121
+ <a class="pilcrow" href="#section-Usage">&#182;</a>
122
+ </div>
123
+ <h1>Usage</h1>
124
+ </td>
125
+ <td class=code>
126
+ <div class='highlight'><pre></pre></div>
127
+ </td>
128
+ </tr>
129
+ <tr id='section-To_do'>
130
+ <td class=docs>
131
+ <div class="pilwrap">
132
+ <a class="pilcrow" href="#section-To_do">&#182;</a>
133
+ </div>
134
+ <h1>To do</h1>
135
+ </td>
136
+ <td class=code>
137
+ <div class='highlight'><pre></pre></div>
138
+ </td>
139
+ </tr>
140
+ <tr id='section-License'>
141
+ <td class=docs>
142
+ <div class="pilwrap">
143
+ <a class="pilcrow" href="#section-License">&#182;</a>
144
+ </div>
145
+ <h1>License</h1>
146
+ </td>
147
+ <td class=code>
148
+ <div class='highlight'><pre></pre></div>
149
+ </td>
150
+ </tr>
151
+ <tr id='section-Contributing'>
152
+ <td class=docs>
153
+ <div class="pilwrap">
154
+ <a class="pilcrow" href="#section-Contributing">&#182;</a>
155
+ </div>
156
+ <h1>Contributing</h1>
157
+
158
+ </td>
159
+ <td class=code>
160
+ <div class='highlight'><pre></pre></div>
161
+ </td>
162
+ </tr>
163
+ </table>
164
+ </div>
165
+ </body>
@@ -5,6 +5,10 @@ require 'httpkit'
5
5
  class EchoServer
6
6
  def serve(request, served)
7
7
  response = streaming_response
8
+
9
+ # We start sending the response even we started writing its body. This is
10
+ # not mandatory, but it delivers the response to client as quickly as
11
+ # possible.
8
12
  served.fulfill(response)
9
13
 
10
14
  serialize(request, response)
@@ -14,10 +18,12 @@ class EchoServer
14
18
  private
15
19
 
16
20
  def streaming_response
17
- HTTPkit::Response.new(200, { 'Content-Type' => 'text/plain' },
21
+ HTTPkit::Response.new(200,
22
+ { 'Content-Type' => 'application/octet-stream' },
18
23
  HTTPkit::Body.new)
19
24
  end
20
25
 
26
+ # This re-serializes the whole request directly into the response body.
21
27
  def serialize(request, response)
22
28
  writer = response.body.method(:write)
23
29
  serializer = HTTPkit::Serializer.new(request, writer)
@@ -25,12 +31,14 @@ class EchoServer
25
31
  end
26
32
  end
27
33
 
28
- HTTPkit.start do
29
- HTTPkit::Server.start(address: ENV.fetch('ADDRESS', '127.0.0.1'),
30
- port: ENV.fetch('PORT', 3000).to_i,
34
+ HTTPkit.run do
35
+ address = '127.0.0.1'
36
+ port = HTTPkit.random_port(address)
37
+
38
+ HTTPkit::Server.start(address: address, port: port,
31
39
  handlers: [HTTPkit::Server::KeepAliveHandler.new,
32
40
  EchoServer.new])
33
41
 
34
- Signal.trap(:INT) { HTTPkit.stop }
35
- Signal.trap(:TERM) { HTTPkit.stop }
42
+ body = HTTPkit.request(:get, "http://#{address}:#{port}").body
43
+ body.to_s.each_line { |line| p line }
36
44
  end
@@ -0,0 +1,56 @@
1
+ # encoding: utf-8
2
+
3
+ require 'httpkit'
4
+
5
+ class Failwhale
6
+ # TODO: Rejecting the served promise on the server side currently has no
7
+ # effect, except for the response simply not being sent. This has the
8
+ # potential of mixing up responses, so we should instead just send
9
+ # a 500 response for every rejected served promise. The same should
10
+ # happen for errors raised from handlers' #serve.
11
+ def serve(request, served)
12
+ raise if request.uri == '/raise'
13
+
14
+ served.fulfill(HTTPkit::Response.new(500))
15
+ end
16
+ end
17
+
18
+ HTTPkit.run do
19
+ address = '127.0.0.1'
20
+ port = HTTPkit.random_port(address)
21
+ uri = "http://#{address}:#{port}"
22
+
23
+ HTTPkit.server(uri) do |request, served|
24
+ raise if request.uri == '/raise'
25
+ served.fulfill(HTTPkit::Response.new(500))
26
+ end
27
+
28
+ # 5xx responses are just normal responses.
29
+ response = HTTPkit.request(:get, uri)
30
+ p response.status
31
+ # => 500
32
+
33
+ # Let's crash the server and make it close the connection.
34
+ begin
35
+ HTTPkit.request(:get, uri + '/raise')
36
+ rescue Promise::Error => ex
37
+ puts ex.backtrace
38
+ # Connection error. Below we see how to find out more.
39
+ end
40
+
41
+ client = HTTPkit::Client.start(address: address, port: port)
42
+ request = HTTPkit::Request.new(:get, '/raise')
43
+ served = client.perform(request)
44
+
45
+ # Instead of getting fulfilled with a response, we see that the served
46
+ # promise gets rejected. Calling #sync on served would raise the rejection
47
+ # reason, in this case Promise::Error.
48
+ served.wait
49
+ p served.state
50
+ # => :rejected
51
+ p served.reason
52
+ # => Promise::Error if the connection was closed properly (in the TCP sense),
53
+ # otherwise one of the Errno:: constants.
54
+ p client.closed?
55
+ # => true
56
+ end
@@ -2,39 +2,31 @@
2
2
 
3
3
  require 'httpkit'
4
4
 
5
- class HelloServer
6
- def serve(request, served)
5
+ HTTPkit.run do
6
+ # This is short-hand for the HTTPkit::Server.start dance.
7
+ HTTPkit.server('http://127.0.0.1:3000') do |request, served|
7
8
  p request.http_method
8
9
  # => :get
9
10
  p request.uri
10
11
  # => "/"
11
12
  p request.headers
12
- # => {"Host"=>"127.0.0.1:3000", "Content-Length"=>"0"}
13
+ # => {"User-Agent"=>"httpkit/0.6.0.pre.5", "Host"=>"127.0.0.1:3000"}
13
14
  p request.body.to_s
14
15
  # => ""
15
16
 
16
- served.fulfill(response)
17
- end
18
-
19
- def response
20
- HTTPkit::Response.new(200, { 'Content-Type' => 'text/plain' }, 'hello')
17
+ served.fulfill(HTTPkit::Response.new(200, {}, 'hello!'))
21
18
  end
22
- end
23
-
24
- HTTPkit.run do
25
- HTTPkit::Server.start(address: '127.0.0.1', port: 3000,
26
- handlers: [HelloServer.new])
27
-
28
- client = HTTPkit::Client.start(address: '127.0.0.1', port: 3000)
29
19
 
30
- response = client.request(:get, '/')
20
+ # Same here, but for HTTPkit::Client.start.
21
+ response = HTTPkit.request(:get, 'http://127.0.0.1:3000')
31
22
 
32
23
  p response.status
33
24
  # => 200
34
25
  p response.status_name
35
26
  # => "OK"
36
27
  p response.headers
37
- # => {"Content-Type"=>"text/plain", "Content-Length"=>"5"}
28
+ # => {"Connection"=>"keep-alive", "Server"=>"httpkit/0.6.0.pre.5",
29
+ # "Date"=>"Sat, 19 Jul 2014 16:13:30 GMT", "Content-Length"=>"6"}
38
30
  p response.body.to_s
39
- # => "hello"
31
+ # => "hello!"
40
32
  end
@@ -0,0 +1,41 @@
1
+ # encoding: utf-8
2
+
3
+ require 'httpkit'
4
+
5
+ class Streaming
6
+ def serve(_request, served)
7
+ response = streaming_response
8
+ served.fulfill(response)
9
+
10
+ response.body.write('Doing stuff...')
11
+ EM.add_timer(1.0) { response.body.write('More stuff...') }
12
+ EM.add_timer(2.0) { response.body.write('Done!') }
13
+ EM.add_timer(3.0) { response.close }
14
+ end
15
+
16
+ private
17
+
18
+ # When passing a Body without source, i.e. nil, the response is being kept
19
+ # open for further body chunks.
20
+ def streaming_response
21
+ HTTPkit::Response.new(200,
22
+ { 'Content-Type' => 'application/octet-stream' },
23
+ HTTPkit::Body.new)
24
+ end
25
+ end
26
+
27
+ HTTPkit.run do
28
+ address = '127.0.0.1'
29
+ port = HTTPkit.random_port(address)
30
+
31
+ HTTPkit::Server.start(address: address, port: port,
32
+ handlers: [Streaming.new])
33
+
34
+ response = HTTPkit.request(:get, "http://#{address}:#{port}")
35
+ # Yields in the Fiber that wrote the chunk, does not block, a.k.a. async.
36
+ # Only yields for future chunks, so we need to explicitly grab past ones.
37
+ puts response.body.chunks
38
+ response.body.closed.on_progress { |chunk| puts chunk }
39
+ # Yields all past and future chunks here, blocks.
40
+ response.body.each { |chunk| puts chunk }
41
+ end