web_pipe 0.15.1 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +10 -0
- data/README.md +13 -10
- data/docs/building_a_rack_application.md +1 -1
- data/docs/composing_applications.md +4 -4
- data/docs/connection_struct/configuring_the_connection_struct.md +4 -4
- data/docs/connection_struct/halting_the_pipe.md +17 -19
- data/docs/connection_struct/sharing_data_downstream.md +9 -8
- data/docs/connection_struct.md +22 -19
- data/docs/design_model.md +10 -9
- data/docs/dsl_free_usage.md +85 -14
- data/docs/extensions/container.md +9 -10
- data/docs/extensions/cookies.md +4 -2
- data/docs/extensions/dry_schema.md +5 -4
- data/docs/extensions/flash.md +9 -11
- data/docs/extensions/hanami_view.md +10 -14
- data/docs/extensions/params.md +6 -4
- data/docs/extensions/rails.md +28 -34
- data/docs/extensions/redirect.md +5 -4
- data/docs/extensions/router_params.md +5 -5
- data/docs/extensions/session.md +4 -4
- data/docs/extensions/url.md +6 -6
- data/docs/extensions.md +5 -6
- data/docs/introduction.md +7 -7
- data/docs/plugging_operations/composing_operations.md +3 -3
- data/docs/plugging_operations/injecting_operations.md +4 -4
- data/docs/plugging_operations/inspecting_operations.md +1 -2
- data/docs/plugging_operations/resolving_operations.md +3 -3
- data/docs/plugging_operations.md +3 -3
- data/docs/plugs/config.md +1 -1
- data/docs/plugs/content_type.md +2 -1
- data/docs/plugs.md +6 -7
- data/docs/recipes/hanami_2_and_dry_rb_integration.md +12 -0
- data/docs/recipes/hanami_router_integration.md +3 -1
- data/docs/recipes/using_all_restful_methods.md +6 -5
- data/docs/using_rack_middlewares/composing_middlewares.md +2 -3
- data/docs/using_rack_middlewares/injecting_middlewares.md +6 -6
- data/docs/using_rack_middlewares/inspecting_middlewares.md +7 -6
- data/docs/using_rack_middlewares.md +6 -6
- data/lib/web_pipe/app.rb +22 -25
- data/lib/web_pipe/conn.rb +0 -1
- data/lib/web_pipe/conn_support/builder.rb +0 -7
- data/lib/web_pipe/conn_support/composition.rb +3 -26
- data/lib/web_pipe/conn_support/errors.rb +5 -5
- data/lib/web_pipe/conn_support/headers.rb +1 -50
- data/lib/web_pipe/conn_support/types.rb +3 -3
- data/lib/web_pipe/dsl/builder.rb +10 -19
- data/lib/web_pipe/dsl/class_context.rb +15 -40
- data/lib/web_pipe/dsl/instance_context.rb +53 -0
- data/lib/web_pipe/extensions/container/container.rb +2 -15
- data/lib/web_pipe/extensions/cookies/cookies.rb +2 -31
- data/lib/web_pipe/extensions/dry_schema/dry_schema.rb +2 -56
- data/lib/web_pipe/extensions/flash/flash.rb +2 -32
- data/lib/web_pipe/extensions/hanami_view/hanami_view.rb +2 -93
- data/lib/web_pipe/extensions/not_found/not_found.rb +2 -40
- data/lib/web_pipe/extensions/params/params.rb +2 -63
- data/lib/web_pipe/extensions/rails/rails.rb +2 -119
- data/lib/web_pipe/extensions/redirect/redirect.rb +2 -20
- data/lib/web_pipe/extensions/router_params/router_params.rb +1 -39
- data/lib/web_pipe/extensions/session/session.rb +2 -25
- data/lib/web_pipe/extensions/url/url.rb +2 -5
- data/lib/web_pipe/pipe.rb +229 -0
- data/lib/web_pipe/plug.rb +30 -75
- data/lib/web_pipe/plugs/config.rb +0 -2
- data/lib/web_pipe/plugs/content_type.rb +0 -2
- data/lib/web_pipe/rack_support/app_with_middlewares.rb +3 -26
- data/lib/web_pipe/rack_support/middleware.rb +2 -2
- data/lib/web_pipe/rack_support/middleware_specification.rb +17 -55
- data/lib/web_pipe/types.rb +1 -3
- data/lib/web_pipe/version.rb +1 -1
- data/lib/web_pipe.rb +77 -21
- data/web_pipe.gemspec +1 -0
- metadata +7 -6
- data/docs/recipes/dry_rb_integration.md +0 -17
- data/lib/web_pipe/dsl/dsl_context.rb +0 -85
- data/lib/web_pipe/dsl/instance_methods.rb +0 -114
data/docs/extensions/rails.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# Rails
|
2
2
|
|
3
|
-
The first two things to keep in mind
|
3
|
+
The first two things to keep in mind to integrate with Rails are
|
4
4
|
that `WebPipe` instances are Rack applications and that rails router can
|
5
|
-
perfectly [dispatch to a rack application](https://guides.rubyonrails.org/routing.html#routing-to-rack-applications).
|
5
|
+
perfectly [dispatch to a rack application](https://guides.rubyonrails.org/routing.html#routing-to-rack-applications).
|
6
6
|
|
7
7
|
```ruby
|
8
8
|
# config/routes.rb
|
@@ -22,30 +22,29 @@ class MyRoute
|
|
22
22
|
end
|
23
23
|
```
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
To do something like the previous example, you don't need to enable this
|
26
|
+
extension. Notice that rails dispatched the request to our `WebPipe` rack
|
27
|
+
application, which was then responsible for generating the response. In this
|
28
|
+
case, it used a simple call to `#set_response_body`.
|
29
29
|
|
30
30
|
It's quite possible that you don't need more than that in terms of rails
|
31
|
-
integration. Of course,
|
31
|
+
integration. Of course, you want something more elaborate to generate
|
32
32
|
responses. For that, you can use the view or template system you like. One
|
33
|
-
option that will play
|
33
|
+
option that will play especially well here is
|
34
34
|
[`hanami-view`](https://github.com/hanami/view). Furthermore, we have a
|
35
35
|
tailored `hanami_view`
|
36
36
|
[extension](https://waiting-for-dev.github.io/web_pipe/docs/extensions/hanami_view.html).
|
37
37
|
|
38
|
-
You need to use `:rails` extension if:
|
38
|
+
You need to use the `:rails` extension if:
|
39
39
|
|
40
|
-
- You want to use `action_view` as rendering system.
|
41
|
-
- You want to use rails
|
40
|
+
- You want to use `action_view` as a rendering system.
|
41
|
+
- You want to use rails URL helpers from your `WebPipe` application.
|
42
42
|
- You want to use controller helpers from your `WebPipe` application.
|
43
43
|
|
44
|
-
Rails responsibilities for controlling the request/response cycle
|
45
|
-
rendering process
|
46
|
-
|
47
|
-
|
48
|
-
some behaviour for the view layer:
|
44
|
+
Rails' responsibilities for controlling the request/response cycle are coupled
|
45
|
+
to the rendering process. For this reason, even if you want to use `WebPipe`
|
46
|
+
applications instead of Rails controller actions you still have to use the
|
47
|
+
typical top `ApplicationController` to define some behavior for the view layer:
|
49
48
|
|
50
49
|
- Which layout is applied to the template.
|
51
50
|
- Which helpers will become available to the templates.
|
@@ -55,11 +54,11 @@ no layout is applied and only built-in helpers (for example,
|
|
55
54
|
`number_as_currency`) are available. You can change it via the
|
56
55
|
`:rails_controller` configuration option.
|
57
56
|
|
58
|
-
The main method that this extension adds to `WebPipe::Conn` is `#render`,
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
57
|
+
The main method that this extension adds to `WebPipe::Conn` is `#render`, which
|
58
|
+
delegates to the [Rails implementation]
|
59
|
+
(https://api.rubyonrails.org/v6.0.1/classes/ActionController/Renderer.html) as
|
60
|
+
you'd do in a typical rails controller. Remember that you can provide template
|
61
|
+
instance variables through the keyword `:assigns`.
|
63
62
|
|
64
63
|
```ruby
|
65
64
|
# config/routes.rb
|
@@ -92,10 +91,10 @@ end
|
|
92
91
|
```
|
93
92
|
|
94
93
|
Notice that we used the keyword `template:` instead of taking advantage of
|
95
|
-
automatic template lookup. We did that way so that we don't have to create
|
96
|
-
|
97
|
-
`ArticlesController
|
98
|
-
|
94
|
+
automatic template lookup. We did that way so that we don't have to create an
|
95
|
+
`ArticlesController`, but it's up to you. In the case of having an
|
96
|
+
`ArticlesController`, we could do `conn.render(:index, assigns: { articles:
|
97
|
+
Article.all })`.
|
99
98
|
|
100
99
|
Besides, this extension provides with two other methods:
|
101
100
|
|
@@ -104,12 +103,7 @@ Besides, this extension provides with two other methods:
|
|
104
103
|
- `helpers` returns the associated [controller
|
105
104
|
helpers](https://api.rubyonrails.org/classes/ActionController/Helpers.html).
|
106
105
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
Here you have a link to a very simple and contrived example of a rails
|
112
|
-
application integrating `web_pipe`:
|
113
|
-
|
114
|
-
https://github.com/waiting-for-dev/rails-web_pipe
|
115
|
-
|
106
|
+
We have placed `WebPipe` applications within `app/controllers/` directory in
|
107
|
+
all the examples. However, remember you can put them wherever you like as long
|
108
|
+
as you respect rails
|
109
|
+
[`autoload_paths`](https://guides.rubyonrails.org/autoloading_and_reloading_constants.html#autoload-paths).
|
data/docs/extensions/redirect.md
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
# Redirect
|
2
2
|
|
3
|
-
This extension helps
|
3
|
+
This extension helps create a redirect response.
|
4
4
|
|
5
5
|
Redirect responses consist of two pieces:
|
6
6
|
|
7
|
-
- `Location` response header with the URL to which browsers should
|
7
|
+
- The `Location` response header with the URL to which browsers should
|
8
|
+
redirect.
|
8
9
|
- A 3xx status code.
|
9
10
|
|
10
|
-
A `#redirect(location, code)` method is added to `WebPipe::Conn
|
11
|
-
care of both steps. `code` argument is optional, defaulting to `302`.
|
11
|
+
A `#redirect(location, code)` method is added to `WebPipe::Conn`, which takes
|
12
|
+
care of both steps. The `code` argument is optional, defaulting to `302`.
|
12
13
|
|
13
14
|
```ruby
|
14
15
|
require 'web_pipe'
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# Router params
|
2
2
|
|
3
|
-
This extension can be used
|
3
|
+
This extension can be used to merge placeholder parameters
|
4
4
|
that usually routers support (like `get /users/:id`) to the parameters hash
|
5
|
-
added through [`:params` extension](params.md) (which is
|
6
|
-
automatically loaded).
|
5
|
+
added through the [`:params` extension](params.md) (which is
|
6
|
+
automatically loaded if using `:router_params`).
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
This extension adds a transformation function named `:router_params`to the
|
9
|
+
registry. Internally, it merges what is present in rack env's
|
10
10
|
`router.params` key.
|
11
11
|
|
12
12
|
It automatically integrates with
|
data/docs/extensions/session.md
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# Session
|
2
2
|
|
3
|
-
Wrapper around `Rack::Session` middleware to help
|
4
|
-
|
3
|
+
Wrapper around `Rack::Session` middleware to help work with sessions in your
|
4
|
+
plugged operations.
|
5
5
|
|
6
|
-
It depends on `Rack::Session` middleware, which is shipped by rack.
|
6
|
+
It depends on the `Rack::Session` middleware, which is shipped by rack.
|
7
7
|
|
8
|
-
It adds following methods to `WebPipe::Conn`:
|
8
|
+
It adds the following methods to `WebPipe::Conn`:
|
9
9
|
|
10
10
|
- `#fetch_session(key)`, `#fetch_session(key, default)` or
|
11
11
|
`#fetch_session(key) { default }`. Returns what is stored under
|
data/docs/extensions/url.md
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# URL
|
2
2
|
|
3
|
-
`:url` extension
|
4
|
-
|
3
|
+
The `:url` extension adds a few methods that process the raw URL information
|
4
|
+
into something more digestable.
|
5
5
|
|
6
6
|
Specifically, it adds:
|
7
7
|
|
8
|
-
- `#base_url`:
|
9
|
-
- `#path`:
|
10
|
-
- `#full_path`:
|
11
|
-
- `#url`:
|
8
|
+
- `#base_url`: That's schema + host + port (unless it is the default for the scheme). E.g. `'https://example.org'` or `'http://example.org:8000'`.
|
9
|
+
- `#path`: That's script name (if any) + path information. E.g. `'index.rb/users/1'` or `'users/1'`.
|
10
|
+
- `#full_path`: That's path + query string (if any). E.g. `'users/1?view=table'`.
|
11
|
+
- `#url`: That's base url + full path. E.g. `'http://example.org:8000/users/1?view=table'`.
|
data/docs/extensions.md
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
# Extensions
|
2
2
|
|
3
|
-
`WebPipe::Conn` features are by default
|
4
|
-
|
5
|
-
|
6
|
-
want to use.
|
3
|
+
`WebPipe::Conn` features are bare-bones by default: the very minimal you need
|
4
|
+
to be able to build a web application. However, there are several extensions to
|
5
|
+
add just the ingredients you want to use progressively.
|
7
6
|
|
8
|
-
|
9
|
-
|
7
|
+
To load the extensions, you have to call `#load_extensions` method in
|
8
|
+
`WebPipe`:
|
10
9
|
|
11
10
|
```ruby
|
12
11
|
WebPipe.load_extensions(:params, :cookies)
|
data/docs/introduction.md
CHANGED
@@ -6,10 +6,10 @@ It means that with it and a rack router (like
|
|
6
6
|
[`hanami-router`](https://github.com/hanami/router),
|
7
7
|
[`http_router`](https://github.com/joshbuddy/http_router) or plain
|
8
8
|
[rack](https://github.com/rack/rack) routing methods you can build a complete
|
9
|
-
web application. However, the idea behind `web_pipe` is
|
10
|
-
component within a web framework. For this reason, it plays
|
11
|
-
with [dry-rb](https://dry-rb.org/) ecosystem. If it helps, you
|
12
|
-
as a decoupled web controller (as the C in MVC).
|
9
|
+
web application. However, the idea behind `web_pipe` is for it to be a
|
10
|
+
decoupled component within a web framework. For this reason, it plays
|
11
|
+
extremely well with [dry-rb](https://dry-rb.org/) ecosystem. If it helps, you
|
12
|
+
can think of it as a decoupled web controller (as the C in MVC).
|
13
13
|
|
14
14
|
`web_pipe` applications are built as a [pipe of
|
15
15
|
operations](design_model.md) on an [immutable
|
@@ -28,9 +28,9 @@ Following there is a simple example. It is a web application that will check
|
|
28
28
|
the value of a `user` parameter. When it is `Alice` or `Joe`, it will kindly
|
29
29
|
say hello. Otherwise, it will unauthorize:
|
30
30
|
|
31
|
-
>
|
32
|
-
|
33
|
-
will be available
|
31
|
+
> To try this example, you can paste it to a file with the name `config.ru` and
|
32
|
+
launch the rack command `rackup` within the same directory. The application
|
33
|
+
will be available at `http://localhost:9292`.
|
34
34
|
|
35
35
|
```ruby
|
36
36
|
require 'web_pipe'
|
@@ -5,9 +5,9 @@ and returning a connection struct. As a result, a composition of operations is
|
|
5
5
|
an operation in itself (as it also takes a connection struct and returns a
|
6
6
|
connection struct).
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
composition of all operations for given application.
|
8
|
+
We can leverage that to plug a whole `web_pipe` application as an operation to
|
9
|
+
another application. By doing so, you are plugging an operation which is the
|
10
|
+
composition of all operations for a given application.
|
11
11
|
|
12
12
|
```ruby
|
13
13
|
class HtmlApp
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# Injecting operations
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
You can inject operations at the moment an application is initialized. It
|
4
|
+
allows you to override what the definition declares.
|
5
5
|
|
6
6
|
To this effect, you must use `plugs:` keyword argument. It must be a hash where
|
7
|
-
operations are matched by the name you gave them in its definition.
|
7
|
+
the operations are matched by the name you gave them in its definition.
|
8
8
|
|
9
|
-
|
9
|
+
That is mainly useful for testing purposes, where you can switch a heavy
|
10
10
|
operation and use another lighter one.
|
11
11
|
|
12
12
|
In the following example, the response body of the application will be
|
@@ -1,11 +1,10 @@
|
|
1
1
|
# Inspecting operations
|
2
2
|
|
3
|
-
Once a `WebPipe` class is initialized all its operations get resolved. It
|
3
|
+
Once a `WebPipe` class is initialized, all its operations get resolved. It
|
4
4
|
happens because they are whether [resolved](resolving_operations.md) or
|
5
5
|
[injected](injecting_operations.md). The final result can be accessed through
|
6
6
|
the `#operations` method:
|
7
7
|
|
8
|
-
|
9
8
|
```ruby
|
10
9
|
require 'web_pipe'
|
11
10
|
require 'web_pipe/conn_support/builder'
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Resolving operations
|
2
2
|
|
3
|
-
There are several ways you can specify how an operation
|
3
|
+
There are several ways you can specify how to resolve an operation.
|
4
4
|
|
5
5
|
## Instance method
|
6
6
|
|
@@ -53,8 +53,8 @@ end
|
|
53
53
|
Operations can be resolved from a dependency injection container.
|
54
54
|
|
55
55
|
A container is anything that responds to `#[]` (accepting `Symbol` or `String`
|
56
|
-
as argument)
|
57
|
-
moment `WebPipe` module
|
56
|
+
as argument) to resolve a dependency. It can be configured at the
|
57
|
+
moment you include the `WebPipe` module:
|
58
58
|
|
59
59
|
```ruby
|
60
60
|
MyContainer = Hash[
|
data/docs/plugging_operations.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# Plugging operations
|
2
2
|
|
3
|
-
You can plug operations
|
3
|
+
You can plug operations into your application with the DSL method `plug`. The
|
4
4
|
first argument it always takes is a symbol with the name you want
|
5
5
|
to give to the operation (which is needed to allow
|
6
|
-
[injection](plugging_operations/injecting_operations.md)
|
7
|
-
initialization).
|
6
|
+
[injection](plugging_operations/injecting_operations.md) at
|
7
|
+
initialization time).
|
8
8
|
|
9
9
|
```ruby
|
10
10
|
class MyApp
|
data/docs/plugs/config.md
CHANGED
data/docs/plugs/content_type.md
CHANGED
data/docs/plugs.md
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
# Plugs
|
2
2
|
|
3
|
-
Some
|
3
|
+
Some groups of operations can be generalized as following the same pattern. For
|
4
4
|
example, an operation setting `Content-Type` header to `text/html` is very
|
5
|
-
similar to
|
6
|
-
|
7
|
-
|
8
|
-
functions.
|
5
|
+
similar to setting the same header to `application/json`. We name plugs to this
|
6
|
+
level of abstraction on top of operations: plugs are operation builders. In
|
7
|
+
other words, they are higher-order functions that return functions.
|
9
8
|
|
10
|
-
Being just functions, we take as convention that plugs respond to `#call`
|
11
|
-
|
9
|
+
Being just functions, we take as a convention that plugs respond to `#call` to
|
10
|
+
create an operation.
|
12
11
|
|
13
12
|
This library ships with some useful plugs.
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# Hanami 2 and dry-rb integration
|
2
|
+
|
3
|
+
`web_pipe` has been designed to integrate smoothly with
|
4
|
+
the [hanami](https://hanamirb.org/) & [dry-rb](https://dry-rb.org/) ecosystems. It shares the same design
|
5
|
+
principles, and it ships with some extensions that even make this
|
6
|
+
integration painless (like [`:dry-schema`](../extensions/dry_schema.md)
|
7
|
+
extension or [`:hanami_view`](../extensions/hanami_view.md)).
|
8
|
+
|
9
|
+
If you want to use `web_pipe` within a hanami 2 application, you can take
|
10
|
+
inspiration from this sample todo app:
|
11
|
+
|
12
|
+
https://github.com/waiting-for-dev/hanami_2_web_pipe_todo_app
|
@@ -22,4 +22,6 @@ end
|
|
22
22
|
run router
|
23
23
|
```
|
24
24
|
|
25
|
-
|
25
|
+
To perform [string matching with
|
26
|
+
variables](https://github.com/hanami/router#string-matching-with-variables) you
|
27
|
+
just need to load [`:router_params` extension](../extensions/router_params.md).
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Using all RESTful methods
|
2
2
|
|
3
|
-
As you probably know,
|
3
|
+
As you probably know, most browsers don't support some RESTful
|
4
4
|
methods like `PATCH` or `PUT`. [Rack's `MethodOverride`
|
5
5
|
middleware](https://github.com/rack/rack/blob/master/lib/rack/method_override.rb)
|
6
6
|
provides a workaround for this limitation, allowing to override
|
@@ -9,12 +9,13 @@ request method in rack's env if a magical `_method` parameter or
|
|
9
9
|
|
10
10
|
You have to be aware that if you use this middleware within a
|
11
11
|
`web_pipe` application (through [`use` DSL
|
12
|
-
method](../using_rack_middlewares.md)) it will have no effect.
|
13
|
-
When your `web_pipe` application takes control of the request it
|
14
|
-
has already gone through the router, which is the one
|
12
|
+
method](../using_rack_middlewares.md)), it will have no effect.
|
13
|
+
When your `web_pipe` application takes control of the request, it
|
14
|
+
has already gone through the router, which is the one that should
|
15
15
|
read the request method set by rack.
|
16
16
|
|
17
|
-
The solution for this is
|
17
|
+
The solution for this is straightforward. Just use `MethodOverride` middleware
|
18
|
+
before your router does its work. For example, in `config.ru`:
|
18
19
|
|
19
20
|
```ruby
|
20
21
|
# config.ru
|
@@ -3,9 +3,8 @@
|
|
3
3
|
In a similar way that you compose plugged operations, you can also compose rack
|
4
4
|
middlewares from another application.
|
5
5
|
|
6
|
-
For that, you just need to `use` another application.
|
7
|
-
|
8
|
-
they had there.
|
6
|
+
For that, you just need to `use` another application. All the middlewares for
|
7
|
+
that application will be added to the stack in the same order.
|
9
8
|
|
10
9
|
```ruby
|
11
10
|
class HtmlApp
|
@@ -1,19 +1,19 @@
|
|
1
1
|
# Injecting middlewares
|
2
2
|
|
3
|
-
|
3
|
+
You can inject middlewares at the moment an application is initialized,
|
4
4
|
allowing you to override what you have defined in the DSL.
|
5
5
|
|
6
|
-
For that purpose, you have to use `middlewares:` keyword argument. It must be a
|
6
|
+
For that purpose, you have to use the `middlewares:` keyword argument. It must be a
|
7
7
|
hash where middlewares are matched by the name you gave them in its definition.
|
8
8
|
|
9
|
-
A middleware must be specified as an `Array`.
|
10
|
-
middleware class. The rest of arguments (if any) should be any
|
9
|
+
A middleware must be specified as an `Array`. The first item must be a rack
|
10
|
+
middleware class. The rest of the arguments (if any) should be any options it may
|
11
11
|
need.
|
12
12
|
|
13
|
-
|
13
|
+
That is mainly useful for testing purposes, where you can switch a heavy
|
14
14
|
middleware and use a mocked one instead.
|
15
15
|
|
16
|
-
In the following example, rack session mechanism
|
16
|
+
In the following example, we mock the rack session mechanism:
|
17
17
|
|
18
18
|
```ruby
|
19
19
|
# config.ru
|
@@ -1,15 +1,16 @@
|
|
1
1
|
# Inspecting middlewares
|
2
2
|
|
3
|
-
Once a `WebPipe` class is initialized all its middlewares get resolved.
|
4
|
-
can
|
3
|
+
Once a `WebPipe` class is initialized, all its middlewares get resolved. You
|
4
|
+
can access them through the `#middlewares` method.
|
5
5
|
|
6
6
|
Each middleware is represented by a
|
7
7
|
`WebPipe::RackSupport::MiddlewareSpecification` instance, which contains two
|
8
|
-
accessors: `middleware` returns the middleware class,
|
9
|
-
an array with the arguments
|
8
|
+
accessors: `middleware` returns the middleware class. In contrast, `options`
|
9
|
+
returns an array with the arguments provided to the middleware on
|
10
|
+
initialization.
|
10
11
|
|
11
|
-
|
12
|
-
can
|
12
|
+
Keep in mind that every middleware is resolved as an array. That is because it
|
13
|
+
can be composed by a chain of middlewares built through
|
13
14
|
[composition](composing_middlewares.md).
|
14
15
|
|
15
16
|
|
@@ -1,16 +1,16 @@
|
|
1
1
|
# Using rack middlewares
|
2
2
|
|
3
3
|
A one-way pipe like the one `web_pipe` implements can deal with any required
|
4
|
-
feature in a web application. However, usually it is convenient to
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
feature in a web application. However, usually, it is convenient to use some
|
5
|
+
well-known rack middleware, so you don't have to reinvent the wheel. Even if
|
6
|
+
you can add them to the router layer, `web_pipe` allows you to encapsulate them
|
7
|
+
in your application definition.
|
8
8
|
|
9
|
-
|
9
|
+
To add rack middlewares to the stack, you have to use the DSL method
|
10
10
|
`use`. The first argument it takes is a `Symbol` with the name you want to
|
11
11
|
assign to it (which is needed to allow
|
12
12
|
[injection](using_rack_middlewares/injecting_middlewares.md) on
|
13
|
-
initialization). Then, it must follow the middleware class and any
|
13
|
+
initialization). Then, it must follow the middleware class and any options it
|
14
14
|
may need:
|
15
15
|
|
16
16
|
```ruby
|
data/lib/web_pipe/app.rb
CHANGED
@@ -1,54 +1,51 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'web_pipe/types'
|
4
3
|
require 'web_pipe/conn'
|
5
4
|
require 'web_pipe/conn_support/builder'
|
6
5
|
require 'web_pipe/conn_support/composition'
|
7
6
|
|
8
7
|
module WebPipe
|
9
|
-
# Rack
|
10
|
-
#
|
8
|
+
# Rack app built from a chain of functions that take and return a
|
9
|
+
# {WebPipe::Conn}.
|
11
10
|
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
11
|
+
# This is the abstraction encompassing a rack application built only with the
|
12
|
+
# functions on {WebPipe::Conn}. {WebPipe::RackSupport::AppWithMiddlewares}
|
13
|
+
# takes middlewares also into account.
|
15
14
|
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
# callable accepting a {Conn} and returning a {Conn}).
|
19
|
-
# - Convert last {Conn} back to a rack response and
|
20
|
-
# return it.
|
15
|
+
# A rack application is something callable that takes the rack environment as
|
16
|
+
# an argument, and returns a rack response. So, this class needs to:
|
21
17
|
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
18
|
+
# - Take rack's environment and create a {WebPipe::Conn} struct from there.
|
19
|
+
# - Starting from the initial struct, apply the pipe of functions.
|
20
|
+
# - Convert the last {WebPipe::Conn} back to a rack response.
|
21
|
+
#
|
22
|
+
# {WebPipe::Conn} can itself be of two different types (subclasses of it}:
|
23
|
+
# {Conn::Ongoing} and {Conn::Halted}. The pipe is stopped on two scenarios:
|
24
|
+
#
|
25
|
+
# - The end of the pipe is reached.
|
26
|
+
# - One function returns a {Conn::Halted}.
|
26
27
|
class App
|
27
|
-
# Type for a rack environment.
|
28
|
-
RackEnv = Types::Strict::Hash
|
29
|
-
|
30
28
|
include Dry::Monads::Result::Mixin
|
31
29
|
|
32
30
|
# @!attribute [r] operations
|
33
|
-
# @return [Array<
|
31
|
+
# @return [Array<Proc>]
|
34
32
|
attr_reader :operations
|
35
33
|
|
34
|
+
# @param operations [Array<Proc>]
|
36
35
|
def initialize(operations)
|
37
|
-
@operations =
|
38
|
-
ConnSupport::Composition::Operation
|
39
|
-
)[operations]
|
36
|
+
@operations = operations
|
40
37
|
end
|
41
38
|
|
42
|
-
# @param env [Hash] Rack
|
39
|
+
# @param env [Hash] Rack environment
|
43
40
|
#
|
44
41
|
# @return env [Array] Rack response
|
45
42
|
# @raise ConnSupport::Composition::InvalidOperationResult when an
|
46
|
-
# operation
|
43
|
+
# operation doesn't return a {WebPipe::Conn}
|
47
44
|
def call(env)
|
48
45
|
extract_rack_response(
|
49
46
|
apply_operations(
|
50
47
|
conn_from_env(
|
51
|
-
|
48
|
+
env
|
52
49
|
)
|
53
50
|
)
|
54
51
|
)
|
data/lib/web_pipe/conn.rb
CHANGED
@@ -6,15 +6,8 @@ require 'web_pipe/conn_support/headers'
|
|
6
6
|
|
7
7
|
module WebPipe
|
8
8
|
module ConnSupport
|
9
|
-
# Helper module to build a {Conn} from a rack's env.
|
10
|
-
#
|
11
|
-
# It always return a {Conn::Ongoing} subclass.
|
12
|
-
#
|
13
9
|
# @api private
|
14
10
|
module Builder
|
15
|
-
# @param env [Types::Env] Rack's env
|
16
|
-
#
|
17
|
-
# @return [Conn::Ongoing]
|
18
11
|
# rubocop:disable Metrics/MethodLength
|
19
12
|
def self.call(env)
|
20
13
|
rr = Rack::Request.new(env)
|