web_pipe 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/Gemfile +4 -2
  4. data/README.md +60 -310
  5. data/Rakefile +5 -3
  6. data/bin/console +4 -3
  7. data/docs/_config.yml +1 -0
  8. data/docs/building_a_rack_application.md +25 -0
  9. data/docs/composing_applications.md +43 -0
  10. data/docs/connection_struct/configuring_the_connection_struct.md +25 -0
  11. data/docs/connection_struct/halting_the_pipe.md +71 -0
  12. data/docs/connection_struct/sharing_data_downstream.md +46 -0
  13. data/docs/connection_struct.md +77 -0
  14. data/docs/design_model.md +44 -0
  15. data/docs/dsl_free_usage.md +26 -0
  16. data/docs/extensions/container.md +41 -0
  17. data/docs/extensions/cookies.md +47 -0
  18. data/docs/extensions/dry_schema.md +51 -0
  19. data/docs/extensions/dry_view.md +113 -0
  20. data/docs/extensions/flash.md +41 -0
  21. data/docs/extensions/params.md +117 -0
  22. data/docs/extensions/redirect.md +25 -0
  23. data/docs/extensions/router_params.md +40 -0
  24. data/docs/extensions/session.md +39 -0
  25. data/docs/extensions/url.md +11 -0
  26. data/docs/extensions.md +13 -0
  27. data/docs/introduction.md +73 -0
  28. data/docs/plugging_operations/composing_operations.md +36 -0
  29. data/docs/plugging_operations/injecting_operations.md +32 -0
  30. data/docs/plugging_operations/resolving_operations.md +71 -0
  31. data/docs/plugging_operations.md +21 -0
  32. data/docs/plugs/config.md +18 -0
  33. data/docs/plugs/content_type.md +16 -0
  34. data/docs/plugs.md +13 -0
  35. data/docs/recipes/dry_rb_integration.md +18 -0
  36. data/docs/recipes/hanami_router_integration.md +25 -0
  37. data/docs/recipes/using_all_restful_methods.md +25 -0
  38. data/docs/using_rack_middlewares/composing_middlewares.md +26 -0
  39. data/docs/using_rack_middlewares/injecting_middlewares.md +47 -0
  40. data/docs/using_rack_middlewares.md +22 -0
  41. data/lib/web_pipe/app.rb +4 -2
  42. data/lib/web_pipe/conn.rb +5 -3
  43. data/lib/web_pipe/conn_support/builder.rb +2 -0
  44. data/lib/web_pipe/conn_support/composition.rb +9 -7
  45. data/lib/web_pipe/conn_support/errors.rb +3 -1
  46. data/lib/web_pipe/conn_support/headers.rb +12 -10
  47. data/lib/web_pipe/conn_support/types.rb +11 -9
  48. data/lib/web_pipe/dsl/builder.rb +5 -3
  49. data/lib/web_pipe/dsl/class_context.rb +5 -3
  50. data/lib/web_pipe/dsl/dsl_context.rb +7 -5
  51. data/lib/web_pipe/dsl/instance_methods.rb +7 -5
  52. data/lib/web_pipe/extensions/container/container.rb +2 -0
  53. data/lib/web_pipe/extensions/cookies/cookies.rb +4 -3
  54. data/lib/web_pipe/extensions/dry_schema/dry_schema.rb +2 -0
  55. data/lib/web_pipe/extensions/dry_schema/plugs/sanitize_params.rb +4 -2
  56. data/lib/web_pipe/extensions/dry_view/dry_view.rb +13 -9
  57. data/lib/web_pipe/extensions/flash/flash.rb +7 -7
  58. data/lib/web_pipe/extensions/params/params/transf.rb +3 -1
  59. data/lib/web_pipe/extensions/params/params.rb +7 -5
  60. data/lib/web_pipe/extensions/redirect/redirect.rb +8 -6
  61. data/lib/web_pipe/extensions/router_params/router_params.rb +4 -2
  62. data/lib/web_pipe/extensions/session/session.rb +6 -4
  63. data/lib/web_pipe/extensions/url/url.rb +3 -1
  64. data/lib/web_pipe/plug.rb +7 -5
  65. data/lib/web_pipe/plugs.rb +7 -1
  66. data/lib/web_pipe/rack_support/app_with_middlewares.rb +3 -1
  67. data/lib/web_pipe/rack_support/middleware.rb +2 -0
  68. data/lib/web_pipe/rack_support/middleware_specification.rb +5 -3
  69. data/lib/web_pipe/types.rb +3 -1
  70. data/lib/web_pipe/version.rb +3 -1
  71. data/lib/web_pipe.rb +5 -3
  72. data/web_pipe.gemspec +34 -34
  73. metadata +82 -48
