landline 0.10.0 → 0.12.1
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/README.md +71 -19
- data/lib/landline/app.rb +65 -0
- data/lib/landline/dsl/constructors_path.rb +21 -0
- data/lib/landline/dsl/constructors_probe.rb +2 -0
- data/lib/landline/dsl/methods_common.rb +2 -0
- data/lib/landline/dsl/methods_path.rb +25 -5
- data/lib/landline/dsl/methods_probe.rb +129 -11
- data/lib/landline/dsl/methods_template.rb +1 -0
- data/lib/landline/extensions/session.rb +98 -0
- data/lib/landline/extensions/websocket.rb +286 -0
- data/lib/landline/path.rb +40 -29
- data/lib/landline/probe/crosscall_handler.rb +25 -0
- data/lib/landline/probe/handler.rb +19 -15
- data/lib/landline/probe.rb +1 -11
- data/lib/landline/request.rb +68 -7
- data/lib/landline/response.rb +1 -1
- data/lib/landline/sandbox.rb +32 -0
- data/lib/landline/server.rb +43 -18
- data/lib/landline/util/cookie.rb +10 -3
- data/lib/landline/util/jwt.rb +82 -0
- data/lib/landline/util/lookup.rb +16 -0
- data/lib/landline/util/mime.rb +1 -0
- data/lib/landline/util/parseutils.rb +13 -11
- data/lib/landline/util/query.rb +2 -0
- data/lib/landline.rb +4 -2
- metadata +10 -6
- data/LAYOUT.md +0 -86
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a6713c809dcb1f2216afff7f05d00e932c85d36c1b205359a2c8f8655b79fbb1
|
4
|
+
data.tar.gz: 34846e521a08d55376a520a194417edf0cb66972bf6c052ac6fb5d888fea30f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b54438875d8532e95858567f0305b03baf00a6c88a735851116be73ea2b7619031226624ff846d05a7439050deff1b02acfe5c5a7d1a8afdb8e67b2ea6b520a1
|
7
|
+
data.tar.gz: 03031f8d28c5e8657854cdff63e4f205d9b553cb03e34109b761a5f65207fd473005a61a5504a3f96517a37fe2d1f1b234b733916a3bd5f33f4de0e64a30fbab
|
data/README.md
CHANGED
@@ -2,25 +2,15 @@
|
|
2
2
|
|
3
3
|
Landline is a library that provides a minimalistic DSL for creating
|
4
4
|
web services. It doesn't include patterns, middleware, or anything that
|
5
|
-
could be considered application logic
|
6
|
-
it does them well
|
5
|
+
could be considered application logic, besides the basic primitives
|
6
|
+
It does a few things, and hopefully it does them well.
|
7
7
|
|
8
|
-
|
9
|
-
- Processing HTTP requests (cookies, headers, etc.)
|
10
|
-
- Filtering, preprocessing and postprocessing requests
|
11
|
-
- Creating responses from templates using various template engines
|
12
|
-
- Parsing and handling forms and queries
|
13
|
-
- Connecting multiple Landline applications together
|
14
|
-
|
15
|
-
As such, the library is pretty thin and can be used to build more complex
|
16
|
-
applications.
|
17
|
-
|
18
|
-
As of now it is using Rack as the webserver adapter, but ideally it
|
19
|
-
shouldn't take much work to make it run on top of any webserver.
|
20
|
-
|
21
|
-
Landline was made mostly for fun. Ideally it will become something more,
|
8
|
+
Landline was made mostly for fun. ~~Ideally it will become something more,
|
22
9
|
but as of yet it's just an experiment revolving around Ruby Metaprogramming
|
23
|
-
and its DSL capabilities
|
10
|
+
and its DSL capabilities.~~ Since then, it has somewhat matured, and while
|
11
|
+
it's still not entirely advisable to use in production due to the experimental
|
12
|
+
nature of the framework, you're free to test it, see if it works, and if it
|
13
|
+
doesn't, supply (hopefully constructive) criticism and/or suggestions.
|
24
14
|
|
25
15
|
## Examples
|
26
16
|
|
@@ -85,7 +75,7 @@ end
|
|
85
75
|
run app
|
86
76
|
```
|
87
77
|
|
88
|
-
Static file serving
|
78
|
+
Static file serving with nginx-like syntax and file globbing
|
89
79
|
(Note: index applies *only* to /var/www (to the path its defined in))
|
90
80
|
|
91
81
|
```ruby
|
@@ -100,7 +90,7 @@ end
|
|
100
90
|
run app
|
101
91
|
```
|
102
92
|
|
103
|
-
|
93
|
+
Preprocessing requests on a subset of handlers
|
104
94
|
|
105
95
|
```ruby
|
106
96
|
require 'landline'
|
@@ -127,8 +117,70 @@ end
|
|
127
117
|
run app
|
128
118
|
```
|
129
119
|
|
120
|
+
Class interface with middleware support
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
require 'landline'
|
124
|
+
|
125
|
+
class TimerMiddleware
|
126
|
+
def initialize(app)
|
127
|
+
@app = app
|
128
|
+
end
|
129
|
+
|
130
|
+
def call(*data)
|
131
|
+
puts("Request accepted")
|
132
|
+
before = Time.now
|
133
|
+
output = @app.call(*data)
|
134
|
+
puts("Time elapsed: #{(Time.now - before) * 1000}ms")
|
135
|
+
output
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
class Application < Landline::App
|
140
|
+
use TimerMiddleware
|
141
|
+
|
142
|
+
get "/hello" do
|
143
|
+
"Hello world!"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
run Application.new
|
148
|
+
```
|
149
|
+
|
130
150
|
And a lot more to be found in /examples in this repo.
|
131
151
|
|
152
|
+
|
153
|
+
## Design goals
|
154
|
+
|
155
|
+
Out of the box, Landline is designed to do the following:
|
156
|
+
|
157
|
+
- Routing HTTP requests to handlers
|
158
|
+
- Processing HTTP requests (cookies, headers, etc.)
|
159
|
+
- Filtering, preprocessing, postprocessing requests
|
160
|
+
- Deferring block execution until after the request gets processed
|
161
|
+
- Creating responses from templates using various template engines
|
162
|
+
- Parsing and handling forms and queries
|
163
|
+
- Connecting multiple ~~Landline~~ Rack applications together
|
164
|
+
- Sending files using nginx-style configuration system
|
165
|
+
- A lot of basic Rack things such as plugging in middleware, BEING middleware,
|
166
|
+
or sending Rack-compatible environment to another Rack application
|
167
|
+
|
168
|
+
As such, the library is pretty thin and can be used to build more complex
|
169
|
+
applications. This is intentional, and hopefully will remain that way.
|
170
|
+
|
171
|
+
Additionally, there are a few extra things landline can do, which can be used
|
172
|
+
by `require`ing from the `landline/extensions` directory. Please note, however,
|
173
|
+
that some of that functionality may require additional dependencies, which
|
174
|
+
would otherwise be optional. This functionality includes:
|
175
|
+
|
176
|
+
- PHP-like Session handling (via `landline/extensions/session`)
|
177
|
+
- Websockets (via `landline/extensions/websockets`) (available for testing)
|
178
|
+
- (Probably something else eventually)
|
179
|
+
|
180
|
+
Landline is built entirely on Rack webserver interface, while being agnostic
|
181
|
+
to any and all underlying webservers (such as Puma, Thin, Unicorn and such).
|
182
|
+
For the foreseeable future, this design decision will not change.
|
183
|
+
|
132
184
|
## Name
|
133
185
|
|
134
186
|
The name is, quite literally, a metaphor for request routing.
|
data/lib/landline/app.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Landline
|
4
|
+
# Rack application interface
|
5
|
+
class App
|
6
|
+
class << self
|
7
|
+
# TODO: fix this mess somehow (probably impossible)
|
8
|
+
# @!parse include Landline::DSL::PathMethods
|
9
|
+
# @!parse include Landline::DSL::PathConstructors
|
10
|
+
# @!parse include Landline::DSL::ProbeConstructors
|
11
|
+
# @!parse include Landline::DSL::ProbeMethods
|
12
|
+
# @!parse include Landline::DSL::CommonMethods
|
13
|
+
|
14
|
+
# Duplicate used middleware for the subclassed app
|
15
|
+
def inherited(subclass)
|
16
|
+
super(subclass)
|
17
|
+
@setup_chain ||= []
|
18
|
+
subclass.middleware = @middleware.dup
|
19
|
+
subclass.setup_chain = @setup_chain.dup
|
20
|
+
end
|
21
|
+
|
22
|
+
# Include a middleware in application
|
23
|
+
# @param middleware [Class]
|
24
|
+
def use(middleware)
|
25
|
+
@middleware ||= []
|
26
|
+
@middleware.append(middleware)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Check if Server can respond to given symbol
|
30
|
+
def respond_to_missing?(symbol, _include_private)
|
31
|
+
Landline::ServerContext.instance_methods.include?(symbol) || super
|
32
|
+
end
|
33
|
+
|
34
|
+
# Store applied app manipulations
|
35
|
+
def method_missing(symbol, *args, **params, &callback)
|
36
|
+
if Landline::ServerContext.instance_methods.include? symbol
|
37
|
+
@setup_chain.append([symbol, args, params, callback])
|
38
|
+
else
|
39
|
+
super(symbol, *args, **params, &callback)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
attr_accessor :middleware, :setup_chain
|
44
|
+
end
|
45
|
+
|
46
|
+
def initialize(*args, **opts)
|
47
|
+
setup_chain = self.class.setup_chain
|
48
|
+
@app = ::Landline::Server.new(*args, **opts) do
|
49
|
+
setup_chain.each do |symbol, cargs, cparams, callback|
|
50
|
+
send(symbol, *cargs, **cparams, &callback)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
self.class.middleware&.reverse_each do |cls|
|
54
|
+
@app = cls.new(@app)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Rack ingress point.
|
59
|
+
# @param env [Hash]
|
60
|
+
# @return [Array(Integer,Hash,Array)]
|
61
|
+
def call(env)
|
62
|
+
@app.call(env)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -5,6 +5,7 @@ module Landline
|
|
5
5
|
module DSL
|
6
6
|
# Path (and subclasses) DSL constructors
|
7
7
|
module PathConstructors
|
8
|
+
# (in Landline::Path context)
|
8
9
|
# Append a Node child object to the list of children
|
9
10
|
def register(obj)
|
10
11
|
unless obj.is_a? Landline::Node
|
@@ -14,11 +15,13 @@ module Landline
|
|
14
15
|
@origin.children.append(obj)
|
15
16
|
end
|
16
17
|
|
18
|
+
# (in Landline::Path context)
|
17
19
|
# Create a new {Landline::Path} object
|
18
20
|
def path(path, **args, &setup)
|
19
21
|
register(Landline::Path.new(path, parent: @origin, **args, &setup))
|
20
22
|
end
|
21
23
|
|
24
|
+
# (in Landline::Path context)
|
22
25
|
# Create a new {Landline::Handlers::Probe} object
|
23
26
|
def probe(path, **args, &_setup)
|
24
27
|
register(Landline::Handlers::Probe.new(path,
|
@@ -26,6 +29,7 @@ module Landline
|
|
26
29
|
**args))
|
27
30
|
end
|
28
31
|
|
32
|
+
# (in Landline::Path context)
|
29
33
|
# Create a new {Landline::Handlers::GETHandler} object
|
30
34
|
def get(path, **args, &setup)
|
31
35
|
register(Landline::Handlers::GET.new(path,
|
@@ -34,6 +38,7 @@ module Landline
|
|
34
38
|
&setup))
|
35
39
|
end
|
36
40
|
|
41
|
+
# (in Landline::Path context)
|
37
42
|
# create a new {Landline::Handlers::POSTHandler} object
|
38
43
|
def post(path, **args, &setup)
|
39
44
|
register(Landline::Handlers::POST.new(path,
|
@@ -42,6 +47,7 @@ module Landline
|
|
42
47
|
&setup))
|
43
48
|
end
|
44
49
|
|
50
|
+
# (in Landline::Path context)
|
45
51
|
# Create a new {Landline::Handlers::PUTHandler} object
|
46
52
|
def put(path, **args, &setup)
|
47
53
|
register(Landline::Handlers::PUT.new(path,
|
@@ -50,6 +56,7 @@ module Landline
|
|
50
56
|
&setup))
|
51
57
|
end
|
52
58
|
|
59
|
+
# (in Landline::Path context)
|
53
60
|
# Create a new {Landline::Handlers::HEADHandler} object
|
54
61
|
def head(path, **args, &setup)
|
55
62
|
register(Landline::Handlers::HEAD.new(path,
|
@@ -58,6 +65,7 @@ module Landline
|
|
58
65
|
&setup))
|
59
66
|
end
|
60
67
|
|
68
|
+
# (in Landline::Path context)
|
61
69
|
# Create a new {Landline::Handlers::DELETEHandler} object
|
62
70
|
def delete(path, **args, &setup)
|
63
71
|
register(Landline::Handlers::DELETE.new(path,
|
@@ -66,6 +74,7 @@ module Landline
|
|
66
74
|
&setup))
|
67
75
|
end
|
68
76
|
|
77
|
+
# (in Landline::Path context)
|
69
78
|
# Create a new {Landline::Handlers::CONNECTHandler} object
|
70
79
|
def connect(path, **args, &setup)
|
71
80
|
register(Landline::Handlers::CONNECT.new(path,
|
@@ -74,6 +83,7 @@ module Landline
|
|
74
83
|
&setup))
|
75
84
|
end
|
76
85
|
|
86
|
+
# (in Landline::Path context)
|
77
87
|
# Create a new {Landline::Handlers::TRACEHandler} object
|
78
88
|
def trace(path, **args, &setup)
|
79
89
|
register(Landline::Handlers::TRACE.new(path,
|
@@ -82,6 +92,7 @@ module Landline
|
|
82
92
|
&setup))
|
83
93
|
end
|
84
94
|
|
95
|
+
# (in Landline::Path context)
|
85
96
|
# Create a new {Landline::Handlers::PATCHHandler} object
|
86
97
|
def patch(path, **args, &setup)
|
87
98
|
register(Landline::Handlers::PATCH.new(path,
|
@@ -90,6 +101,7 @@ module Landline
|
|
90
101
|
&setup))
|
91
102
|
end
|
92
103
|
|
104
|
+
# (in Landline::Path context)
|
93
105
|
# Create a new {Landline::Handlers::OPTIONSHandler} object
|
94
106
|
def options(path, **args, &setup)
|
95
107
|
register(Landline::Handlers::OPTIONS.new(path,
|
@@ -98,10 +110,19 @@ module Landline
|
|
98
110
|
&setup))
|
99
111
|
end
|
100
112
|
|
113
|
+
# (in Landline::Path context)
|
101
114
|
# Create a new {Landline::Handlers::GETHandler} that serves static files
|
102
115
|
def serve(path)
|
103
116
|
register(Landline::Handlers::Serve.new(path, parent: @origin))
|
104
117
|
end
|
118
|
+
|
119
|
+
# (in Landline::Path context)
|
120
|
+
# Create a new application crosscall link (acts like #call in probe context and strips its path from request)
|
121
|
+
def link(path, application)
|
122
|
+
register(Landline::Handlers::Link.new(path,
|
123
|
+
application,
|
124
|
+
parent: @origin))
|
125
|
+
end
|
105
126
|
end
|
106
127
|
end
|
107
128
|
end
|
@@ -4,6 +4,7 @@ module Landline
|
|
4
4
|
module DSL
|
5
5
|
# Probe (and subclasses) DSL construct
|
6
6
|
module ProbeConstructors
|
7
|
+
# (in Landline::Probe context)
|
7
8
|
# Create a new erb template
|
8
9
|
# @see Landline::Template#new
|
9
10
|
def erb(input, vars = {})
|
@@ -13,6 +14,7 @@ module Landline
|
|
13
14
|
filename: caller_locations[0].path)
|
14
15
|
end
|
15
16
|
|
17
|
+
# (in Landline::Probe context)
|
16
18
|
# Create a new erb template using Erubi engine
|
17
19
|
# @see Landline::Template#new
|
18
20
|
# @param freeze [Boolean] whether to use frozen string literal
|
@@ -4,6 +4,7 @@ module Landline
|
|
4
4
|
module DSL
|
5
5
|
# Methods shared by probes, preprocessors and filters.
|
6
6
|
module CommonMethods
|
7
|
+
# (in Landline::Probe context)
|
7
8
|
# Stop execution and generate a boilerplate response with the given code
|
8
9
|
# @param errorcode [Integer]
|
9
10
|
# @param backtrace [Array(String), nil]
|
@@ -18,6 +19,7 @@ module Landline
|
|
18
19
|
)
|
19
20
|
end
|
20
21
|
|
22
|
+
# (in Landline::Probe context)
|
21
23
|
# Bounce request to the next handler
|
22
24
|
# @raise [UncaughtThrowError] throws :break to get out of the callback
|
23
25
|
def bounce
|
@@ -5,11 +5,19 @@ module Landline
|
|
5
5
|
module DSL
|
6
6
|
# Common path methods
|
7
7
|
module PathMethods
|
8
|
+
# (in Landline::Path context)
|
8
9
|
# Bounce request if no handler found instead of issuing 404
|
9
10
|
def bounce
|
10
11
|
@origin.bounce = true
|
11
12
|
end
|
12
13
|
|
14
|
+
# (in Landline::Path context)
|
15
|
+
# Unset bounce
|
16
|
+
def nobounce
|
17
|
+
@origin.bounce = false
|
18
|
+
end
|
19
|
+
|
20
|
+
# (in Landline::Path context)
|
13
21
|
# Create a status code handler on path.
|
14
22
|
# Recursively applies to all paths unless overridden.
|
15
23
|
# @param code [Integer, nil] Specify a status code to handle
|
@@ -18,6 +26,7 @@ module Landline
|
|
18
26
|
@origin.properties["handle.#{code || 'default'}"] = block
|
19
27
|
end
|
20
28
|
|
29
|
+
# (in Landline::Path context)
|
21
30
|
# Insert a pass-through pipeline into request processing
|
22
31
|
# (i.e. for error handling purposes).
|
23
32
|
# Passed block should yield request (and return yielded data back).
|
@@ -26,6 +35,7 @@ module Landline
|
|
26
35
|
@origin.pipeline = block
|
27
36
|
end
|
28
37
|
|
38
|
+
# (in Landline::Path context)
|
29
39
|
# Set path index
|
30
40
|
# @param index [Array,String]
|
31
41
|
def index(index)
|
@@ -39,18 +49,21 @@ module Landline
|
|
39
49
|
end
|
40
50
|
end
|
41
51
|
|
52
|
+
# (in Landline::Path context)
|
42
53
|
# Set root path (appends matched part of the path).
|
43
54
|
# @param path [String]
|
44
55
|
def root(path)
|
45
|
-
@origin.root = path
|
56
|
+
@origin.root = File.expand_path(path)
|
46
57
|
end
|
47
58
|
|
59
|
+
# (in Landline::Path context)
|
48
60
|
# Set root path (without appending matched part).
|
49
61
|
# @param path [String]
|
50
62
|
def remap(path)
|
51
|
-
@origin.remap = path
|
63
|
+
@origin.remap = File.expand_path(path)
|
52
64
|
end
|
53
65
|
|
66
|
+
# (in Landline::Path context)
|
54
67
|
# Add a preprocessor to the path.
|
55
68
|
# Does not modify path execution.
|
56
69
|
# @param block [#call]
|
@@ -60,6 +73,7 @@ module Landline
|
|
60
73
|
block
|
61
74
|
end
|
62
75
|
|
76
|
+
# (in Landline::Path context)
|
63
77
|
# Add a postprocessor to the path.
|
64
78
|
# @param block [#call]
|
65
79
|
# @yieldparam request [Landline::Request]
|
@@ -69,6 +83,10 @@ module Landline
|
|
69
83
|
block
|
70
84
|
end
|
71
85
|
|
86
|
+
alias before preprocess
|
87
|
+
alias after postprocess
|
88
|
+
|
89
|
+
# (in Landline::Path context)
|
72
90
|
# Add a filter to the path.
|
73
91
|
# Blocks path access if a filter returns false.
|
74
92
|
# @param block [#call]
|
@@ -78,10 +96,12 @@ module Landline
|
|
78
96
|
block
|
79
97
|
end
|
80
98
|
|
99
|
+
# (in Landline::Path context)
|
81
100
|
# Include an application as a child of path.
|
101
|
+
# @deprecated this method is being deprecated due to strong dependency on the framework
|
82
102
|
# @param filename [String]
|
83
103
|
def plugin(filename)
|
84
|
-
|
104
|
+
define_singleton_method(:run) do |object|
|
85
105
|
unless object.is_a? Landline::Node
|
86
106
|
raise ArgumentError, "not a node instance or subclass instance"
|
87
107
|
end
|
@@ -89,9 +109,9 @@ module Landline
|
|
89
109
|
object
|
90
110
|
end
|
91
111
|
@origin.children.append(
|
92
|
-
|
112
|
+
instance_eval(File.read(filename), filename)
|
93
113
|
)
|
94
|
-
|
114
|
+
singleton_class.undef_method :run
|
95
115
|
end
|
96
116
|
end
|
97
117
|
end
|
@@ -4,17 +4,20 @@ require_relative '../response'
|
|
4
4
|
require_relative '../util/multipart'
|
5
5
|
require_relative '../util/parseutils'
|
6
6
|
require_relative '../util/html'
|
7
|
+
require 'json'
|
7
8
|
|
8
9
|
module Landline
|
9
10
|
module DSL
|
10
11
|
# Common methods for Probe objects
|
11
12
|
module ProbeMethods
|
13
|
+
# (in Landline::Probe context)
|
12
14
|
# Get the current request
|
13
15
|
# @return [Landline::Request]
|
14
16
|
def request
|
15
17
|
@origin.request
|
16
18
|
end
|
17
19
|
|
20
|
+
# (in Landline::Probe context)
|
18
21
|
# Set response status (generate response if one doesn't exist yet)
|
19
22
|
# @param status [Integer] http status code
|
20
23
|
def status(status)
|
@@ -22,8 +25,59 @@ module Landline
|
|
22
25
|
@origin.response.status = status
|
23
26
|
end
|
24
27
|
|
28
|
+
# (in Landline::Probe context)
|
29
|
+
# Add a finalizer callable to the response
|
30
|
+
# @param callable [#call]
|
31
|
+
def defer(&callable)
|
32
|
+
rack = @origin.request.rack
|
33
|
+
if rack.respond_to?(:response_finished)
|
34
|
+
rack.response_finished.append(callable)
|
35
|
+
end
|
36
|
+
# puma for some reason isn't compatible with the 3.0.0 spec on this
|
37
|
+
rack.after_reply.append(callable) if rack.respond_to?(:after_reply)
|
38
|
+
end
|
39
|
+
|
40
|
+
# (in Landline::Probe context)
|
41
|
+
# Do serverside request redirection
|
42
|
+
# @note this essentially reprocesses the whole request - be mindful of processing time!
|
43
|
+
# @param path [String]
|
44
|
+
def jump(path)
|
45
|
+
@origin.request.path = path
|
46
|
+
throw(:finish, [307, { "x-internal-jump": true }, []])
|
47
|
+
end
|
48
|
+
|
49
|
+
# (in Landline::Probe context)
|
50
|
+
# Do clientside request redirection via 302 code
|
51
|
+
# @param path [String]
|
52
|
+
def redirect(path)
|
53
|
+
throw(:finish, [302, { "location": path }, []])
|
54
|
+
end
|
55
|
+
|
56
|
+
# (in Landline::Probe context)
|
57
|
+
# Do clientside request redirection via 307 code
|
58
|
+
# @param path [String]
|
59
|
+
def redirect_with_method(path)
|
60
|
+
throw(:finish, [307, { "location": path }, []])
|
61
|
+
end
|
62
|
+
|
25
63
|
alias code status
|
26
64
|
|
65
|
+
# (in Landline::Probe context)
|
66
|
+
# Set a partial hijack callback
|
67
|
+
# @param block [#call] Callable block
|
68
|
+
def partial_hijack(&block)
|
69
|
+
@origin.response ||= Landline::Response.new
|
70
|
+
@origin.response.add_header("rack.hijack", block)
|
71
|
+
end
|
72
|
+
|
73
|
+
# (in Landline::Probe context)
|
74
|
+
# Fully hijack IO
|
75
|
+
# @return [IO]
|
76
|
+
def hijack
|
77
|
+
@origin.request.hijack.call
|
78
|
+
end
|
79
|
+
|
80
|
+
# (in Landline::Probe context)
|
27
81
|
# Set response header (generate response if one doesn't exist yet)
|
28
82
|
# @param key [String] header name
|
29
83
|
# @param value [String] header value
|
@@ -39,10 +93,11 @@ module Landline
|
|
39
93
|
end
|
40
94
|
|
41
95
|
@origin.response = (@origin.response or Landline::Response.new)
|
42
|
-
key = key.downcase
|
96
|
+
key = key.downcase.to_s
|
43
97
|
@origin.response.add_header(key, value)
|
44
98
|
end
|
45
99
|
|
100
|
+
# (in Landline::Probe context)
|
46
101
|
# Delete a header value from the headers hash
|
47
102
|
# If no value is provided, deletes all key entries
|
48
103
|
# @param key [String] header name
|
@@ -60,9 +115,10 @@ module Landline
|
|
60
115
|
raise ArgumentError, "value key has invalid characters"
|
61
116
|
end
|
62
117
|
|
63
|
-
@origin.response.delete_header(key, value)
|
118
|
+
@origin.response.delete_header(key.to_s, value)
|
64
119
|
end
|
65
120
|
|
121
|
+
# (in Landline::Probe context)
|
66
122
|
# Set response cookie
|
67
123
|
# @see Landline::Cookie.new
|
68
124
|
def cookie(*params, **options)
|
@@ -72,6 +128,7 @@ module Landline
|
|
72
128
|
)
|
73
129
|
end
|
74
130
|
|
131
|
+
# (in Landline::Probe context)
|
75
132
|
# Delete a cookie
|
76
133
|
# If no value is provided, deletes all cookies with the same key
|
77
134
|
# @param key [String] cookie key
|
@@ -82,21 +139,17 @@ module Landline
|
|
82
139
|
@origin.response.delete_cookie(key, value)
|
83
140
|
end
|
84
141
|
|
142
|
+
# (in Landline::Probe context)
|
85
143
|
# Checks if current request has multipart/form-data associated with it
|
86
144
|
# @return [Boolean]
|
87
145
|
def form?
|
88
|
-
value, opts =
|
89
|
-
|
90
|
-
)
|
91
|
-
if value == "multipart/form-data" and
|
92
|
-
opts["boundary"]
|
93
|
-
true
|
94
|
-
else
|
95
|
-
false
|
96
|
-
end
|
146
|
+
value, opts = _verify_content_type('multipart/form-data')
|
147
|
+
!!(value && opts && opts['boundary'])
|
97
148
|
end
|
98
149
|
|
150
|
+
# (in Landline::Probe context)
|
99
151
|
# Returns formdata
|
152
|
+
# @note reads request.input - may nullify request.body.
|
100
153
|
# @return [Hash{String=>(String,Landline::Util::FormPart)}]
|
101
154
|
def form
|
102
155
|
_, opts = Landline::Util::ParserCommon.parse_value(
|
@@ -107,23 +160,88 @@ module Landline
|
|
107
160
|
).to_h
|
108
161
|
end
|
109
162
|
|
163
|
+
# (in Landline::Probe context)
|
164
|
+
# Checks if current request has urlencoded query string
|
165
|
+
# @return [Boolean]
|
166
|
+
def query?
|
167
|
+
!!_verify_content_type("application/x-www-form-urlencode")
|
168
|
+
end
|
169
|
+
|
170
|
+
# (in Landline::Probe context)
|
171
|
+
# Returns parsed query hash
|
172
|
+
# @note reads request.body - may nullify .input, .body data is memoized
|
173
|
+
# @return [Hash{String => Object}] query data
|
174
|
+
def query
|
175
|
+
Landline::Util::Query.new(request.body).parse
|
176
|
+
end
|
177
|
+
|
178
|
+
# (in Landline::Probe context)
|
179
|
+
# Returns shallow parsed query hash
|
180
|
+
# @note reads request.body - may nullify .input, .body data is memoized
|
181
|
+
# @return [Hash{String => Object}] query data
|
182
|
+
def query_shallow
|
183
|
+
Landline::Util::Query.new(request.body).parse_shallow
|
184
|
+
end
|
185
|
+
|
186
|
+
# (in Landline::Probe context)
|
187
|
+
# Check if body is a JSON object
|
188
|
+
# @return [Boolean]
|
189
|
+
def json?
|
190
|
+
!!_verify_content_type('application/json')
|
191
|
+
end
|
192
|
+
|
193
|
+
# (in Landline::Probe context)
|
194
|
+
# Return parse JSON object
|
195
|
+
# @note reads request.input - may nullify request.body.
|
196
|
+
# @return [Object]
|
197
|
+
def json
|
198
|
+
JSON.parse(request.input)
|
199
|
+
end
|
200
|
+
|
201
|
+
# (in Landline::Probe context)
|
110
202
|
# Open a file relative to current filepath
|
111
203
|
# @see File.open
|
112
204
|
def file(path, mode = "r", *all, &block)
|
113
205
|
File.open("#{request.filepath}/#{path}", mode, *all, &block)
|
114
206
|
end
|
115
207
|
|
208
|
+
# (in Landline::Probe context)
|
116
209
|
# Escape HTML entities
|
117
210
|
# @see Landline::Util.escape_html
|
118
211
|
def escape_html(text)
|
119
212
|
Landline::Util.escape_html(text)
|
120
213
|
end
|
121
214
|
|
215
|
+
# (in Landline::Probe context)
|
122
216
|
# Unescape HTML entities
|
123
217
|
# @see Landline::Util.escape_html
|
124
218
|
def unescape_html(text)
|
125
219
|
Landline::Util.unescape_html(text)
|
126
220
|
end
|
221
|
+
|
222
|
+
# (in Landline::Path context)
|
223
|
+
# Pass the requested environment to a different application
|
224
|
+
# @param application [#call] Rack application
|
225
|
+
# @return [Array(Integer, Hash{String => Object}, Object)] response
|
226
|
+
def call(application)
|
227
|
+
application.call(@origin.request.env)
|
228
|
+
end
|
229
|
+
|
230
|
+
private
|
231
|
+
|
232
|
+
def _verify_content_type(type)
|
233
|
+
return false unless request.headers['content-type']
|
234
|
+
|
235
|
+
value, opts = Landline::Util::ParserCommon.parse_value(
|
236
|
+
request.headers["content-type"]
|
237
|
+
)
|
238
|
+
if value == type and
|
239
|
+
request.input
|
240
|
+
[value, opts]
|
241
|
+
else
|
242
|
+
false
|
243
|
+
end
|
244
|
+
end
|
127
245
|
end
|
128
246
|
end
|
129
247
|
end
|
@@ -7,6 +7,7 @@ module Landline
|
|
7
7
|
module DSL
|
8
8
|
# Common methods for template contexts
|
9
9
|
module TemplateMethods
|
10
|
+
# (in Landline::Template context)
|
10
11
|
# Import a template part
|
11
12
|
# @param filepath [String, File] path to the file (or the file itself)
|
12
13
|
# @return [String] compiled template
|