tipi 0.30
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/test.yml +27 -0
- data/.gitignore +56 -0
- data/CHANGELOG.md +33 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +50 -0
- data/LICENSE +21 -0
- data/README.md +23 -0
- data/Rakefile +12 -0
- data/TODO.md +66 -0
- data/bin/tipi +12 -0
- data/docs/README.md +62 -0
- data/docs/summary.md +60 -0
- data/examples/cuba.ru +23 -0
- data/examples/hanami-api.ru +23 -0
- data/examples/http_server.js +24 -0
- data/examples/http_server.rb +21 -0
- data/examples/http_server_forked.rb +29 -0
- data/examples/http_server_graceful.rb +27 -0
- data/examples/http_server_simple.rb +11 -0
- data/examples/http_server_throttled.rb +15 -0
- data/examples/http_server_timeout.rb +35 -0
- data/examples/http_ws_server.rb +37 -0
- data/examples/https_server.rb +24 -0
- data/examples/https_server_forked.rb +32 -0
- data/examples/https_wss_server.rb +39 -0
- data/examples/rack_server.rb +12 -0
- data/examples/rack_server_https.rb +19 -0
- data/examples/rack_server_https_forked.rb +27 -0
- data/examples/websocket_secure_server.rb +27 -0
- data/examples/websocket_server.rb +24 -0
- data/examples/ws_page.html +34 -0
- data/examples/wss_page.html +34 -0
- data/lib/tipi.rb +54 -0
- data/lib/tipi/http1_adapter.rb +268 -0
- data/lib/tipi/http2_adapter.rb +74 -0
- data/lib/tipi/http2_stream.rb +134 -0
- data/lib/tipi/rack_adapter.rb +67 -0
- data/lib/tipi/request.rb +118 -0
- data/lib/tipi/version.rb +5 -0
- data/lib/tipi/websocket.rb +61 -0
- data/test/coverage.rb +45 -0
- data/test/eg.rb +27 -0
- data/test/helper.rb +51 -0
- data/test/run.rb +5 -0
- data/test/test_http_server.rb +321 -0
- data/tipi.gemspec +34 -0
- metadata +241 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 92c33ccc40f7b8f4f53fded65ab5902c81bcf0a92598fa5b2be3ada409a78721
|
4
|
+
data.tar.gz: b4f80d28c10539b44d1554fbd8e640c253919070cc576efbf62249eee8efeeb7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6a5712289bb6adc18e4c6fa24495157c19c41831036adc2e5ef082a640b09df426d015de5f00cb48d1d78d0855ce078c1cc7f2c15a1cec24a68cf022d45f9eea
|
7
|
+
data.tar.gz: 55e627cb9a6e91a846460ee30f3480ad77e4cb9124a40cd2fc68bf9abba7d6ecdbc52530ac92271d78c4a75fc9654be706efb59dba491ebbc6bc70532bc42aaa
|
@@ -0,0 +1,27 @@
|
|
1
|
+
name: Tests
|
2
|
+
|
3
|
+
on: [push, pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
build:
|
7
|
+
strategy:
|
8
|
+
fail-fast: false
|
9
|
+
matrix:
|
10
|
+
os: [ubuntu-latest]
|
11
|
+
ruby: [2.6, 2.7]
|
12
|
+
|
13
|
+
name: >-
|
14
|
+
${{matrix.os}}, ${{matrix.ruby}}
|
15
|
+
|
16
|
+
runs-on: ${{matrix.os}}
|
17
|
+
steps:
|
18
|
+
- uses: actions/checkout@v1
|
19
|
+
- uses: actions/setup-ruby@v1
|
20
|
+
with:
|
21
|
+
ruby-version: ${{matrix.ruby}}
|
22
|
+
- name: Install dependencies
|
23
|
+
run: |
|
24
|
+
gem install bundler
|
25
|
+
bundle install
|
26
|
+
- name: Run tests
|
27
|
+
run: bundle exec rake test
|
data/.gitignore
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/spec/examples.txt
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
/tmp/
|
12
|
+
|
13
|
+
# Used by dotenv library to load environment variables.
|
14
|
+
# .env
|
15
|
+
|
16
|
+
# Ignore Byebug command history file.
|
17
|
+
.byebug_history
|
18
|
+
|
19
|
+
## Specific to RubyMotion:
|
20
|
+
.dat*
|
21
|
+
.repl_history
|
22
|
+
build/
|
23
|
+
*.bridgesupport
|
24
|
+
build-iPhoneOS/
|
25
|
+
build-iPhoneSimulator/
|
26
|
+
|
27
|
+
## Specific to RubyMotion (use of CocoaPods):
|
28
|
+
#
|
29
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
30
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
31
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
32
|
+
#
|
33
|
+
# vendor/Pods/
|
34
|
+
|
35
|
+
## Documentation cache and generated files:
|
36
|
+
/.yardoc/
|
37
|
+
/_yardoc/
|
38
|
+
/doc/
|
39
|
+
/rdoc/
|
40
|
+
|
41
|
+
## Environment normalization:
|
42
|
+
/.bundle/
|
43
|
+
/vendor/bundle
|
44
|
+
/lib/bundler/man/
|
45
|
+
|
46
|
+
# for a library or gem, you might want to ignore these files since the code is
|
47
|
+
# intended to run in multiple environments; otherwise, check them in:
|
48
|
+
# Gemfile.lock
|
49
|
+
# .ruby-version
|
50
|
+
# .ruby-gemset
|
51
|
+
|
52
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
53
|
+
.rvmrc
|
54
|
+
|
55
|
+
# Used by RuboCop. Remote config files pulled in from inherit_from directive.
|
56
|
+
# .rubocop-https?--*
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
## 0.30 2020-07-15
|
2
|
+
|
3
|
+
* Rename project to Tipi
|
4
|
+
* Rearrange source code
|
5
|
+
* Remove HTTP client code (to be developed eventually into a separate gem)
|
6
|
+
* Fix header rendering in rack adapter (#2)
|
7
|
+
|
8
|
+
## 0.29 2020-07-06
|
9
|
+
|
10
|
+
* Use IO#read_loop
|
11
|
+
|
12
|
+
## 0.28 2020-07-03
|
13
|
+
|
14
|
+
* Update with API changes from Polyphony >= 0.41
|
15
|
+
|
16
|
+
## 0.27 2020-04-14
|
17
|
+
|
18
|
+
* Remove modulation dependency
|
19
|
+
|
20
|
+
## 0.26 2020-03-03
|
21
|
+
|
22
|
+
* Fix `Server#listen`
|
23
|
+
|
24
|
+
## 0.25 2020-02-19
|
25
|
+
|
26
|
+
* Ensure server socket is closed upon stopping loop
|
27
|
+
* Fix `Request#format_header_lines`
|
28
|
+
|
29
|
+
## 0.24 2020-01-08
|
30
|
+
|
31
|
+
* Move HTTP to separate polyphony-http gem
|
32
|
+
|
33
|
+
For earlier changes look at the Polyphony changelog.
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
tipi (0.30)
|
5
|
+
http-2 (~> 0.10.0)
|
6
|
+
http_parser.rb (~> 0.6.0)
|
7
|
+
polyphony (~> 0.43.5)
|
8
|
+
rack (>= 2.0.8, < 2.3.0)
|
9
|
+
websocket (~> 1.2.8)
|
10
|
+
|
11
|
+
GEM
|
12
|
+
remote: https://rubygems.org/
|
13
|
+
specs:
|
14
|
+
ansi (1.5.0)
|
15
|
+
builder (3.2.4)
|
16
|
+
docile (1.3.2)
|
17
|
+
http-2 (0.10.2)
|
18
|
+
http_parser.rb (0.6.0)
|
19
|
+
json (2.1.0)
|
20
|
+
localhost (1.1.4)
|
21
|
+
minitest (5.11.3)
|
22
|
+
minitest-reporters (1.4.2)
|
23
|
+
ansi
|
24
|
+
builder
|
25
|
+
minitest (>= 5.0)
|
26
|
+
ruby-progressbar
|
27
|
+
polyphony (0.43.5)
|
28
|
+
rack (2.2.3)
|
29
|
+
rake (12.3.3)
|
30
|
+
ruby-progressbar (1.10.1)
|
31
|
+
simplecov (0.17.1)
|
32
|
+
docile (~> 1.1)
|
33
|
+
json (>= 1.8, < 3)
|
34
|
+
simplecov-html (~> 0.10.0)
|
35
|
+
simplecov-html (0.10.2)
|
36
|
+
websocket (1.2.8)
|
37
|
+
|
38
|
+
PLATFORMS
|
39
|
+
ruby
|
40
|
+
|
41
|
+
DEPENDENCIES
|
42
|
+
localhost (~> 1.1.4)
|
43
|
+
minitest (~> 5.11.3)
|
44
|
+
minitest-reporters (~> 1.4.2)
|
45
|
+
rake (~> 12.3.3)
|
46
|
+
simplecov (~> 0.17.1)
|
47
|
+
tipi!
|
48
|
+
|
49
|
+
BUNDLED WITH
|
50
|
+
2.1.4
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2018 Sharon Rosner
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# Tipi - the All-in-one Web Server for Ruby Apps
|
2
|
+
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/tipi.svg)](http://rubygems.org/gems/tipi)
|
4
|
+
[![Modulation Test](https://github.com/digital-fabric/tipi/workflows/Tests/badge.svg)](https://github.com/digital-fabric/tipi/actions?query=workflow%3ATests)
|
5
|
+
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/digital-fabric/tipi/blob/master/LICENSE)
|
6
|
+
|
7
|
+
## What is Tipi?
|
8
|
+
|
9
|
+
Tipi is an integrated, feature-complete HTTP/S server for Ruby applications.
|
10
|
+
Tipi is built on Polyphony, a robust, high-performance library for building
|
11
|
+
highly-concurrent applications in Ruby. Tipi can be used to serve any Rack
|
12
|
+
application or set of static files directly without having to employ a
|
13
|
+
reverse-proxy such as Nginx.
|
14
|
+
|
15
|
+
## Features
|
16
|
+
|
17
|
+
* **Full-blown, integrated, high-performance HTTP 1 / HTTP 2 / WebSocket server
|
18
|
+
with TLS/SSL termination, automatic ALPN protocol selection, and body
|
19
|
+
streaming**.
|
20
|
+
|
21
|
+
## Documentation
|
22
|
+
|
23
|
+
Documentation for Tipi is coming soon...
|
data/Rakefile
ADDED
data/TODO.md
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# Roadmap
|
2
|
+
|
3
|
+
- Update README (get rid of non-http stuff)
|
4
|
+
- Improve Rack spec compliance, add tests
|
5
|
+
- Homogenize HTTP 1 and HTTP 2 headers - upcase ? downcase ?
|
6
|
+
|
7
|
+
## 0.30
|
8
|
+
|
9
|
+
- Add more poly CLI commands and options:
|
10
|
+
|
11
|
+
- serve static files from given directory
|
12
|
+
- serve from rack up file
|
13
|
+
- serve both http and https
|
14
|
+
- use custom certificate files for SSL
|
15
|
+
- set host address to bind to
|
16
|
+
- set port to bind to
|
17
|
+
- set forking process count
|
18
|
+
|
19
|
+
## 0.31 Working Sinatra application
|
20
|
+
|
21
|
+
- app with database access (postgresql)
|
22
|
+
- benchmarks!
|
23
|
+
|
24
|
+
# HTTP Client Agent
|
25
|
+
|
26
|
+
The concurrency model and the fact that we want to serve the response object on
|
27
|
+
receiving headers and let the user lazily read the response body, means we'll
|
28
|
+
need to change the API to accept a block:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
# current API
|
32
|
+
resp = Agent.get('http://acme.org')
|
33
|
+
puts resp.body
|
34
|
+
|
35
|
+
# proposed API
|
36
|
+
Agent.get('http://acme.org') do |resp|
|
37
|
+
puts resp.body
|
38
|
+
end
|
39
|
+
```
|
40
|
+
|
41
|
+
While the block is running, the connection adapter is acquired. Once the block
|
42
|
+
is done running, the request (and response) can be discarded. The problem with
|
43
|
+
that if we spin up a coprocess from that block we risk all kinds of race
|
44
|
+
conditions and weird behaviours.
|
45
|
+
|
46
|
+
A compromise might be to allow the two: doing a `get` without providing a block
|
47
|
+
will return a response object that already has the body (i.e. the entire
|
48
|
+
response has already been received). Doing a `get` with a block will invoke the
|
49
|
+
block once headers are received, letting the user's code stream the body:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
def request(ctx, &block)
|
53
|
+
...
|
54
|
+
connection_manager.acquire do |adapter|
|
55
|
+
response = adapter.request(ctx)
|
56
|
+
if block
|
57
|
+
block.(response)
|
58
|
+
else
|
59
|
+
# wait for body
|
60
|
+
response.body
|
61
|
+
end
|
62
|
+
response
|
63
|
+
end
|
64
|
+
end
|
65
|
+
```
|
66
|
+
|
data/bin/tipi
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.expand_path('../lib/tipi', __dir__)
|
4
|
+
require File.expand_path('../lib/tipi/rack_adapter', __dir__)
|
5
|
+
|
6
|
+
app_path = ARGV.first || './config.ru'
|
7
|
+
app = Tipi::RackAdapter.load(app_path)
|
8
|
+
opts = { reuse_addr: true, dont_linger: true }
|
9
|
+
|
10
|
+
puts "listening on port 1234"
|
11
|
+
puts "pid: #{Process.pid}"
|
12
|
+
Tipi.serve('0.0.0.0', 1234, opts, &app)
|
data/docs/README.md
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# Polyphony - Easy Concurrency for Ruby
|
2
|
+
|
3
|
+
> Polyphony \| pəˈlɪf\(ə\)ni \|
|
4
|
+
> 1. _Music_ the style of simultaneously combining a number of parts, each
|
5
|
+
> forming an individual melody and harmonizing with each other.
|
6
|
+
> 2. _Programming_ a Ruby gem for concurrent programming focusing on performance
|
7
|
+
> and developer happiness.
|
8
|
+
|
9
|
+
Polyphony is a library for building concurrent applications in Ruby. Polyphony
|
10
|
+
harnesses the power of [Ruby fibers](https://ruby-doc.org/core-2.5.1/Fiber.html)
|
11
|
+
to provide a cooperative, sequential coprocess-based concurrency model. Under
|
12
|
+
the hood, Polyphony uses [libev](https://github.com/enki/libev) as a
|
13
|
+
high-performance event reactor that provides timers, I/O watchers and other
|
14
|
+
asynchronous event primitives.
|
15
|
+
|
16
|
+
Polyphony makes it possible to use normal Ruby built-in classes like `IO`, and
|
17
|
+
`Socket` in a concurrent fashion without having to resort to threads. Polyphony
|
18
|
+
takes care of context-switching automatically whenever a blocking call like
|
19
|
+
`Socket#accept` or `IO#read` is issued.
|
20
|
+
|
21
|
+
## Features
|
22
|
+
|
23
|
+
* **Full-blown, integrated, high-performance HTTP 1 / HTTP 2 / WebSocket server
|
24
|
+
with TLS/SSL termination, automatic ALPN protocol selection, and body
|
25
|
+
streaming**.
|
26
|
+
* Co-operative scheduling of concurrent tasks using Ruby fibers.
|
27
|
+
* High-performance event reactor for handling I/O events and timers.
|
28
|
+
* Natural, sequential programming style that makes it easy to reason about concurrent code.
|
29
|
+
* Abstractions and constructs for controlling the execution of concurrent code:
|
30
|
+
coprocesses, supervisors, throttling, resource pools etc.
|
31
|
+
* Code can use native networking classes and libraries, growing support for
|
32
|
+
third-party gems such as `pg` and `redis`.
|
33
|
+
* Use stdlib classes such as `TCPServer` and `TCPSocket` and `Net::HTTP`.
|
34
|
+
* HTTP 1 / HTTP 2 client agent with persistent connections.
|
35
|
+
* Competitive performance and scalability characteristics, in terms of both
|
36
|
+
throughput and memory consumption.
|
37
|
+
|
38
|
+
## Prior Art
|
39
|
+
|
40
|
+
Polyphony draws inspiration from the following, in no particular order:
|
41
|
+
|
42
|
+
* [nio4r](https://github.com/socketry/nio4r/) and
|
43
|
+
[async](https://github.com/socketry/async) (Polyphony's C-extension code is
|
44
|
+
largely a spinoff of
|
45
|
+
[nio4r's](https://github.com/socketry/nio4r/tree/master/ext))
|
46
|
+
* [EventMachine](https://github.com/eventmachine/eventmachine)
|
47
|
+
* [Trio](https://trio.readthedocs.io/)
|
48
|
+
* [Erlang supervisors](http://erlang.org/doc/man/supervisor.html) (and actually,
|
49
|
+
Erlang in general)
|
50
|
+
|
51
|
+
## Going further
|
52
|
+
|
53
|
+
To learn more about using Polyphony to build concurrent applications, read the
|
54
|
+
technical overview below, or look at the [included
|
55
|
+
examples](https://github.com/digital-fabric/polyphony/tree/9e0f3b09213156bdf376ef33684ef267517f06e8/examples/README.md).
|
56
|
+
A thorough reference is forthcoming.
|
57
|
+
|
58
|
+
## Contributing to Polyphony
|
59
|
+
|
60
|
+
Issues and pull requests will be gladly accepted. Please use the git repository
|
61
|
+
at https://github.com/digital-fabric/polyphony as your primary point of
|
62
|
+
departure for contributing.
|
data/docs/summary.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# Table of contents
|
2
|
+
|
3
|
+
* [Polyphony - Easy Concurrency for Ruby](../README.md)
|
4
|
+
|
5
|
+
## Getting Started
|
6
|
+
|
7
|
+
* [Installing](getting-started/installing.md)
|
8
|
+
* [Tutorial](getting-started/tutorial.md)
|
9
|
+
|
10
|
+
## Technical overview
|
11
|
+
|
12
|
+
* [Design Principles](technical-overview/design-principles.md)
|
13
|
+
* [Concurrency the Easy Way](technical-overview/concurrency.md)
|
14
|
+
* [How Fibers are Scheduled](technical-overview/fiber-scheduling.md)
|
15
|
+
* [Exception Handling](technical-overview/exception-handling.md)
|
16
|
+
* [Frequently Asked Questions](technical-overview/faq.md)
|
17
|
+
|
18
|
+
## How To
|
19
|
+
|
20
|
+
* [Make an echo server](howto/echo-server.md)
|
21
|
+
* [Make an HTTP server](howto/http-server.md)
|
22
|
+
* [Make a Websocket server](howto/websocket-server.md)
|
23
|
+
* [Use timers](howto/timers.md)
|
24
|
+
* [Throttle recurrent operations](howto/throttle.md)
|
25
|
+
* [Cancel ongoing operations](howto/cancel.md)
|
26
|
+
* [Control coprocesses](howto/coprocesses.md)
|
27
|
+
* [Synchronize concurrent operations](howto/synchronize.md)
|
28
|
+
* [Perform CPU-bound operations](howto/cpu-bound.md)
|
29
|
+
* [Control backpressure](howto/backpressure.md)
|
30
|
+
* [Fork worker processes](howto/worker-processes.md)
|
31
|
+
|
32
|
+
## Polyphony extensions
|
33
|
+
|
34
|
+
* [Postgresql](extensions/pg)
|
35
|
+
* [Redis](extensions/redis)
|
36
|
+
* [IRB](extensions/irb)
|
37
|
+
* [Throttlers](#)
|
38
|
+
* [Resource Pools](#)
|
39
|
+
* [Synchronisation](#)
|
40
|
+
* [Web Server](user-guide/web-server.md)
|
41
|
+
* [Websocket Server](#)
|
42
|
+
* [Reactor API](#)
|
43
|
+
|
44
|
+
## API Reference
|
45
|
+
|
46
|
+
* [Polyphony::CancelScope](#)
|
47
|
+
* [Polyphony::Coprocess](#)
|
48
|
+
* [Gyro](#)
|
49
|
+
* [Gyro::Async](#)
|
50
|
+
* [Gyro::Child](#)
|
51
|
+
* [Gyro::IO](#)
|
52
|
+
* [Gyro::Timer](#)
|
53
|
+
* [Kernel](#)
|
54
|
+
* [Polyphony](#)
|
55
|
+
* [Polyphony::Mutex](#)
|
56
|
+
* [Polyphony::Pulser](#)
|
57
|
+
* [Polyphony::ResourcePool](#)
|
58
|
+
* [Polyphony::Throttler](#)
|
59
|
+
|
60
|
+
## [Contributing to Polyphony](contributing.md)
|