@@ -0,0 +1,73 @@
1
+ # Introduction
2
+
3
+ `web_pipe` is a rack application builder.
4
+
5
+ It means that with it and a rack router (like
6
+ [`hanami-router`](https://github.com/hanami/router),
7
+ [`http_router`](https://github.com/joshbuddy/http_router) or plain
8
+ [rack](https://github.com/rack/rack) routing methods you can build a complete
9
+ web application. However, the idea behind `web_pipe` is being a decoupled
10
+ component within a web framework. For this reason, it plays extremely well
11
+ with [dry-rb](https://dry-rb.org/) ecosystem. If it helps, you can think of it
12
+ as a decoupled web controller (as the C in MVC).
13
+
14
+ `web_pipe` applications are built as a [pipe of
15
+ operations](/docs/design_model.md) on an [immutable
16
+ struct](/docs/connection_struct.md). The struct is automatically created
17
+ with data from an HTTP request, and it contains methods to
18
+ incrementally add data to generate an HTTP response. The pipe can
19
+ be [halted](/docs/connection_struct/halting_the_pipe.md) at any moment,
20
+ taking away from all operations downstream any chance to modify the
21
+ response.
22
+
23
+ `web_pipe` has a modular design, with only the minimal functionalities needed
24
+ to build a web application enabled by default. However, it ships with several
25
+ [extensions](/docs/extensions.md) to make your life easier.
26
+
27
+ Following there is a simple example. It is a web application that will check
28
+ the value of a `user` parameter. When it is `Alice` or `Joe`, it will kindly
29
+ say hello. Otherwise, it will unauthorize:
30
+
31
+ > In order to try this example you can paste it to a file with name `config.ru`
32
+ and launch the rack command `rackup` within the same directory. The application
33
+ will be available in `http://localhost:9292`.
34
+
35
+ ```ruby
36
+ require 'web_pipe'
37
+
38
+ WebPipe.load_extensions(:params)
39
+
40
+ class HelloApp
41
+ include WebPipe
42
+
43
+ AUTHORIZED_USERS = %w[Alice Joe]
44
+
45
+ plug :html
46
+ plug :authorize
47
+ plug :greet
48
+
49
+ private
50
+
51
+ def html(conn)
52
+ conn.add_response_header('Content-Type', 'text/html')
53
+ end
54
+
55
+ def authorize(conn)
56
+ user = conn.params['user']
57
+ if AUTHORIZED_USERS.include?(user)
58
+ conn.add(:user, user)
59
+ else
60
+ conn.
61
+ set_status(401).
62
+ set_response_body('<h1>Not authorized</h1>').
63
+ halt
64
+ end
65
+ end
66
+
67
+ def greet(conn)
68
+ conn.set_response_body("<h1>Hello #{conn.fetch(:user)}</h1>")
69
+ end
70
+ end
71
+
72
+ run HelloApp.new
73
+ ``
@@ -0,0 +1,36 @@
1
+ # Composing operations
2
+
3
+ As we already have said, operations are functions taking a connection struct
4
+ and returning a connection struct. As a result, a composition of operations is
5
+ an operation in itself (as it also takes a connection struct and returns a
6
+ connection struct).
7
+
8
+ This can be leveraged to plug a whole `web_pipe` application as an operation
9
+ to another application. Doing so, you are plugging an operation which is the
10
+ composition of all operations for given application.
11
+
12
+ ```ruby
13
+ class HtmlApp
14
+ include WebPipe
15
+
16
+ plug :content_type
17
+ plug :default_status
18
+
19
+ private
20
+
21
+ def content_type(conn)
22
+ conn.add_response_header('Content-Type' => 'text/html')
23
+ end
24
+
25
+ def default_status(conn)
26
+ conn.set_status(404)
27
+ end
28
+ end
29
+
30
+ class MyApp
31
+ include WebPipe
32
+
33
+ plug :html, HtmlApp.new
34
+ # plug ...
35
+ end
36
+ ```
@@ -0,0 +1,32 @@
1
+ # Injecting operations
2
+
3
+ Operations can be injected at the moment an application is initialized,
4
+ which allows you to override what the definition declares.
5
+
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.
8
+
9
+ This is mainly useful for testing purposes, where you can switch a heavy
10
+ operation and use another lighter one.
11
+
12
+ In the following example, the response body of the application will be
13
+ `'Hello from injection'`:
14
+
15
+ ```ruby
16
+ # config.ru
17
+ require 'web_pipe'
18
+
19
+ class MyApp
20
+ include WebPipe
21
+
22
+ plug(:hello) do |conn|
23
+ conn.set_response_body('Hello from definition')
24
+ end
25
+ end
26
+
27
+ injection = lambda do |conn|
28
+ conn.set_response_body('Hello from injection')
29
+ end
30
+
31
+ run MyApp.new(plugs: { hello: injection })
32
+ ```
@@ -0,0 +1,71 @@
1
+ # Resolving operations
2
+
3
+ There are several ways you can specify how an operation is resolved.
4
+
5
+ ## Instance method
6
+
7
+ Operations can be plugged as methods (both public and private) in the
8
+ application class:
9
+
10
+ ```ruby
11
+ class MyApp
12
+ include WebPipe
13
+
14
+ plug :html
15
+
16
+ private
17
+
18
+ def html(conn)
19
+ conn.add_response_header('Content-Type' => 'text/html')
20
+ end
21
+ end
22
+ ```
23
+
24
+ ## `#call`
25
+
26
+ Operations can be plugged inline as anything responding to `#call`, like a
27
+ `Proc` or a `lambda`:
28
+
29
+ ```ruby
30
+ class MyApp
31
+ include WebPipe
32
+
33
+ plug :html, ->(conn) { conn.add_response_header('Content-Type' => 'text/html') }
34
+ end
35
+ ```
36
+
37
+ ## Block
38
+
39
+ In the same way that `#call`, operations can also be plugged inline as blocks:
40
+
41
+ ```ruby
42
+ class MyApp
43
+ include WebPipe
44
+
45
+ plug :html do |conn|
46
+ conn.add_response_header('Content-Type' => 'text/html')
47
+ end
48
+ end
49
+ ```
50
+
51
+ ## Container
52
+
53
+ Operations can be resolved from a dependency injection container.
54
+
55
+ A container is anything that responds to `#[]` (accepting `Symbol` or `String`
56
+ as argument) in order to resolve a dependency. It can be configured at the
57
+ moment `WebPipe` module is included:
58
+
59
+ ```ruby
60
+ MyContainer = Hash[
61
+ 'plugs.html' => lambda do |conn|
62
+ conn.add_response_header('Content-Type' => 'text/html')
63
+ end
64
+ ]
65
+
66
+ class MyApp
67
+ include WebPipe.(container: MyContainer)
68
+
69
+ plug :html, 'plugs.html'
70
+ end
71
+ ```
@@ -0,0 +1,21 @@
1
+ # Plugging operations
2
+
3
+ You can plug operations to your application with the DSL method `plug`. The
4
+ first argument it always takes is a symbol with the name you want
5
+ to give to the operation (which is needed to allow
6
+ [injection](/docs/plugging_operations/injecting_operations.md) on
7
+ initialization).
8
+
9
+ ```ruby
10
+ class MyApp
11
+ include WebPipe
12
+
13
+ plug :dummy_operation, ->(conn) { conn }
14
+ end
15
+ ```
16
+
17
+ Remember, an operation is just a function (in ruby, anything responding to
18
+ `#call`) that takes a struct with connection information and returns another
19
+ instance of it. First operation in the stack receives a struct which has been
20
+ automatically created with the request data. From then on, any operation can
21
+ add to it response data.
@@ -0,0 +1,18 @@
1
+ # Config
2
+
3
+ `Config` plug helps in the addition of configuration settings (`#config` hash
4
+ attribute) to an instance of `WebPipe::Conn`.
5
+
6
+ ```ruby
7
+ require 'web_pipe'
8
+ require 'web_pipe/plugs/config'
9
+
10
+ class MyApp
11
+ include WebPipe
12
+
13
+ plug :config, WebPipe::Plugs::Config.(
14
+ key1: :value1,
15
+ key2: :value2
16
+ )
17
+ end
18
+ ```
@@ -0,0 +1,16 @@
1
+ # ContentType
2
+
3
+ `ContentType` plug is just a helper to set `Content-Type` response header.
4
+
5
+ Example:
6
+
7
+ ```ruby
8
+ require 'web_pipe'
9
+ require 'web_pipe/plugs/content_type'
10
+
11
+ class MyApp
12
+ include WebPipe
13
+
14
+ plug :html, WebPipe::Plugs::ContentType.('text/html')
15
+ end
16
+ ```
data/docs/plugs.md ADDED
@@ -0,0 +1,13 @@
1
+ # Plugs
2
+
3
+ Some group of operations can be generalized as following same pattern. For
4
+ example, an operation setting `Content-Type` header to `text/html` is very
5
+ similar to another one setting same header to `application/json`. We name plugs
6
+ to this level of abstraction on top of operations: plugs are operation
7
+ builders. In other words, they are higher order functions which return
8
+ functions.
9
+
10
+ Being just functions, we take as convention that plugs respond to `#call` in
11
+ order to create an operation.
12
+
13
+ This library ships with some useful plugs.
@@ -0,0 +1,18 @@
1
+ # dry-rb integration
2
+
3
+ `web_pipe` has been designed to integrate smoothly with
4
+ [dry-rb](https://dry-rb.org/) ecosystem. It shares same design
5
+ principles and it ships with some extensions which even make this
6
+ integration tighter (like
7
+ [`:dry-view`](/docs/extensions/dry_view.md) or
8
+ [`:dry-schema`](/docs/extensions/dry_schema.md) extensions).
9
+
10
+ If you want to use `web_pipe` with the rest of dry-rb libraries,
11
+ your best bet is to use
12
+ [`dry-web-web_pipe`](https://github.com/waiting-for-dev/dry-web-web_pipe)
13
+ skeleton generator. It is a fork of
14
+ [`dry-web-roda`](https://github.com/dry-rb/dry-web-roda) with
15
+ `roda` dependency switched to a combination of `web_pipe` and
16
+ [`hanami-router`](https://github.com/hanami/router).
17
+
18
+ Look at `dry-web-web_pipe` README for more details.
@@ -0,0 +1,25 @@
1
+ # hanami-router integration
2
+
3
+ A `web_pipe` application instance is a rack application.
4
+ Consequently, you can mount it with `hanami-router`'s' `to:`
5
+ option.
6
+
7
+ ```ruby
8
+ # config.ru
9
+ require 'hanami/router'
10
+ require 'web_pipe'
11
+
12
+ class MyApp
13
+ include WebPipe
14
+
15
+ plug :this, ->(conn) { conn.set_response_body('This') }
16
+ end
17
+
18
+ router = Hanami::Router.new do
19
+ get 'my_app', to: MyApp.new
20
+ end
21
+
22
+ run router
23
+ ```
24
+
25
+ In order to perform [string matching with variables](https://github.com/hanami/router#string-matching-with-variables) you just need to load [`:router_params` extension](/docs/extensions/router_params.md).
@@ -0,0 +1,25 @@
1
+ # Using all RESTful methods
2
+
3
+ As you probably know, a lot of browsers don't support some RESTful
4
+ methods like `PATCH` or `PUT`. [Rack's `MethodOverride`
5
+ middleware](https://github.com/rack/rack/blob/master/lib/rack/method_override.rb)
6
+ provides a workaround for this limitation, allowing to override
7
+ request method in rack's env if a magical `_method` parameter or
8
+ `HTTP_METHOD_OVERRIDE` request header is found.
9
+
10
+ You have to be aware that if you use this middleware within a
11
+ `web_pipe` application (through [`use` DSL
12
+ method](docs/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 who should
15
+ read the request method set by rack.
16
+
17
+ The solution for this is very simple. Just use `MethodOverride` middleware before your router does its work. For example, in `config.ru`:
18
+
19
+ ```ruby
20
+ # config.ru
21
+
22
+ use Rack::MethodOverride
23
+
24
+ # Load your router and map to web_pipe applications
25
+ ```
@@ -0,0 +1,26 @@
1
+ # Composing middlewares
2
+
3
+ In a similar way that you compose plugged operations, you can also compose rack
4
+ middlewares from another application.
5
+
6
+ For that, you just need to `use` another application. When you do so, all the
7
+ middlewares for that application will be added to the stack in the same order
8
+ they had there.
9
+
10
+ ```ruby
11
+ class HtmlApp
12
+ include WebPipe
13
+
14
+ use :session, Rack::Session::Cookie, key: 'my_app.session', secret: 'long'
15
+ use :csrf, Rack::Csrf, raise: true
16
+ end
17
+
18
+ class MyApp
19
+ include WebPipe
20
+
21
+ use :html, HtmlApp.new
22
+ # use ...
23
+
24
+ # plug ...
25
+ end
26
+ ```
@@ -0,0 +1,47 @@
1
+ # Injecting middlewares
2
+
3
+ Middlewares can be injected at the moment an application is initialized,
4
+ allowing you to override what you have defined in the DSL.
5
+
6
+ For that purpose, you have to use `middlewares:` keyword argument. It must be a
7
+ hash where middlewares are matched by the name you gave them in its definition.
8
+
9
+ A middleware must be specified as an `Array`. First item must be a rack
10
+ middleware class. The rest of arguments (if any) should be any option it may
11
+ need.
12
+
13
+ This is mainly useful for testing purposes, where you can switch a heavy
14
+ middleware and use a mocked one instead.
15
+
16
+ In the following example, rack session mechanism is being mocked:
17
+
18
+ ```ruby
19
+ # config.ru
20
+ require 'web_pipe'
21
+ require 'rack/session/cookie'
22
+
23
+ class MyApp
24
+ include WebPipe
25
+
26
+ use :session, Rack::Session::Cookie, key: 'my_app.session', secret: 'long'
27
+
28
+ plug(:serialize_session) do |conn|
29
+ conn.set_response_body(conn.env['rack.session'].inspect)
30
+ end
31
+ end
32
+
33
+ class MockedSession
34
+ attr_reader :app, :key
35
+
36
+ def initialize(app, key)
37
+ @app = app
38
+ @key = key
39
+ end
40
+
41
+ def call(env)
42
+ env['rack.session'] = "Mocked for '#{key}' key"
43
+ end
44
+ end
45
+
46
+ run MyApp.new(middlewares: { session: [MockedSession, 'my_app_mocked'] })
47
+ ```
@@ -0,0 +1,22 @@
1
+ # Using rack middlewares
2
+
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 be able to
5
+ use some well-known rack middleware so you don't have to reinvent the wheel.
6
+ Even if you can add them at the router layer, `web_pipe` allows you to
7
+ encapsulate them in your application definition.
8
+
9
+ In order to add rack middlewares to the stack, you have to use the DSL method
10
+ `use`. The first argument it takes is a `Symbol` with the name you want to
11
+ assign to it (which is needed to allow
12
+ [injection](/docs/using_rack_middlewares/injecting_middlewares.md) on
13
+ initialization). Then, it must follow the middleware class and any option it
14
+ may need:
15
+
16
+ ```ruby
17
+ class MyApp
18
+ include WebPipe
19
+
20
+ use :cookies, Rack::Session::Cookie, key: 'my_app.session', secret: 'long'
21
+ end
22
+ ```
data/lib/web_pipe/app.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'web_pipe/types'
2
4
  require 'web_pipe/conn'
3
5
  require 'web_pipe/conn_support/builder'
@@ -55,7 +57,7 @@ module WebPipe
55
57
  private
56
58
 
57
59
  def conn_from_env(env)
58
- ConnSupport::Builder.(env)
60
+ ConnSupport::Builder.call(env)
59
61
  end
60
62
 
61
63
  def apply_operations(conn)
@@ -66,4 +68,4 @@ module WebPipe
66
68
  conn.rack_response
67
69
  end
68
70
  end
69
- end
71
+ end
data/lib/web_pipe/conn.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'dry/struct'
2
4
  require 'web_pipe/types'
3
5
  require 'web_pipe/conn_support/types'
@@ -315,7 +317,7 @@ module WebPipe
315
317
  def fetch(key, default = Types::Undefined)
316
318
  return bag.fetch(key, default) unless default == Types::Undefined
317
319
 
318
- bag.fetch(key) { raise ConnSupport::KeyNotFoundInBagError.new(key) }
320
+ bag.fetch(key) { raise ConnSupport::KeyNotFoundInBagError, key }
319
321
  end
320
322
 
321
323
  # Writes an item to the {#bag}.
@@ -343,7 +345,7 @@ module WebPipe
343
345
  def fetch_config(key, default = Types::Undefined)
344
346
  return config.fetch(key, default) unless default == Types::Undefined
345
347
 
346
- config.fetch(key) { raise ConnSupport::KeyNotFoundInConfigError.new(key) }
348
+ config.fetch(key) { raise ConnSupport::KeyNotFoundInConfigError, key }
347
349
  end
348
350
 
349
351
  # Writes an item to {#config}.
@@ -402,4 +404,4 @@ module WebPipe
402
404
  # cycle.
403
405
  class Halted < Conn; end
404
406
  end
405
- end
407
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rack'
2
4
  require 'web_pipe/conn'
3
5
  require 'web_pipe/conn_support/headers'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'dry/monads/result'
2
4
  require 'web_pipe/types'
3
5
  require 'web_pipe/conn'
@@ -27,10 +29,10 @@ module WebPipe
27
29
  def initialize(returned)
28
30
  super(
29
31
  <<~eos
30
- An operation returned +#{returned.inspect}+. To be valid,
31
- an operation must return whether a
32
- WebPipe::Conn::Ongoing or a WebPipe::Conn::Halted.
33
- eos
32
+ An operation returned +#{returned.inspect}+. To be valid,
33
+ an operation must return whether a
34
+ WebPipe::Conn::Ongoing or a WebPipe::Conn::Halted.
35
+ eos
34
36
  )
35
37
  end
36
38
  end
@@ -66,14 +68,14 @@ module WebPipe
66
68
  end
67
69
 
68
70
  def apply_operation(conn, operation)
69
- result = operation.(conn)
71
+ result = operation.call(conn)
70
72
  case result
71
73
  when Conn::Ongoing
72
74
  Success(result)
73
75
  when Conn::Halted
74
76
  Failure(result)
75
77
  else
76
- raise InvalidOperationResult.new(result)
78
+ raise InvalidOperationResult, result
77
79
  end
78
80
  end
79
81
 
@@ -84,4 +86,4 @@ module WebPipe
84
86
  end
85
87
  end
86
88
  end
87
- end
89
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebPipe
2
4
  module ConnSupport
3
5
  # Error raised when trying to fetch an entry in {Conn#bag} for an
@@ -42,4 +44,4 @@ module WebPipe
42
44
  end
43
45
  end
44
46
  end
45
- end
47
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebPipe
2
4
  module ConnSupport
3
5
  # Helpers to work with headers and its rack's env representation.
@@ -12,7 +14,7 @@ module WebPipe
12
14
  #
13
15
  # Headers are all those pairs which key begins with `HTTP_` plus
14
16
  # those detailed in {HEADERS_AS_CGI}.
15
- #
17
+ #
16
18
  # @param env [Types::Env[]]
17
19
  #
18
20
  # @return [Types::Headers[]]
@@ -21,14 +23,14 @@ module WebPipe
21
23
  # @see .normalize_key
22
24
  def self.extract(env)
23
25
  Hash[
24
- env.
25
- select { |k, _v| k.start_with?('HTTP_') }.
26
- map { |k, v| pair(k[5 .. -1], v) }.
27
- concat(
28
- env.
29
- select { |k, _v| HEADERS_AS_CGI.include?(k) }.
30
- map { |k, v| pair(k, v) }
31
- )
26
+ env
27
+ .select { |k, _v| k.start_with?('HTTP_') }
28
+ .map { |k, v| pair(k[5..-1], v) }
29
+ .concat(
30
+ env
31
+ .select { |k, _v| HEADERS_AS_CGI.include?(k) }
32
+ .map { |k, v| pair(k, v) }
33
+ )
32
34
  ]
33
35
  end
34
36
 
@@ -103,4 +105,4 @@ module WebPipe
103
105
  end
104
106
  end
105
107
  end
106
- end
108
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'dry/types'
2
4
  require 'rack/request'
3
5
 
@@ -25,18 +27,18 @@ module WebPipe
25
27
  QueryString = Strict::String
26
28
  RequestBody = Interface(:gets, :each, :read, :rewind)
27
29
 
28
- Status = Strict::Integer.
29
- default(200).
30
- constrained(gteq: 100, lteq: 599)
30
+ Status = Strict::Integer
31
+ .default(200)
32
+ .constrained(gteq: 100, lteq: 599)
31
33
  ResponseBody = Interface(:each).default { [''] }
32
34
 
33
- Headers = Strict::Hash.
34
- map(Strict::String, Strict::String).
35
- default { {} }
35
+ Headers = Strict::Hash
36
+ .map(Strict::String, Strict::String)
37
+ .default { {} }
36
38
 
37
- Bag = Strict::Hash.
38
- map(Strict::Symbol, Strict::Any).
39
- default { {} }
39
+ Bag = Strict::Hash
40
+ .map(Strict::Symbol, Strict::Any)
41
+ .default { {} }
40
42
  end
41
43
  end
42
44
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'web_pipe/types'
2
4
  require 'web_pipe/dsl/class_context'
3
5
  require 'web_pipe/dsl/instance_methods'
@@ -12,7 +14,7 @@ module WebPipe
12
14
  class Builder < Module
13
15
  # Container with nothing registered.
14
16
  EMPTY_CONTAINER = Types::EMPTY_HASH
15
-
17
+
16
18
  # @!attribute [r] container
17
19
  # @return [Types::Container[]]
18
20
  attr_reader :container
@@ -24,11 +26,11 @@ module WebPipe
24
26
  @container = Types::Container[container]
25
27
  @class_context = ClassContext.new(container: container)
26
28
  end
27
-
29
+
28
30
  def included(klass)
29
31
  klass.extend(class_context)
30
32
  klass.include(InstanceMethods)
31
33
  end
32
34
  end
33
35
  end
34
- end
36
+ end