landline 0.9.3 → 0.12.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/HACKING.md +0 -5
- data/README.md +73 -19
- data/lib/landline/app.rb +50 -0
- data/lib/landline/dsl/constructors_path.rb +21 -0
- data/lib/landline/dsl/constructors_probe.rb +4 -2
- data/lib/landline/dsl/methods_common.rb +2 -0
- data/lib/landline/dsl/methods_path.rb +46 -5
- data/lib/landline/dsl/methods_probe.rb +129 -11
- data/lib/landline/dsl/methods_template.rb +11 -1
- data/lib/landline/extensions/session.rb +98 -0
- data/lib/landline/extensions/websocket.rb +286 -0
- data/lib/landline/node.rb +3 -2
- data/lib/landline/path.rb +69 -23
- data/lib/landline/pattern_matching/glob.rb +1 -1
- data/lib/landline/pattern_matching/rematch.rb +1 -1
- data/lib/landline/probe/crosscall_handler.rb +25 -0
- data/lib/landline/probe/handler.rb +13 -17
- data/lib/landline/probe/serve_handler.rb +0 -1
- data/lib/landline/probe.rb +12 -0
- data/lib/landline/request.rb +57 -6
- data/lib/landline/response.rb +1 -1
- data/lib/landline/server.rb +43 -18
- data/lib/landline/template/erb.rb +1 -1
- data/lib/landline/template/erubi.rb +1 -1
- data/lib/landline/template.rb +8 -3
- data/lib/landline/util/cookie.rb +10 -3
- data/lib/landline/util/jwt.rb +82 -0
- data/lib/landline/util/lookup.rb +14 -0
- data/lib/landline/util/mime.rb +2 -1
- data/lib/landline/util/multipart.rb +7 -4
- data/lib/landline/util/parseutils.rb +13 -11
- data/lib/landline/util/query.rb +2 -0
- data/lib/landline.rb +5 -3
- metadata +9 -6
- data/LAYOUT.md +0 -59
data/lib/landline/request.rb
CHANGED
@@ -21,10 +21,10 @@ module Landline
|
|
21
21
|
@param = {}
|
22
22
|
@splat = []
|
23
23
|
# Traversal route. Public and writable.
|
24
|
-
@path = URI.decode_www_form_component(env["PATH_INFO"]
|
24
|
+
@path = URI.decode_www_form_component(env["PATH_INFO"])
|
25
25
|
# File serving path. Public and writable.
|
26
26
|
@filepath = "/"
|
27
|
-
# Encapsulates all rack variables.
|
27
|
+
# Encapsulates all rack variables. Is no longer private, but usually should not be used directly
|
28
28
|
@rack = init_rack_vars(env)
|
29
29
|
# Internal navigation states. Private.
|
30
30
|
@states = []
|
@@ -35,18 +35,21 @@ module Landline
|
|
35
35
|
# Run postprocessors
|
36
36
|
# @param response [Landline::Response]
|
37
37
|
def run_postprocessors(response)
|
38
|
-
@postprocessors.
|
38
|
+
@postprocessors.reverse_each do |postproc|
|
39
39
|
postproc.call(self, response)
|
40
40
|
end
|
41
|
+
@postprocessors = []
|
41
42
|
end
|
42
43
|
|
43
44
|
# Returns request body (if POST data exists)
|
45
|
+
# @note reads data from rack.input, which is not rewindable. .body data is memoized.
|
44
46
|
# @return [nil, String]
|
45
47
|
def body
|
46
48
|
@body ||= @rack.input&.read
|
47
49
|
end
|
48
50
|
|
49
51
|
# Returns raw Rack input object
|
52
|
+
# @note Rack IO is not always rewindable - if it is read once, the data is gone (i.e. request.body will return nothing).
|
50
53
|
# @return [IO] (May not entirely be compatible with IO, see Rack/SPEC.rdoc)
|
51
54
|
def input
|
52
55
|
@rack.input
|
@@ -62,10 +65,33 @@ module Landline
|
|
62
65
|
@path, @param, @splat, @filepath = @states.pop
|
63
66
|
end
|
64
67
|
|
68
|
+
# Checks if response stream can be partially hijacked
|
69
|
+
def hijack?
|
70
|
+
@_original_env['rack.hijack?']
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns full hijack callback
|
74
|
+
def hijack
|
75
|
+
@_original_env['rack.hijack']
|
76
|
+
end
|
77
|
+
|
78
|
+
# Reconstructs rack env after modification
|
79
|
+
def env
|
80
|
+
path = @path
|
81
|
+
@_original_env.merge(reconstruct_headers)
|
82
|
+
.merge({
|
83
|
+
'PATH_INFO' => path,
|
84
|
+
'REQUEST_PATH' => path,
|
85
|
+
'QUERY_STRING' => query.query,
|
86
|
+
'REQUEST_URI' => "#{path}?#{query.query}"
|
87
|
+
})
|
88
|
+
.merge(reconstruct_cookie)
|
89
|
+
end
|
90
|
+
|
65
91
|
attr_reader :request_method, :script_name, :path_info, :server_name,
|
66
92
|
:server_port, :server_protocol, :headers, :param, :splat,
|
67
|
-
:postprocessors, :
|
68
|
-
attr_accessor :path, :filepath
|
93
|
+
:postprocessors, :cookies, :rack
|
94
|
+
attr_accessor :path, :filepath, :query
|
69
95
|
|
70
96
|
private
|
71
97
|
|
@@ -117,7 +143,7 @@ module Landline
|
|
117
143
|
.freeze
|
118
144
|
end
|
119
145
|
|
120
|
-
#
|
146
|
+
# Initialize headers hash
|
121
147
|
# @param env [Hash]
|
122
148
|
# @return Hash
|
123
149
|
def init_headers(env)
|
@@ -131,5 +157,30 @@ module Landline
|
|
131
157
|
x.downcase.gsub("_", "-") if x.is_a? String
|
132
158
|
end.freeze
|
133
159
|
end
|
160
|
+
|
161
|
+
# Reconstruct headers
|
162
|
+
def reconstruct_headers
|
163
|
+
@headers.filter_map do |k, v|
|
164
|
+
next unless v
|
165
|
+
|
166
|
+
if !['content-type', 'content-length',
|
167
|
+
'remote-addr'].include?(k) && (k.is_a? String)
|
168
|
+
k = "http_#{k}"
|
169
|
+
end
|
170
|
+
k = k.upcase.gsub("-", "_")
|
171
|
+
[k, v]
|
172
|
+
end.to_h
|
173
|
+
end
|
174
|
+
|
175
|
+
# Reconstruct cookie string
|
176
|
+
def reconstruct_cookie
|
177
|
+
return {} if @cookies.empty?
|
178
|
+
|
179
|
+
{
|
180
|
+
"HTTP_COOKIE" => @cookies.map do |_, v|
|
181
|
+
v.finalize_short
|
182
|
+
end.join(";")
|
183
|
+
}
|
184
|
+
end
|
134
185
|
end
|
135
186
|
end
|
data/lib/landline/response.rb
CHANGED
data/lib/landline/server.rb
CHANGED
@@ -11,39 +11,64 @@ module Landline
|
|
11
11
|
# A specialized path that can be used directly as a Rack application.
|
12
12
|
class Server < Landline::Path
|
13
13
|
Context = ServerContext
|
14
|
-
|
15
14
|
# @param parent [Landline::Node, nil] Parent object to inherit properties to
|
16
15
|
# @param setup [#call] Setup block
|
17
|
-
def initialize(parent: nil, **
|
18
|
-
super("", parent: nil, **
|
16
|
+
def initialize(passthrough = nil, parent: nil, **opts, &setup)
|
17
|
+
super("", parent: nil, **opts, &setup)
|
19
18
|
return if parent
|
20
19
|
|
20
|
+
@passthrough = passthrough
|
21
|
+
setup_properties(parent: nil, **opts)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Rack ingress point.
|
25
|
+
# @param env [Hash]
|
26
|
+
# @return [Array(Integer,Hash,Array)]
|
27
|
+
def call(env)
|
28
|
+
request = Landline::Request.new(env)
|
29
|
+
|
30
|
+
response = handle_jumps(request)
|
31
|
+
request.run_postprocessors(response)
|
32
|
+
resp = response.finalize
|
33
|
+
if resp[1][:"x-cascade"] and resp[0] == 404 and @passthrough
|
34
|
+
@passthrough.call(request.env)
|
35
|
+
else
|
36
|
+
resp
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# Catch internal jumps
|
43
|
+
def handle_jumps(request)
|
44
|
+
response = Response.convert(catch(:finish) do
|
45
|
+
go(request)
|
46
|
+
end)
|
47
|
+
while response and
|
48
|
+
response.status == 307 and
|
49
|
+
response.headers.include? :"x-internal-jump"
|
50
|
+
response = Response.convert(catch(:finish) do
|
51
|
+
go(request)
|
52
|
+
end)
|
53
|
+
end
|
54
|
+
response
|
55
|
+
end
|
56
|
+
|
57
|
+
# Inititalization block for property setup
|
58
|
+
def setup_properties(*_args, **_opts)
|
21
59
|
{
|
22
60
|
"index" => [],
|
23
61
|
"handle.default" => proc do |code, backtrace: nil|
|
24
62
|
page = Landline::Util.default_error_page(code, backtrace)
|
25
63
|
headers = {
|
26
64
|
"content-length": page.bytesize,
|
27
|
-
"content-type": "text/html"
|
65
|
+
"content-type": "text/html",
|
66
|
+
"x-cascade": true
|
28
67
|
}
|
29
68
|
[headers, page]
|
30
69
|
end,
|
31
70
|
"path" => "/"
|
32
71
|
}.each { |k, v| @properties[k] = v unless @properties[k] }
|
33
72
|
end
|
34
|
-
|
35
|
-
# Rack ingress point.
|
36
|
-
# This should not be called under any circumstances twice in the same application,
|
37
|
-
# although server nesting for the purpose of creating virtual hosts is allowed.
|
38
|
-
# @param env [Hash]
|
39
|
-
# @return [Array(Integer,Hash,Array)]
|
40
|
-
def call(env)
|
41
|
-
request = Landline::Request.new(env)
|
42
|
-
response = catch(:finish) do
|
43
|
-
go(request)
|
44
|
-
end
|
45
|
-
request.run_postprocessors(response)
|
46
|
-
Response.convert(response).finalize
|
47
|
-
end
|
48
73
|
end
|
49
74
|
end
|
@@ -7,7 +7,7 @@ module Landline
|
|
7
7
|
module Templates
|
8
8
|
# ERB Template language adapter
|
9
9
|
class ERB < Landline::Template
|
10
|
-
#
|
10
|
+
# (see Landline::Template#new)
|
11
11
|
def initialize(input, vars = nil, parent:, filename:)
|
12
12
|
super
|
13
13
|
varname = "_part_#{SecureRandom.hex(10)}".to_sym
|
data/lib/landline/template.rb
CHANGED
@@ -86,9 +86,14 @@ module Landline
|
|
86
86
|
# ... (stub)
|
87
87
|
end
|
88
88
|
|
89
|
-
# Import a template from within current template
|
90
|
-
|
91
|
-
|
89
|
+
# Import a template from within current template.
|
90
|
+
# @param file [File] template file to import
|
91
|
+
# @return [Landline::Template] loaded tempalte
|
92
|
+
def import(file)
|
93
|
+
newtemp = self.class.new(file,
|
94
|
+
{},
|
95
|
+
parent: @parent,
|
96
|
+
filename: file.path)
|
92
97
|
newtemp.binding = @binding
|
93
98
|
newtemp
|
94
99
|
end
|
data/lib/landline/util/cookie.rb
CHANGED
@@ -4,9 +4,16 @@ require_relative 'parseutils'
|
|
4
4
|
require_relative 'errors'
|
5
5
|
require 'date'
|
6
6
|
require 'openssl'
|
7
|
+
require 'base64'
|
7
8
|
HeaderRegexp = Landline::Util::HeaderRegexp
|
8
9
|
ParserCommon = Landline::Util::ParserCommon
|
9
10
|
|
11
|
+
if RUBY_ENGINE == 'jruby' # fix for JRuby
|
12
|
+
OpenSSL::HMAC.define_singleton_method(:base64digest) do |*args|
|
13
|
+
Base64.strict_encode64(OpenSSL::HMAC.digest(*args)).strip
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
10
17
|
module Landline
|
11
18
|
# Utility class for handling cookies
|
12
19
|
class Cookie
|
@@ -22,11 +29,11 @@ module Landline
|
|
22
29
|
# @option params [String, Date] "expires"
|
23
30
|
# @raise Landline::ParsingError invalid cookie parameters
|
24
31
|
def initialize(key, value, params = {})
|
25
|
-
unless key.match?
|
32
|
+
unless key.match?(/\A#{HeaderRegexp::COOKIE_NAME}\z/o)
|
26
33
|
raise Landline::ParsingError, "invalid cookie key: #{key}"
|
27
34
|
end
|
28
35
|
|
29
|
-
unless value.match?
|
36
|
+
unless value.match?(/\A#{HeaderRegexp::COOKIE_VALUE}\z/o)
|
30
37
|
raise Landline::ParsingError, "invalid cookie value: #{value}"
|
31
38
|
end
|
32
39
|
|
@@ -81,7 +88,7 @@ module Landline
|
|
81
88
|
# @param sep [String] Hash separator
|
82
89
|
# @return [Boolean] whether value is signed and valid
|
83
90
|
def verify(key, algorithm: "sha256", sep: "&")
|
84
|
-
val, sig = @value.match(/\A(.*)#{sep}([A-Za-z0-9+\/=]+)\
|
91
|
+
val, sig = @value.match(/\A(.*)#{sep}([A-Za-z0-9+\/=]+)\z/).to_a[1..]
|
85
92
|
return false unless val and sig
|
86
93
|
|
87
94
|
sig == ::OpenSSL::HMAC.base64digest(algorithm, key, val)
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'openssl'
|
4
|
+
require 'json'
|
5
|
+
require 'base64'
|
6
|
+
|
7
|
+
if RUBY_ENGINE == 'jruby' # fix for JRuby
|
8
|
+
OpenSSL::HMAC.define_singleton_method(:base64digest) do |*args|
|
9
|
+
Base64.strict_encode64(OpenSSL::HMAC.digest(*args)).strip
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module Landline
|
14
|
+
module Util
|
15
|
+
# JSON Web Token construction class
|
16
|
+
class JWT
|
17
|
+
ALGO = {
|
18
|
+
"HS256" => proc do |data, secret|
|
19
|
+
Base64.urlsafe_encode64(
|
20
|
+
OpenSSL::HMAC.digest("SHA256", secret, data)
|
21
|
+
).gsub('=', '')
|
22
|
+
end,
|
23
|
+
"HS384" => proc do |data, secret|
|
24
|
+
Base64.urlsafe_encode64(
|
25
|
+
OpenSSL::HMAC.digest("SHA384", secret, data)
|
26
|
+
).gsub('=', '')
|
27
|
+
end,
|
28
|
+
"HS512" => proc do |data, secret|
|
29
|
+
Base64.urlsafe_encode64(
|
30
|
+
OpenSSL::HMAC.digest("SHA512", secret, data)
|
31
|
+
).gsub('=', '')
|
32
|
+
end
|
33
|
+
}.freeze
|
34
|
+
|
35
|
+
# Create a new JWT token wrapper
|
36
|
+
# @param data [Hash, Array] JSON-formattable data
|
37
|
+
# @param halgo [String] Name of the hash algorithm to use
|
38
|
+
def initialize(data, halgo = "HS256")
|
39
|
+
unless ALGO.include? halgo
|
40
|
+
raise StandardError, "hash algorithm #{halgo} not supported"
|
41
|
+
end
|
42
|
+
|
43
|
+
@halgo = halgo
|
44
|
+
@data = data
|
45
|
+
end
|
46
|
+
|
47
|
+
# Construct a string representation of the current token
|
48
|
+
# @param key [String]
|
49
|
+
# @return [String]
|
50
|
+
def make(key)
|
51
|
+
jsonheader = {
|
52
|
+
"alg": @halgo,
|
53
|
+
"typ": "JWT"
|
54
|
+
}.to_json
|
55
|
+
jsondata = @data.to_json
|
56
|
+
data = "#{base64(jsonheader)}.#{base64(jsondata)}"
|
57
|
+
"#{data}.#{ALGO[@halgo].call(data, key)}"
|
58
|
+
end
|
59
|
+
|
60
|
+
# Construct an object from string
|
61
|
+
# @param input [String]
|
62
|
+
# @param key [String]
|
63
|
+
# @return [JWT, nil] returns nil if verification couldn't complete
|
64
|
+
def self.from_string(input, key)
|
65
|
+
halgoj, dataj, sig = input.split(".")
|
66
|
+
halgo = JSON.parse(Base64.urlsafe_decode64(halgoj))["alg"]
|
67
|
+
return nil unless ALGO.include? halgo
|
68
|
+
return nil if ALGO[halgo].call("#{halgoj}.#{dataj}", key) != sig
|
69
|
+
|
70
|
+
new(JSON.parse(Base64.urlsafe_decode64(dataj)), halgo)
|
71
|
+
end
|
72
|
+
|
73
|
+
attr_accessor :data
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def base64(data)
|
78
|
+
Base64.urlsafe_encode64(data).gsub("=", "")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/landline/util/lookup.rb
CHANGED
@@ -33,5 +33,19 @@ module Landline
|
|
33
33
|
|
34
34
|
attr_accessor :parent
|
35
35
|
end
|
36
|
+
|
37
|
+
# Read-only lookup proxy
|
38
|
+
class LookupROProxy
|
39
|
+
def initialize(lookup)
|
40
|
+
@lookup = lookup
|
41
|
+
end
|
42
|
+
|
43
|
+
# Get a value by key
|
44
|
+
# @param key [#hash] key for value
|
45
|
+
# @return [Object,nil]
|
46
|
+
def [](key)
|
47
|
+
@lookup.[](key)
|
48
|
+
end
|
49
|
+
end
|
36
50
|
end
|
37
51
|
end
|
data/lib/landline/util/mime.rb
CHANGED
@@ -1267,7 +1267,8 @@ module Landline
|
|
1267
1267
|
}.freeze
|
1268
1268
|
|
1269
1269
|
# Get MIME type by file extension
|
1270
|
-
# @
|
1270
|
+
# @note This function does no checks on the file - simply renaming the file to a different extension will yield an invalid result. Do not use this to check uploaded files - preferably, use libmagic or proper mime type tools for Ruby.
|
1271
|
+
# @param file [String] filename
|
1271
1272
|
# @return [String] MIME type, defaults to "application/octet-stream"
|
1272
1273
|
def self.get_mime_type(file)
|
1273
1274
|
MIME[file.match(/\.(\w+)$/)&.[](1)] or "application/octet-stream"
|
@@ -9,6 +9,8 @@ require_relative 'html'
|
|
9
9
|
|
10
10
|
module Landline
|
11
11
|
module Util
|
12
|
+
FormPart = Struct.new(:data, :name, :filename,
|
13
|
+
:filetype, :tempfile, :headers)
|
12
14
|
# Valid element of form data with headers
|
13
15
|
# @!attribute headers [Hash] headers recevied from form data
|
14
16
|
# @!attribute name [String] name of the form part
|
@@ -16,8 +18,7 @@ module Landline
|
|
16
18
|
# @!attribute filename [String,nil] Original name of the sent file
|
17
19
|
# @!attribute filetype [String,nil] MIME-type of the file
|
18
20
|
# @!attribute tempfile [File,nil] Temporary file for storing sent file data.
|
19
|
-
FormPart
|
20
|
-
:filetype, :tempfile, :headers) do
|
21
|
+
class FormPart
|
21
22
|
# Is this form part a file or plain data?
|
22
23
|
# @return [Boolean]
|
23
24
|
def file?
|
@@ -135,7 +136,8 @@ module Landline
|
|
135
136
|
end
|
136
137
|
|
137
138
|
# Setup file metadata
|
138
|
-
# @
|
139
|
+
# @param part [Landline::Util::FormPart]
|
140
|
+
# @return [void]
|
139
141
|
def setup_file_meta(part)
|
140
142
|
part.name = part.headers.dig("content-disposition", 1, "name")
|
141
143
|
part.filename = part.headers.dig("content-disposition", 1, "filename")
|
@@ -144,7 +146,8 @@ module Landline
|
|
144
146
|
end
|
145
147
|
|
146
148
|
# Setup plain metadata
|
147
|
-
# @
|
149
|
+
# @param part [Landline::Util::FormPart]
|
150
|
+
# @return [void]
|
148
151
|
def setup_data_meta(part)
|
149
152
|
part.name = part.headers.dig("content-disposition", 1, "name")
|
150
153
|
end
|
@@ -8,28 +8,28 @@ module Landline
|
|
8
8
|
# (not exactly precise) Regular expressions for some RFC definitions
|
9
9
|
module HeaderRegexp
|
10
10
|
# Matches the RFC2616 definiton of token
|
11
|
-
TOKEN = /[!-~&&[^()<>@,;:\\"\/\[\]?={}\t]]
|
11
|
+
TOKEN = /[!-~&&[^()<>@,;:\\"\/\[\]?={}\t]]+/
|
12
12
|
# Matches the RFC2616 definition of quoted-string
|
13
|
-
QUOTED = /"[\x0-\x7E&&[^\x1-\x8\xb-\x1f]]*(?<!\\)"
|
13
|
+
QUOTED = /"[\x0-\x7E&&[^\x1-\x8\xb-\x1f]]*(?<!\\)"/
|
14
14
|
# Matches any CHAR except CTLs
|
15
|
-
PRINTCHAR = /[\x2-\x7E]
|
15
|
+
PRINTCHAR = /[\x2-\x7E]/
|
16
16
|
# Matches 1 or more CHARs excluding CTLs
|
17
|
-
PRINTABLE = /#{PRINTCHAR}+/o
|
17
|
+
PRINTABLE = /#{PRINTCHAR}+/o
|
18
18
|
# Matches the RFC6265 definition of a cookie-octet
|
19
|
-
COOKIE_OCTET = /[\x21-\x7E&&[^",;\\]]
|
20
|
-
COOKIE_VALUE = /(?:#{QUOTED}|#{COOKIE_OCTET})/o
|
19
|
+
COOKIE_OCTET = /[\x21-\x7E&&[^",;\\]]*/
|
20
|
+
COOKIE_VALUE = /(?:#{QUOTED}|#{COOKIE_OCTET})/o
|
21
21
|
COOKIE_NAME = TOKEN
|
22
22
|
# Matches the RFC6265 definition of cookie-pair.
|
23
23
|
# Captures name (1) and value (2).
|
24
|
-
COOKIE_PAIR = /\A(#{COOKIE_NAME})=(#{COOKIE_VALUE})\
|
24
|
+
COOKIE_PAIR = /\A(#{COOKIE_NAME})=(#{COOKIE_VALUE})\z/o
|
25
25
|
# Matches a very abstract definition of a quoted header paramter.
|
26
26
|
# Captures name (1) and value (2).
|
27
|
-
PARAM_QUOTED = /\A(#{TOKEN})=?(#{QUOTED}|#{PRINTCHAR}*)\
|
27
|
+
PARAM_QUOTED = /\A(#{TOKEN})=?(#{QUOTED}|#{PRINTCHAR}*)\z/o
|
28
28
|
# Matches a very abstract definition of a header parameter.
|
29
29
|
# Captures name (1) and value (2).
|
30
|
-
PARAM = /\A(#{TOKEN})=?(#{PRINTCHAR}*)\
|
30
|
+
PARAM = /\A(#{TOKEN})=?(#{PRINTCHAR}*)\z/o
|
31
31
|
# Specifically matches cookie parameters
|
32
|
-
COOKIE_PARAM = /\A(#{TOKEN})=?(#{QUOTED}|#{COOKIE_OCTET})\
|
32
|
+
COOKIE_PARAM = /\A(#{TOKEN})=?(#{QUOTED}|#{COOKIE_OCTET})\z/o
|
33
33
|
end
|
34
34
|
|
35
35
|
# Module for all things related to parsing HTTP and related syntax.
|
@@ -48,7 +48,9 @@ module Landline
|
|
48
48
|
# @param regexp [Regexp,nil] override param matching regexp
|
49
49
|
# @return [Array(String, Hash)]
|
50
50
|
def self.parse_value(input, sep: ";", unquote: false, regexp: nil)
|
51
|
-
parts = input.split(sep).map
|
51
|
+
parts = input.split(sep).map do |x|
|
52
|
+
URI.decode_www_form_component(x).strip
|
53
|
+
end
|
52
54
|
base = parts.shift
|
53
55
|
opts = parts.map do |raw|
|
54
56
|
key, value = raw.match(if regexp
|
data/lib/landline/util/query.rb
CHANGED
data/lib/landline.rb
CHANGED
@@ -1,19 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'landline/util/jwt'
|
3
4
|
require_relative 'landline/server'
|
4
5
|
require_relative 'landline/path'
|
5
6
|
require_relative 'landline/probe'
|
6
7
|
require_relative 'landline/request'
|
7
8
|
require_relative 'landline/response'
|
8
9
|
require_relative 'landline/template'
|
10
|
+
require_relative 'landline/app'
|
9
11
|
|
10
|
-
# Landline is a
|
12
|
+
# Landline is a backend framework born as a by-product of experimentation
|
11
13
|
module Landline
|
12
14
|
# Landline version
|
13
|
-
VERSION = '0.
|
15
|
+
VERSION = '0.12 "Concrete and Gold" (pre-alpha)'
|
14
16
|
|
15
17
|
# Landline branding and version
|
16
|
-
VLINE = "Landline/#{Landline::VERSION} (Ruby/#{RUBY_VERSION}/#{RUBY_RELEASE_DATE})\n"
|
18
|
+
VLINE = "Landline/#{Landline::VERSION} (Ruby/#{RUBY_VERSION}/#{RUBY_RELEASE_DATE})\n".freeze
|
17
19
|
|
18
20
|
# Landline copyright
|
19
21
|
COPYRIGHT = "Copyright 2023 Yessiest"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: landline
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yessiest
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-04-28 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
14
|
Landline is a no-hard-dependencies HTTP routing DSL that was made entirely for fun.
|
@@ -19,21 +19,22 @@ executables: []
|
|
19
19
|
extensions: []
|
20
20
|
extra_rdoc_files:
|
21
21
|
- HACKING.md
|
22
|
-
- LAYOUT.md
|
23
22
|
- LICENSE.md
|
24
23
|
- README.md
|
25
24
|
files:
|
26
25
|
- HACKING.md
|
27
|
-
- LAYOUT.md
|
28
26
|
- LICENSE.md
|
29
27
|
- README.md
|
30
28
|
- lib/landline.rb
|
29
|
+
- lib/landline/app.rb
|
31
30
|
- lib/landline/dsl/constructors_path.rb
|
32
31
|
- lib/landline/dsl/constructors_probe.rb
|
33
32
|
- lib/landline/dsl/methods_common.rb
|
34
33
|
- lib/landline/dsl/methods_path.rb
|
35
34
|
- lib/landline/dsl/methods_probe.rb
|
36
35
|
- lib/landline/dsl/methods_template.rb
|
36
|
+
- lib/landline/extensions/session.rb
|
37
|
+
- lib/landline/extensions/websocket.rb
|
37
38
|
- lib/landline/node.rb
|
38
39
|
- lib/landline/path.rb
|
39
40
|
- lib/landline/pattern_matching.rb
|
@@ -41,6 +42,7 @@ files:
|
|
41
42
|
- lib/landline/pattern_matching/rematch.rb
|
42
43
|
- lib/landline/pattern_matching/util.rb
|
43
44
|
- lib/landline/probe.rb
|
45
|
+
- lib/landline/probe/crosscall_handler.rb
|
44
46
|
- lib/landline/probe/handler.rb
|
45
47
|
- lib/landline/probe/http_method.rb
|
46
48
|
- lib/landline/probe/serve_handler.rb
|
@@ -53,6 +55,7 @@ files:
|
|
53
55
|
- lib/landline/util/cookie.rb
|
54
56
|
- lib/landline/util/errors.rb
|
55
57
|
- lib/landline/util/html.rb
|
58
|
+
- lib/landline/util/jwt.rb
|
56
59
|
- lib/landline/util/lookup.rb
|
57
60
|
- lib/landline/util/mime.rb
|
58
61
|
- lib/landline/util/multipart.rb
|
@@ -61,7 +64,7 @@ files:
|
|
61
64
|
- lib/landline/util/query.rb
|
62
65
|
homepage: https://adastra7.net/git/Yessiest/landline
|
63
66
|
licenses:
|
64
|
-
- AGPL-3.0
|
67
|
+
- AGPL-3.0-or-later
|
65
68
|
metadata: {}
|
66
69
|
post_install_message:
|
67
70
|
rdoc_options: []
|
@@ -78,7 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
81
|
- !ruby/object:Gem::Version
|
79
82
|
version: '0'
|
80
83
|
requirements: []
|
81
|
-
rubygems_version: 3.3
|
84
|
+
rubygems_version: 3.5.3
|
82
85
|
signing_key:
|
83
86
|
specification_version: 4
|
84
87
|
summary: Elegant HTTP DSL
|
data/LAYOUT.md
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
# Internal structure of Landline lib
|
2
|
-
|
3
|
-
Note: If you want to start hacking on Landline and extending it, follow this
|
4
|
-
layout as closely as possible.
|
5
|
-
|
6
|
-
## Core classes
|
7
|
-
|
8
|
-
These are core classes of Landline and they are loaded as soon as the library is loaded.
|
9
|
-
|
10
|
-
- Landline::Path [path.rb]
|
11
|
-
- Landline::PathBinding [path.rb]
|
12
|
-
- Landline::Probe [probe.rb]
|
13
|
-
- Landline::ProbeBinding [probe.rb]
|
14
|
-
- Landline::Node (parent of Path and Probe) [node.rb]
|
15
|
-
- Landline::Server (Rack application interface) [server.rb]
|
16
|
-
- Landline::ServerBinding [server.rb]
|
17
|
-
- Landline::Request (Rack request wrapper) [request.rb]
|
18
|
-
- Landline::Response (Rack response wrapper) [response.rb]
|
19
|
-
- Landline::Pattern [pattern\_matching.rb]
|
20
|
-
|
21
|
-
## Patterns
|
22
|
-
|
23
|
-
These are classes that Landline::Pattern can interface with to create Patterns.
|
24
|
-
|
25
|
-
- Landline::PatternMatching::ReMatch [pattern\_matching/rematch.rb]
|
26
|
-
- Landline::PatternMatching::Glob [pattern\_matching/glob.rb]
|
27
|
-
|
28
|
-
## DSL Method mixins
|
29
|
-
|
30
|
-
These are module mixins that add common methods to DSL bindings.
|
31
|
-
|
32
|
-
- Landline::DSL::PathConstructors [dsl/path\_constructors.rb]
|
33
|
-
|
34
|
-
## Utilities
|
35
|
-
|
36
|
-
These are self-contained classes and methods that add extra functionality to Landline.
|
37
|
-
|
38
|
-
- Landline::Util::Lookup [util/lookup.rb]
|
39
|
-
|
40
|
-
## Probe subclasses
|
41
|
-
|
42
|
-
These are reactive request handlers with their own semantics, if needed.
|
43
|
-
|
44
|
-
- Landline::Handler [probe/handler.rb]
|
45
|
-
- Landline::GETHandler [probe/http\_method.rb]
|
46
|
-
- Landline::POSTHandler [probe/http\_method.rb]
|
47
|
-
- Landline::HEADHandler [probe/http\_method.rb]
|
48
|
-
- Landline::PUTHandler [probe/http\_method.rb]
|
49
|
-
- Landline::DELETEHandler [probe/http\_method.rb]
|
50
|
-
- Landline::CONNECTHandler [probe/http\_method.rb]
|
51
|
-
- Landline::OPTIONSHandler [probe/http\_method.rb]
|
52
|
-
- Landline::TRACEHandler [probe/http\_method.rb]
|
53
|
-
- Landline::PATCHHandler [probe/http\_method.rb]
|
54
|
-
|
55
|
-
## Path subclasses
|
56
|
-
|
57
|
-
These are navigation handlers with their own semantics.
|
58
|
-
|
59
|
-
(currently none)
|