web_pipe 0.15.1 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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)
|