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.
@@ -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"].dup)
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. Should not be public.
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.each do |postproc|
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, :query, :cookies
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
- # Iniitalize headers hash
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
@@ -96,7 +96,7 @@ module Landline
96
96
  end
97
97
  end
98
98
 
99
- attr_accessor :status, :headers, :body
99
+ attr_accessor :status, :headers, :body, :cookies
100
100
 
101
101
  # Ensure response correctness
102
102
  # @param obj [String, Array, Landline::Response]
@@ -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, **args, &setup)
18
- super("", parent: nil, **args, &setup)
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
- # @see {Landline::Template#new}
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
@@ -7,7 +7,7 @@ module Landline
7
7
  module Templates
8
8
  # Erubi (ERB) template language adapter
9
9
  class Erubi < Landline::Template
10
- # @see {Landline::Template#new}
10
+ # (see Landline::Template#new)
11
11
  def initialize(input,
12
12
  vars = nil,
13
13
  **ext)
@@ -86,9 +86,14 @@ module Landline
86
86
  # ... (stub)
87
87
  end
88
88
 
89
- # Import a template from within current template
90
- def import(filepath)
91
- newtemp = self.class.new(filepath, {}, parent: @parent)
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
@@ -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? HeaderRegexp::COOKIE_NAME
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? HeaderRegexp::COOKIE_VALUE
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+\/=]+)\Z/).to_a[1..]
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
@@ -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
@@ -1267,7 +1267,8 @@ module Landline
1267
1267
  }.freeze
1268
1268
 
1269
1269
  # Get MIME type by file extension
1270
- # @param ext [String] filename
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 = Struct.new(:data, :name, :filename,
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
- # @part part [FormPart]
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
- # @part part [FormPart]
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]]+/.freeze
11
+ TOKEN = /[!-~&&[^()<>@,;:\\"\/\[\]?={}\t]]+/
12
12
  # Matches the RFC2616 definition of quoted-string
13
- QUOTED = /"[\x0-\x7E&&[^\x1-\x8\xb-\x1f]]*(?<!\\)"/.freeze
13
+ QUOTED = /"[\x0-\x7E&&[^\x1-\x8\xb-\x1f]]*(?<!\\)"/
14
14
  # Matches any CHAR except CTLs
15
- PRINTCHAR = /[\x2-\x7E]/.freeze
15
+ PRINTCHAR = /[\x2-\x7E]/
16
16
  # Matches 1 or more CHARs excluding CTLs
17
- PRINTABLE = /#{PRINTCHAR}+/o.freeze
17
+ PRINTABLE = /#{PRINTCHAR}+/o
18
18
  # Matches the RFC6265 definition of a cookie-octet
19
- COOKIE_OCTET = /[\x21-\x7E&&[^",;\\]]*/.freeze
20
- COOKIE_VALUE = /(?:#{QUOTED}|#{COOKIE_OCTET})/o.freeze
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})\Z/o.freeze
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}*)\Z/o.freeze
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}*)\Z/o.freeze
30
+ PARAM = /\A(#{TOKEN})=?(#{PRINTCHAR}*)\z/o
31
31
  # Specifically matches cookie parameters
32
- COOKIE_PARAM = /\A(#{TOKEN})=?(#{QUOTED}|#{COOKIE_OCTET})\Z/o.freeze
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 { |x| URI.decode_uri_component(x).strip }
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
@@ -8,6 +8,8 @@ module Landline
8
8
  # Query string parser
9
9
  class Query
10
10
  include Landline::Util::ParserSorting
11
+ attr_reader :query
12
+
11
13
  # @param query [String]
12
14
  def initialize(query)
13
15
  @query = query
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 hideously simple ruby web framework
12
+ # Landline is a backend framework born as a by-product of experimentation
11
13
  module Landline
12
14
  # Landline version
13
- VERSION = '0.9 "Moonsong" (beta/rewrite)'
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.9.3
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: 2023-09-25 00:00:00.000000000 Z
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.25
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)