midori.rb 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/lib/midori/configure.rb +1 -0
- data/lib/midori/core_ext/tcp_server.rb +11 -0
- data/lib/midori/runner.rb +2 -0
- data/lib/midori/server.rb +3 -0
- data/lib/midori/version.rb +1 -1
- data/lib/midori.rb +3 -2
- metadata +4 -21
- data/tutorial/README.md +0 -11
- data/tutorial/SUMMARY.md +0 -29
- data/tutorial/advanced/custom_extensions.md +0 -0
- data/tutorial/advanced/deploying_for_production.md +0 -0
- data/tutorial/advanced/error_handling.md +0 -0
- data/tutorial/advanced/rerl.md +0 -0
- data/tutorial/advanced/scaling_project.md +0 -0
- data/tutorial/advanced/unit_testing.md +0 -0
- data/tutorial/essentials/extensions.md +0 -31
- data/tutorial/essentials/getting_started.md +0 -27
- data/tutorial/essentials/installation.md +0 -93
- data/tutorial/essentials/middlewares.md +0 -88
- data/tutorial/essentials/request_handling.md +0 -74
- data/tutorial/essentials/routing.md +0 -136
- data/tutorial/essentials/runner.md +0 -59
- data/tutorial/meta/comparison_with_other_frameworks.md +0 -0
- data/tutorial/meta/join_the_midori_community.md +0 -0
- data/tutorial/meta/next_steps.md +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0ffac6eac2b627e157f087d6c92d6e7e52f0e76af114a8a575e2e0fef512d388
|
4
|
+
data.tar.gz: 48c09ef3b224fc67f74a3eead572bf729b9110643b0f837c1034147c57eddada
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: faccb4442498bf24e101933af5b7f46c9c4f6ecf5c6f2a3fe912254b3171b3c0e8ebec73b41dc10916250aeca8e36ef5cc78e58b33e3860d8812e5b4616cc3de
|
7
|
+
data.tar.gz: 68b22b8a8a053546a1131ac67cb7201b60856d7f2012519d19e8ee40766788954079782cc4dea96233c3ba7df6fd23111f5c90b41b800f3319bac70644264151
|
data/lib/midori/configure.rb
CHANGED
@@ -0,0 +1,11 @@
|
|
1
|
+
class TCPServer
|
2
|
+
def tcp_fast_open
|
3
|
+
# macOS devices option is DIFFERENT from Linux and FreeBSD
|
4
|
+
opt = (/darwin/ =~ RUBY_PLATFORM) ? 1 : 5
|
5
|
+
# Magic number 6 may refer to Socket::SOL_TCP or Socket::IPPROTO_TCP
|
6
|
+
self.setsockopt(6, Socket::TCP_FASTOPEN, opt)
|
7
|
+
true
|
8
|
+
rescue => _e
|
9
|
+
false
|
10
|
+
end
|
11
|
+
end
|
data/lib/midori/runner.rb
CHANGED
@@ -31,6 +31,8 @@ class Midori::Runner
|
|
31
31
|
return false if running? || EventLoop.running?
|
32
32
|
@logger.info "Midori #{Midori::VERSION} is now running on #{bind}:#{port}".blue
|
33
33
|
@server = TCPServer.new(@bind, @port)
|
34
|
+
tfo = @server.tcp_fast_open if Midori::Configure.tcp_fast_open
|
35
|
+
@logger.warn 'Failed to use TCP Fast Open feature on your OS'.yellow unless tfo
|
34
36
|
EventLoop.register(@server, :r) do |monitor|
|
35
37
|
socket = monitor.io.accept_nonblock
|
36
38
|
connection = Midori::Connection.new(socket)
|
data/lib/midori/server.rb
CHANGED
@@ -39,6 +39,9 @@ module Midori::Server
|
|
39
39
|
@request.parse(data)
|
40
40
|
receive_new_request if @request.parsed && @request.body_parsed?
|
41
41
|
end
|
42
|
+
rescue EOFError, Errno::ENOTCONN => _e
|
43
|
+
close_connection
|
44
|
+
# Ignore client's disconnection
|
42
45
|
rescue => e
|
43
46
|
close_connection
|
44
47
|
@logger.warn "#{@request.ip} - - #{e.class} #{e.backtrace.join("\n")}".yellow
|
data/lib/midori/version.rb
CHANGED
data/lib/midori.rb
CHANGED
@@ -10,10 +10,11 @@ require 'socket'
|
|
10
10
|
|
11
11
|
require_relative 'midori_ext'
|
12
12
|
require_relative 'midori/core_ext/configurable'
|
13
|
-
require_relative 'midori/core_ext/http_header'
|
14
|
-
require_relative 'midori/core_ext/string'
|
15
13
|
require_relative 'midori/core_ext/define_class'
|
14
|
+
require_relative 'midori/core_ext/http_header'
|
16
15
|
require_relative 'midori/core_ext/proc'
|
16
|
+
require_relative 'midori/core_ext/string'
|
17
|
+
require_relative 'midori/core_ext/tcp_server'
|
17
18
|
|
18
19
|
require_relative 'midori/version'
|
19
20
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: midori.rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- HeckPsi Lab
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: murasaki
|
@@ -91,6 +91,7 @@ files:
|
|
91
91
|
- lib/midori/core_ext/http_header.rb
|
92
92
|
- lib/midori/core_ext/proc.rb
|
93
93
|
- lib/midori/core_ext/string.rb
|
94
|
+
- lib/midori/core_ext/tcp_server.rb
|
94
95
|
- lib/midori/env.rb
|
95
96
|
- lib/midori/eventsource.rb
|
96
97
|
- lib/midori/exception.rb
|
@@ -105,24 +106,6 @@ files:
|
|
105
106
|
- lib/midori/version.rb
|
106
107
|
- lib/midori/websocket.rb
|
107
108
|
- midori.sublime-project
|
108
|
-
- tutorial/README.md
|
109
|
-
- tutorial/SUMMARY.md
|
110
|
-
- tutorial/advanced/custom_extensions.md
|
111
|
-
- tutorial/advanced/deploying_for_production.md
|
112
|
-
- tutorial/advanced/error_handling.md
|
113
|
-
- tutorial/advanced/rerl.md
|
114
|
-
- tutorial/advanced/scaling_project.md
|
115
|
-
- tutorial/advanced/unit_testing.md
|
116
|
-
- tutorial/essentials/extensions.md
|
117
|
-
- tutorial/essentials/getting_started.md
|
118
|
-
- tutorial/essentials/installation.md
|
119
|
-
- tutorial/essentials/middlewares.md
|
120
|
-
- tutorial/essentials/request_handling.md
|
121
|
-
- tutorial/essentials/routing.md
|
122
|
-
- tutorial/essentials/runner.md
|
123
|
-
- tutorial/meta/comparison_with_other_frameworks.md
|
124
|
-
- tutorial/meta/join_the_midori_community.md
|
125
|
-
- tutorial/meta/next_steps.md
|
126
109
|
homepage: https://github.com/midori-rb/midori.rb
|
127
110
|
licenses:
|
128
111
|
- MIT
|
@@ -149,7 +132,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
149
132
|
version: '0'
|
150
133
|
requirements: []
|
151
134
|
rubyforge_project:
|
152
|
-
rubygems_version: 2.
|
135
|
+
rubygems_version: 2.7.3
|
153
136
|
signing_key:
|
154
137
|
specification_version: 4
|
155
138
|
summary: High performance ruby web framework
|
data/tutorial/README.md
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
# Introduction
|
2
|
-
|
3
|
-
## What is midori?
|
4
|
-
|
5
|
-
Midori (pronounced /miːdɒliː/) is a **Ruby web framework** for building APIs, web pages and realtime web services. Midori is designed to provide **non-blocking** I/O operations without **callback hells** on web development. The core library is focused on network I/Os, and gives a very easy DSL to pick up and converting existed projects on. On the other hand, midori also officially provides extension libraries that could deal with file, database, cache, network requests and other I/O operations without blocking.
|
6
|
-
|
7
|
-
If you want to know how midori compares to other libraries/frameworks, checkout out the [Comparison with Other Frameworks](meta/comparison_with_other_frameworks.md)
|
8
|
-
|
9
|
-
## Note
|
10
|
-
|
11
|
-
The official guide assumes intermediate level knowledge of Ruby and backend development. If you are totally new , it might not be the best idea to jump right into a framework as your first step - grasp the basics then come back! Prior experience with other frameworks like Rails helps, but is not required.
|
data/tutorial/SUMMARY.md
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
# Summary
|
2
|
-
|
3
|
-
## Essentials
|
4
|
-
|
5
|
-
* [Introduction](README.md)
|
6
|
-
* [Installation](essentials/installation.md)
|
7
|
-
* [Getting Started](essentials/getting_started.md)
|
8
|
-
* [Routing](essentials/routing.md)
|
9
|
-
* [Request Handling](essentials/request_handling.md)
|
10
|
-
* [Runner](essentials/runner.md)
|
11
|
-
* [Middlewares](essentials/middlewares.md)
|
12
|
-
* [Extensions](essentials/extensions.md)
|
13
|
-
|
14
|
-
|
15
|
-
## Advanced
|
16
|
-
|
17
|
-
- [Error Handling](advanced/error_handling.md)
|
18
|
-
- [Request-Eval-Response Loop](advanced/rerl.md)
|
19
|
-
- [Custom Extensions](advanced/custom_extensions.md)
|
20
|
-
- [Scaling Project](advanced/scaling_project.md)
|
21
|
-
- [Unit Testing](advanced/unit_testing.md)
|
22
|
-
- [Deploying for Production](advanced/deploying_for_production.md)
|
23
|
-
|
24
|
-
## Meta
|
25
|
-
|
26
|
-
- [Comparison with Other Frameworks](meta/comparison_with_other_frameworks.md)
|
27
|
-
- [Next Steps](meta/next_steps.md)
|
28
|
-
- [Join the Midori Community](meta/join_the_midori_community.md)
|
29
|
-
|
File without changes
|
File without changes
|
File without changes
|
data/tutorial/advanced/rerl.md
DELETED
File without changes
|
File without changes
|
File without changes
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# Extensions
|
2
|
-
|
3
|
-
Extensions are rubygems that could combine other gems with midori through meta-programming.
|
4
|
-
There's a set of officially supported midori extensions called `midori-contrib`.
|
5
|
-
This contains gems commonly used like Database ORM, Redis Driver, Redis ORM, HTTP Driver, etc.
|
6
|
-
|
7
|
-
To include it inside your project, be sure to get the original gem installed without require it.
|
8
|
-
Then include specific parts of `midori-contrib` to make it work.
|
9
|
-
|
10
|
-
For example:
|
11
|
-
|
12
|
-
`Gemfile`
|
13
|
-
|
14
|
-
```ruby
|
15
|
-
source 'https://rubygems.org'
|
16
|
-
|
17
|
-
gem 'bundler', '~> 1.0'
|
18
|
-
gem 'rake', '~> 12.0'
|
19
|
-
|
20
|
-
gem 'hiredis', '~> 0.6.0', require: false
|
21
|
-
gem 'ohm', '~> 3.0'
|
22
|
-
gem 'sequel', '~> 5.0', require: false
|
23
|
-
gem 'mysql2', '~> 0.4', require: false
|
24
|
-
|
25
|
-
gem 'em-midori', '~> 0.4.3', require: 'midori'
|
26
|
-
gem 'midori-contrib', '~> 0.1.0', require: %w(
|
27
|
-
midori-contrib
|
28
|
-
midori-contrib/sequel/mysql2
|
29
|
-
midori-contrib/redic
|
30
|
-
)
|
31
|
-
```
|
@@ -1,27 +0,0 @@
|
|
1
|
-
# Getting Started
|
2
|
-
|
3
|
-
## Hello Midori
|
4
|
-
|
5
|
-
midori is a [DSL](https://en.wikipedia.org/wiki/Domain-specific_language) for web and API development in Ruby with minimal effort:
|
6
|
-
|
7
|
-
```ruby
|
8
|
-
# hello_midori.rb
|
9
|
-
require 'midori'
|
10
|
-
|
11
|
-
class HelloWorldAPI < Midori::API
|
12
|
-
get '/' do
|
13
|
-
'Ohayou Midori'
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
Midori::Runner.new(HelloWorldAPI).start
|
18
|
-
```
|
19
|
-
|
20
|
-
Run with
|
21
|
-
|
22
|
-
```
|
23
|
-
$ ruby hello_midori.rb
|
24
|
-
```
|
25
|
-
|
26
|
-
View at: http://127.0.0.1:8080 with your browser, if you see a page showing: **Ohayou Midori**. You've made your first application with midori.
|
27
|
-
|
@@ -1,93 +0,0 @@
|
|
1
|
-
# Installation
|
2
|
-
|
3
|
-
## Requirements
|
4
|
-
|
5
|
-
Open up a command line prompt. Any commands prefaced with a dollar sign `$` should be run in the command line. Verify that you have a current version of Ruby installed:
|
6
|
-
|
7
|
-
```
|
8
|
-
$ ruby -v
|
9
|
-
ruby 2.4.1p111
|
10
|
-
```
|
11
|
-
|
12
|
-
Generally, midori supports the following ruby interpreters:
|
13
|
-
|
14
|
-
- Ruby (MRI) **>= 2.2.6**
|
15
|
-
|
16
|
-
For every version released, it would be tested and **officially ensured** in the following environments:
|
17
|
-
|
18
|
-
- Ruby (MRI)
|
19
|
-
- 2.2.8
|
20
|
-
- 2.3.5
|
21
|
-
- 2.4.2
|
22
|
-
|
23
|
-
**Note: **
|
24
|
-
|
25
|
-
- **For JRuby users, due to some C extensions used in midori, it is still unable to run on the current version of JRuby.**
|
26
|
-
- **For macOS users, you may meet performance problem due to the issue of [nio4r](https://github.com/socketry/nio4r/issues/125). Very few people would use macOS in production, so this issue may not affect much. We would still be working hard on fixing it, but the issue wouldn't be a high priority one.**
|
27
|
-
|
28
|
-
It's hard to say that if it is possible for running on other ruby implementations like Rubinius or RubyMotion, if you're in favor of supporting more ruby implementations, you could open a ticket [here](https://github.com/midori-rb/midori.rb/issues), and we are glad to discuss it.
|
29
|
-
|
30
|
-
## Install with RubyGems
|
31
|
-
|
32
|
-
```
|
33
|
-
$ gem install em-midori
|
34
|
-
Successfully installed em-midori-0.4.3
|
35
|
-
1 gem installed
|
36
|
-
```
|
37
|
-
|
38
|
-
To test whether it has installed properly, run:
|
39
|
-
|
40
|
-
```
|
41
|
-
$ ruby -r "midori" -e "class A < Midori::API;end;Midori::Runner.new(A).start"
|
42
|
-
```
|
43
|
-
|
44
|
-
If you see the following message, then everything now works fine.
|
45
|
-
|
46
|
-
```
|
47
|
-
Midori 0.4.3 is now running on 127.0.0.1:8080
|
48
|
-
```
|
49
|
-
|
50
|
-
## Use Bundler
|
51
|
-
|
52
|
-
Example `Gemfile` of basic usage as following:
|
53
|
-
|
54
|
-
```ruby
|
55
|
-
source 'https://rubygems.org'
|
56
|
-
gem 'bundler', '~> 1.0'
|
57
|
-
gem 'em-midori', '~> 0.4', require: 'midori'
|
58
|
-
```
|
59
|
-
|
60
|
-
and then running:
|
61
|
-
|
62
|
-
```
|
63
|
-
$ bundle install
|
64
|
-
```
|
65
|
-
|
66
|
-
You could use
|
67
|
-
|
68
|
-
```ruby
|
69
|
-
require 'bundler'
|
70
|
-
Bundler.require
|
71
|
-
```
|
72
|
-
|
73
|
-
in your entrance ruby file.
|
74
|
-
|
75
|
-
To include built-in extensions of midori you could make your `Gemfile` like:
|
76
|
-
|
77
|
-
```ruby
|
78
|
-
source 'https://rubygems.org'
|
79
|
-
gem 'bundler', '~> 1.0'
|
80
|
-
gem 'em-midori', '~> 0.4', require: 'midori'
|
81
|
-
gem 'midori-contrib', '~> 0.0.1', require: %w'midori-contrib/file midori-contrib/sequel/mysql2'
|
82
|
-
```
|
83
|
-
|
84
|
-
Using bunlder could make dependency management much easier, which helps a lot in scaling project. To learn more about bundler, you could see docs [here](http://bundler.io/docs.html).
|
85
|
-
|
86
|
-
## For Developers in China
|
87
|
-
|
88
|
-
You may probably meet problems with rubygems due to unstable overseas internet connection issues in China. The most popular way to solve it is to use mirror provided by [RubyChina](https://gems.ruby-china.org/) or [TUNA](https://mirror.tuna.tsinghua.edu.cn/help/rubygems/) as your gem source. This may have some side effects in development, because there's a few minutes' delay in receiving gem updates.
|
89
|
-
|
90
|
-
Alternatively, you could use proxy to connect to the main repository directly to avoid the delay problem. But using proxy is a little too complex in production environment.
|
91
|
-
|
92
|
-
Choose the solution better fits your requirements. Mixing the solutions like using proxy in development and using mirror in production is also a good choice.
|
93
|
-
|
@@ -1,88 +0,0 @@
|
|
1
|
-
# Middlewares
|
2
|
-
|
3
|
-
Middlewares are very exciting features midori support.
|
4
|
-
As it has been implemented for lots of web frameworks.
|
5
|
-
Middlewares from midori behaves very different from other frameworks, which greatly helps reducing complexity and improving performance in scaling projects.
|
6
|
-
|
7
|
-
## Basic Usage
|
8
|
-
|
9
|
-
To begin with, inheritate the `Midori::Middleware` class. Here's an example:
|
10
|
-
|
11
|
-
```ruby
|
12
|
-
class JSONMiddleware < Midori::Middleware
|
13
|
-
def before(request)
|
14
|
-
request.body = JSON.parse(request.body) unless request.body == ''
|
15
|
-
request
|
16
|
-
end
|
17
|
-
|
18
|
-
def after(_request, response)
|
19
|
-
response.header['Content-Type'] = 'application/json'
|
20
|
-
response.body = response.body.to_json
|
21
|
-
response
|
22
|
-
end
|
23
|
-
end
|
24
|
-
```
|
25
|
-
|
26
|
-
To use middleware inside router, there're two possible ways.
|
27
|
-
One is through `use` method, which would affect all routes in the current scope.
|
28
|
-
The other is through `filter` method, which would affect the following route definition only.
|
29
|
-
|
30
|
-
Here are some examples.
|
31
|
-
|
32
|
-
```ruby
|
33
|
-
class API < Midori::API
|
34
|
-
use AMiddleware
|
35
|
-
|
36
|
-
filter BMiddleware
|
37
|
-
get '/' do
|
38
|
-
# Both AMiddleware and BMiddleware works here.
|
39
|
-
'Hello'
|
40
|
-
end
|
41
|
-
|
42
|
-
get '/a' do
|
43
|
-
# Only AMiddleware is involved here.
|
44
|
-
'World'
|
45
|
-
end
|
46
|
-
end
|
47
|
-
```
|
48
|
-
|
49
|
-
## Stack-less Design
|
50
|
-
|
51
|
-
For rack users, middlewares are always considered as parts of stack.
|
52
|
-
Deep stacks may cause several performance issues in Ruby, including increasing cost when context switching, thread switching and process forking, etc.
|
53
|
-
For frameworks like Rails, it defaulty contains lots of middlewares which enlarge this problem.
|
54
|
-
|
55
|
-
In midori, middlewares are no longer stack-based.
|
56
|
-
It uses a loop-based system to run middleware code.
|
57
|
-
This makes using of middlewares with less side effects.
|
58
|
-
|
59
|
-
## Early Exit Feature
|
60
|
-
|
61
|
-
Early exit feature is also supported in midori without stack.
|
62
|
-
To make it happen, just respond an `Midori::Response` object during request processing.
|
63
|
-
Here's an example for CORS middleware using early exit feature.
|
64
|
-
|
65
|
-
```ruby
|
66
|
-
class CorsMiddleware < Midori::Middleware
|
67
|
-
def before(request)
|
68
|
-
if request.method == :OPTIONS
|
69
|
-
# PREFLIGHT
|
70
|
-
return Midori::Response.new(
|
71
|
-
header: {
|
72
|
-
'Access-Control-Allow-Origin': request.header['Origin'],
|
73
|
-
'Access-Control-Request-Headers': 'Token',
|
74
|
-
'Access-Control-Allow-Headers': 'Token',
|
75
|
-
'Access-Control-Allow-Methods': 'OPTIONS, POST, PUT, DELETE'
|
76
|
-
}
|
77
|
-
)
|
78
|
-
else
|
79
|
-
request
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def after(request, response)
|
84
|
-
response.header['Access-Control-Allow-Origin'] = request.header['Origin']
|
85
|
-
response
|
86
|
-
end
|
87
|
-
end
|
88
|
-
```
|
@@ -1,74 +0,0 @@
|
|
1
|
-
# Request Handling
|
2
|
-
|
3
|
-
## Accessing the request object
|
4
|
-
|
5
|
-
The incoming request object can be accessed from request level (filter, routes, error handlers) through the `request` method:
|
6
|
-
|
7
|
-
```ruby
|
8
|
-
class ExampleAPI < Midori::API
|
9
|
-
get '/' do
|
10
|
-
request.ip # '127.0.0.1' client ip address
|
11
|
-
request.port # '8080' client port
|
12
|
-
request.method # 'GET'
|
13
|
-
request.path # '/'
|
14
|
-
request.query_string # ''
|
15
|
-
request.query_params # {} query params, parsed from query string
|
16
|
-
request.header # {} request header
|
17
|
-
request.body # request body sent by the client
|
18
|
-
request.params # {} params matched in router
|
19
|
-
request.cookie # {} cookie parsed from header
|
20
|
-
end
|
21
|
-
end
|
22
|
-
```
|
23
|
-
|
24
|
-
**Note (for sinatra users): **The `request.body` in modori is a `String` object but not a `StringIO` object.
|
25
|
-
|
26
|
-
## Construct the response object
|
27
|
-
|
28
|
-
Midori accepts the return value of the block as the response body by default.
|
29
|
-
|
30
|
-
You could edit variable `status` and `header` to construct things other than body.
|
31
|
-
|
32
|
-
You could also return a `Midori::Response` object as your response, which could override everything.
|
33
|
-
|
34
|
-
```ruby
|
35
|
-
class ExampleAPI < Midori::API
|
36
|
-
get '/case_0' do
|
37
|
-
'Hello'
|
38
|
-
# HTTP/1.1 200 OK
|
39
|
-
# Server: Midori/1.0
|
40
|
-
#
|
41
|
-
# Hello
|
42
|
-
end
|
43
|
-
|
44
|
-
get '/case_1' do
|
45
|
-
@status = 418
|
46
|
-
"I\'m a teapot"
|
47
|
-
# HTTP/1.1 418 I'm a teapot
|
48
|
-
# Server: Midori/1.0
|
49
|
-
#
|
50
|
-
# I'm a teapot
|
51
|
-
end
|
52
|
-
|
53
|
-
get '/case_2' do
|
54
|
-
@header['Example-Header'] = 'Example-Value'
|
55
|
-
'Hello'
|
56
|
-
# HTTP/1.1 200 OK
|
57
|
-
# Server: Midori/1.0
|
58
|
-
# Example-Header: Example-Value
|
59
|
-
#
|
60
|
-
# Hello
|
61
|
-
end
|
62
|
-
|
63
|
-
get '/case_3' do
|
64
|
-
@status = 202
|
65
|
-
@header['Example-Header'] = 'Example-Value'
|
66
|
-
Midori::Response.new(status: 200, header: {}, body: 'Hello') # Overrides everything else
|
67
|
-
# HTTP/1.1 200 OK
|
68
|
-
# Server: Midori/1.0
|
69
|
-
#
|
70
|
-
# Hello
|
71
|
-
end
|
72
|
-
end
|
73
|
-
```
|
74
|
-
|
@@ -1,136 +0,0 @@
|
|
1
|
-
# Routing
|
2
|
-
|
3
|
-
## Basic Usage
|
4
|
-
|
5
|
-
Routes should be defined inside a class inherited from `Midori::API`. Midori doesn't support defining routes globally like sinatra to avoid scope pollution, which affects a lot in scaling project.
|
6
|
-
|
7
|
-
In midori, a route is an HTTP method with a URL-matching pattern. Each route is associated with a block:
|
8
|
-
|
9
|
-
```ruby
|
10
|
-
class ExampleAPI < Midori::API
|
11
|
-
get '/' do
|
12
|
-
#.. show something ..
|
13
|
-
end
|
14
|
-
|
15
|
-
post '/' do
|
16
|
-
#.. create something ..
|
17
|
-
end
|
18
|
-
|
19
|
-
put '/' do
|
20
|
-
#.. replace something ..
|
21
|
-
end
|
22
|
-
|
23
|
-
delete '/' do
|
24
|
-
#.. annihilate something ..
|
25
|
-
end
|
26
|
-
|
27
|
-
options '/' do
|
28
|
-
#.. appease something ..
|
29
|
-
end
|
30
|
-
|
31
|
-
link '/' do
|
32
|
-
#.. affiliate something ..
|
33
|
-
end
|
34
|
-
|
35
|
-
unlink '/' do
|
36
|
-
#.. separate something ..
|
37
|
-
end
|
38
|
-
end
|
39
|
-
```
|
40
|
-
|
41
|
-
Routes are matched in the order they are defined. The first route that matches the request is invoked.
|
42
|
-
|
43
|
-
Midori not only supports the methods above, it supports almost every method provided in RFC standards. You could look it up in [API doc](http://www.rubydoc.info/gems/em-midori/Midori/API) for more details.
|
44
|
-
|
45
|
-
## Params
|
46
|
-
|
47
|
-
Routes patterns may include named parameters, accessible via the `request.params` hash:
|
48
|
-
|
49
|
-
```ruby
|
50
|
-
class ExampleAPI < Midori::API
|
51
|
-
get '/hello/:name' do
|
52
|
-
"Ohayou #{request.params['name']}"
|
53
|
-
end
|
54
|
-
end
|
55
|
-
```
|
56
|
-
|
57
|
-
Route patterns may also include splat (or wildcard) parameters, accessible via the `request.params['splat']` array:
|
58
|
-
|
59
|
-
```ruby
|
60
|
-
class ExampleAPI < Midori::API
|
61
|
-
get '/say/*/to/*' do
|
62
|
-
# matches /say/hello/to/world
|
63
|
-
request.params['splat'] # => ["hello", "world"]
|
64
|
-
end
|
65
|
-
|
66
|
-
get '/download/*.*' do
|
67
|
-
# matches /download/path/to/file.xml
|
68
|
-
request.params['splat'] # => ["path/to/file", "xml"]
|
69
|
-
end
|
70
|
-
end
|
71
|
-
```
|
72
|
-
|
73
|
-
Routes may also utilize query string:
|
74
|
-
|
75
|
-
```ruby
|
76
|
-
class ExampleAPI < Midori::API
|
77
|
-
get '/posts' do
|
78
|
-
# matches "GET /posts?title=foo&author=bar"
|
79
|
-
request.query_string # => title=foo&author=bar
|
80
|
-
end
|
81
|
-
end
|
82
|
-
```
|
83
|
-
|
84
|
-
## WebSocket & EventSource
|
85
|
-
|
86
|
-
`WebSocket` connection uses `GET` method in HTTP protocol, but indeed, it behaves totally different from `GET` requests. You don't need to care about the protocol details. In midori, you could easily manage websocket connections easily.
|
87
|
-
|
88
|
-
Here's a chatroom example using websocket in midori:
|
89
|
-
|
90
|
-
```ruby
|
91
|
-
CONNECTION_POOL = []
|
92
|
-
|
93
|
-
class ExampleAPI < Midori::API
|
94
|
-
websocket '/' do |ws|
|
95
|
-
ws.on :open do
|
96
|
-
ws.send 'Ohayo Midori'
|
97
|
-
CONNECTION_POOL << ws
|
98
|
-
end
|
99
|
-
|
100
|
-
ws.on :message do |msg|
|
101
|
-
CONNECTION_POOL.map do |client|
|
102
|
-
client.send msg
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
ws.on :close do
|
107
|
-
CONNECTION_POOL.delete(ws)
|
108
|
-
puts 'Oyasumi midori'
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
```
|
113
|
-
|
114
|
-
midori also supports `EventSource` connection as part of your route.
|
115
|
-
|
116
|
-
Here's a chatroom example using eventsource in midori:
|
117
|
-
|
118
|
-
```ruby
|
119
|
-
CONNECTION_POOL = []
|
120
|
-
|
121
|
-
class ExampleAPI < Midori::API
|
122
|
-
post '/pub' do
|
123
|
-
clients = CONNECTION_POOL.clone
|
124
|
-
CONNECTION_POOL.clear
|
125
|
-
# EventSource connection disconnects every time message sent, DO NOT reuse connection pool
|
126
|
-
clients.map do |client|
|
127
|
-
client.send request.body
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
eventsource '/sub' do |es|
|
132
|
-
CONNECTION_POOL << es
|
133
|
-
end
|
134
|
-
end
|
135
|
-
```
|
136
|
-
|
@@ -1,59 +0,0 @@
|
|
1
|
-
# Runner
|
2
|
-
|
3
|
-
## Introdution
|
4
|
-
|
5
|
-
`Runner` is the container of midori server. You could create, start, stop midori instance by `Runner`.
|
6
|
-
|
7
|
-
`Runner` use `Midori::Configure` as its configuration by default.
|
8
|
-
|
9
|
-
## Examples
|
10
|
-
|
11
|
-
Here're some examples for common usages
|
12
|
-
|
13
|
-
### Port Binding
|
14
|
-
|
15
|
-
Start midori instance with port `4567` instead of the default `8080`.
|
16
|
-
|
17
|
-
```ruby
|
18
|
-
require 'midori'
|
19
|
-
class API < Midori::API
|
20
|
-
get '/' do
|
21
|
-
'Hello World'
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
Midori::Configure.set :port, 4567
|
26
|
-
Midori::Runner.new(API).start
|
27
|
-
```
|
28
|
-
|
29
|
-
### Address Binding
|
30
|
-
|
31
|
-
Start midori instance listening to all IP addresses.
|
32
|
-
|
33
|
-
```ruby
|
34
|
-
require 'midori'
|
35
|
-
class API < Midori::API
|
36
|
-
get '/' do
|
37
|
-
'Hello World'
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
Midori::Configure.set :bind, '0.0.0.0'
|
42
|
-
Midori::Runner.new(API).start
|
43
|
-
```
|
44
|
-
|
45
|
-
### Stop Midori
|
46
|
-
|
47
|
-
Stop midori instance when specified route been called.
|
48
|
-
|
49
|
-
```ruby
|
50
|
-
require 'midori'
|
51
|
-
$runner = nil
|
52
|
-
class API < Midori::API
|
53
|
-
get '/stop' do
|
54
|
-
$runner.stop
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
$runner = Midori::Runner.new(API).start
|
59
|
-
```
|
File without changes
|
File without changes
|
data/tutorial/meta/next_steps.md
DELETED
File without changes
|