diff --git a/.yardoc/checksums b/.yardoc/checksums index 1faf9f8..5ce3526 100644 --- a/.yardoc/checksums +++ b/.yardoc/checksums @@ -1,5 +1,21 @@ -lib/hyde.rb 6b22abff461426484b51291071193f02c2cf7850 -lib/hyde/pattern_matching.rb 84399fe8cc7f55b1da9a9348759a75ba1e6374e6 -lib/hyde/pattern_matching/glob.rb c8dab66857e6da3770f94ab26134ec27d262f240 +lib/hyde.rb 775368f05e89c7396fdf9a9c1f55e3537f8fba98 +lib/hyde/node.rb 93d92492390abb2b55649c6d027fa3a2cb8f2014 +lib/hyde/path.rb 280170523467824ac6ce310500fc88439808d59e +lib/hyde/probe.rb 994a5527bb30c713c1c70e56195ea6967ae39241 +lib/hyde/server.rb 3286219acc8606b432d12545e9ba3a57dd227473 +lib/hyde/request.rb 9baea24ae9975e3a26571878ed7e9da99889584f +lib/hyde/response.rb 0f0c107c7db883b308b81cbf5c0c4b7d5c90e7ba +lib/hyde/util/html.rb 3767a1632026ba555ae5517b59728b2e916b61de +lib/hyde/util/query.rb ffa6f9b6631277d7061f63dd36e4cb431a8169f5 +lib/hyde/util/lookup.rb 5b8e28a8471bb786f4e0a0d616885d238c806661 +lib/hyde/probe/binding.rb 1a83cfea5e7b620d075798c920dd4af3335871c7 +lib/hyde/probe/handler.rb 4d45e895a3bfee8e5234be3862c7e201772731b1 +lib/hyde/dsl/path_methods.rb 0369e370c594f0bd5c987c67791175eeaa8f9c21 +lib/hyde/pattern_matching.rb fe86f6529a2d22c128d9d3a74217862e9fa59c15 +lib/hyde/dsl/probe_methods.rb a9dd3ddbdf89875d79d5ca3e56fd3a261546dd25 +lib/hyde/probe/http_method.rb f5f6874998e4a581cd3673a06f3536c8a14e67c8 +lib/hyde/probe/serve_handler.rb 1690e7dd3f0abe9180a61d474bb89c0a765fc381 +lib/hyde/dsl/path_constructors.rb 97895412fc27eeb7f3fa379a85972c97a24d97bf +lib/hyde/pattern_matching/glob.rb 16595083bc8d6f7b98f4adda502a05bd411bc1ca lib/hyde/pattern_matching/util.rb 188dc7d5d9a9a6538a01943a83eb132c385dc092 lib/hyde/pattern_matching/rematch.rb 54a4f94791e68d85c38034d954e4c3174e01511b diff --git a/.yardoc/object_types b/.yardoc/object_types index 89279bc..e2ba358 100644 Binary files a/.yardoc/object_types and b/.yardoc/object_types differ diff --git a/.yardoc/objects/root.dat b/.yardoc/objects/root.dat index 547ea67..eb76e34 100644 Binary files a/.yardoc/objects/root.dat and b/.yardoc/objects/root.dat differ diff --git a/doc/Hyde.html b/doc/Hyde.html index 1dc921d..21d25e5 100644 --- a/doc/Hyde.html +++ b/doc/Hyde.html @@ -79,7 +79,7 @@
Defined in:
lib/hyde.rb,
- lib/hyde/pattern_matching.rb,
lib/hyde/pattern_matching/glob.rb,
lib/hyde/pattern_matching/util.rb,
lib/hyde/pattern_matching/rematch.rb
+ lib/hyde/node.rb,
lib/hyde/path.rb,
lib/hyde/probe.rb,
lib/hyde/server.rb,
lib/hyde/request.rb,
lib/hyde/response.rb,
lib/hyde/util/html.rb,
lib/hyde/util/query.rb,
lib/hyde/util/lookup.rb,
lib/hyde/probe/binding.rb,
lib/hyde/probe/handler.rb,
lib/hyde/dsl/path_methods.rb,
lib/hyde/pattern_matching.rb,
lib/hyde/dsl/probe_methods.rb,
lib/hyde/probe/http_method.rb,
lib/hyde/probe/serve_handler.rb,
lib/hyde/dsl/path_constructors.rb,
lib/hyde/pattern_matching/glob.rb,
lib/hyde/pattern_matching/util.rb,
lib/hyde/pattern_matching/rematch.rb
@@ -100,15 +100,74 @@

- Modules: PatternMatching + Modules: DSL, PatternMatching, Util - Classes: Path, PathBinding, Pattern + Classes: CONNECTHandler, DELETEHandler, GETHandler, HEADHandler, Handler, Node, OPTIONSHandler, PATCHHandler, POSTHandler, PUTHandler, Path, PathBinding, Pattern, Probe, ProbeBinding, Request, Response, ServeHandler, Server, ServerBinding, TRACEHandler

+ +

+ Constant Summary + collapse +

+ +
+ +
VERSION = +
+
+ +

Hyde version

+ + +
+
+
+ + +
+
+
'0.8 (beta/rewrite)'
+ +
VLINE = +
+
+ +

Hyde branding and version

+ + +
+
+
+ + +
+
+
"Hyde/#{Hyde::VERSION} (Ruby/#{RUBY_VERSION}/#{RUBY_RELEASE_DATE})\n"
+ + +
"Copyright 2023 Yessiest"
+ +
+ + @@ -120,7 +179,7 @@ diff --git a/doc/Hyde/CONNECTHandler.html b/doc/Hyde/CONNECTHandler.html new file mode 100644 index 0000000..9e86e2e --- /dev/null +++ b/doc/Hyde/CONNECTHandler.html @@ -0,0 +1,221 @@ + + + + + + + Class: Hyde::CONNECTHandler + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Class: Hyde::CONNECTHandler + + + +

+
+ +
+
Inherits:
+
+ GETHandler + + + show all + +
+
+ + + + + + + + + + + +
+
Defined in:
+
lib/hyde/probe/http_method.rb
+
+ +
+ +

Overview

+
+ +

Probe that executes callback on a CONNECT

+ + +
+
+
+ + +
+ +

+ Constant Summary + collapse +

+ +
+ +
METHOD = + +
+
"CONNECT"
+ +
+ + + + + + + +

Instance Attribute Summary

+ +

Attributes inherited from Handler

+

#request, #response

+ + + +

Attributes inherited from Probe

+

#properties

+ + + +

Attributes inherited from Node

+

#remap, #root

+ + + + + + + + + +

Method Summary

+ +

Methods inherited from GETHandler

+

#process

+ + + + + + + + + +

Methods inherited from Handler

+

#initialize, #process

+ + + + + + + + + +

Methods inherited from Probe

+

#initialize, #process

+ + + + + + + + + +

Methods inherited from Node

+

#go, #initialize, #process, #reject

+
+

Constructor Details

+ +

This class inherits a constructor from Hyde::Handler

+ +
+ + +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/DELETEHandler.html b/doc/Hyde/DELETEHandler.html new file mode 100644 index 0000000..98b97d2 --- /dev/null +++ b/doc/Hyde/DELETEHandler.html @@ -0,0 +1,221 @@ + + + + + + + Class: Hyde::DELETEHandler + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Class: Hyde::DELETEHandler + + + +

+
+ +
+
Inherits:
+
+ GETHandler + + + show all + +
+
+ + + + + + + + + + + +
+
Defined in:
+
lib/hyde/probe/http_method.rb
+
+ +
+ +

Overview

+
+ +

Probe that executes callback on a DELETE

+ + +
+
+
+ + +
+ +

+ Constant Summary + collapse +

+ +
+ +
METHOD = + +
+
"DELETE"
+ +
+ + + + + + + +

Instance Attribute Summary

+ +

Attributes inherited from Handler

+

#request, #response

+ + + +

Attributes inherited from Probe

+

#properties

+ + + +

Attributes inherited from Node

+

#remap, #root

+ + + + + + + + + +

Method Summary

+ +

Methods inherited from GETHandler

+

#process

+ + + + + + + + + +

Methods inherited from Handler

+

#initialize, #process

+ + + + + + + + + +

Methods inherited from Probe

+

#initialize, #process

+ + + + + + + + + +

Methods inherited from Node

+

#go, #initialize, #process, #reject

+
+

Constructor Details

+ +

This class inherits a constructor from Hyde::Handler

+ +
+ + +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/DSL.html b/doc/Hyde/DSL.html new file mode 100644 index 0000000..1279e94 --- /dev/null +++ b/doc/Hyde/DSL.html @@ -0,0 +1,128 @@ + + + + + + + Module: Hyde::DSL + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: Hyde::DSL + + + +

+
+ + + + + + + + + + + +
+
Defined in:
+
lib/hyde/dsl/path_methods.rb,
+ lib/hyde/dsl/probe_methods.rb,
lib/hyde/dsl/path_constructors.rb
+
+
+ +
+ +

Overview

+
+ +

Shared DSL methods

+ + +
+
+
+ + +

Defined Under Namespace

+

+ + + Modules: PathConstructors, PathMethods, ProbeMethods + + + + +

+ + + + + + + + + +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/DSL/PathConstructors.html b/doc/Hyde/DSL/PathConstructors.html new file mode 100644 index 0000000..83472b8 --- /dev/null +++ b/doc/Hyde/DSL/PathConstructors.html @@ -0,0 +1,995 @@ + + + + + + + Module: Hyde::DSL::PathConstructors + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: Hyde::DSL::PathConstructors + + + +

+
+ + + + + + + + + +
+
Included in:
+
PathBinding
+
+ + + +
+
Defined in:
+
lib/hyde/dsl/path_constructors.rb
+
+ +
+ +

Overview

+
+ +

Path (and subclasses) DSL constructors

+ + +
+
+
+ + +
+ + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + +
+

Instance Method Details

+ + +
+

+ + #connect(path, &setup) ⇒ Object + + + + + +

+
+ +

Create a new CONNECTHandler object

+ + +
+
+
+ + +
+ + + + +
+
+
+
+55
+56
+57
+
+
# File 'lib/hyde/dsl/path_constructors.rb', line 55
+
+def connect(path, &setup)
+  register(Hyde::CONNECTHandler.new(path, parent: @origin, &setup))
+end
+
+
+ +
+

+ + #delete(path, &setup) ⇒ Object + + + + + +

+
+ +

Create a new Hyde::DELETEHandler object

+ + +
+
+
+ + +
+ + + + +
+
+
+
+50
+51
+52
+
+
# File 'lib/hyde/dsl/path_constructors.rb', line 50
+
+def delete(path, &setup)
+  register(Hyde::DELETEHandler.new(path, parent: @origin, &setup))
+end
+
+
+ +
+

+ + #get(path, &setup) ⇒ Object + + + + + +

+
+ +

Create a new GETHandler object

+ + +
+
+
+ + +
+ + + + +
+
+
+
+30
+31
+32
+
+
# File 'lib/hyde/dsl/path_constructors.rb', line 30
+
+def get(path, &setup)
+  register(Hyde::GETHandler.new(path, parent: @origin, &setup))
+end
+
+
+ +
+

+ + #head(path, &setup) ⇒ Object + + + + + +

+
+ +

Create a new HEADHandler object

+ + +
+
+
+ + +
+ + + + +
+
+
+
+45
+46
+47
+
+
# File 'lib/hyde/dsl/path_constructors.rb', line 45
+
+def head(path, &setup)
+  register(Hyde::HEADHandler.new(path, parent: @origin, &setup))
+end
+
+
+ +
+

+ + #options(path, &setup) ⇒ Object + + + + + +

+
+ +

Create a new OPTIONSHandler object

+ + +
+
+
+ + +
+ + + + +
+
+
+
+70
+71
+72
+
+
# File 'lib/hyde/dsl/path_constructors.rb', line 70
+
+def options(path, &setup)
+  register(Hyde::OPTIONSHandler.new(path, parent: @origin, &setup))
+end
+
+
+ +
+

+ + #patch(path, &setup) ⇒ Object + + + + + +

+
+ +

Create a new PATCHHandler object

+ + +
+
+
+ + +
+ + + + +
+
+
+
+65
+66
+67
+
+
# File 'lib/hyde/dsl/path_constructors.rb', line 65
+
+def patch(path, &setup)
+  register(Hyde::PATCHHandler.new(path, parent: @origin, &setup))
+end
+
+
+ +
+

+ + #path(path, &setup) ⇒ Object + + + + + +

+
+ +

Create a new Path object

+ + +
+
+
+ + +
+ + + + +
+
+
+
+18
+19
+20
+21
+22
+
+
# File 'lib/hyde/dsl/path_constructors.rb', line 18
+
+def path(path, &setup)
+  # i don't know WHAT is wrong with this thing. it just is wrong.
+  # @sg-ignore
+  register(Hyde::Path.new(path, parent: @origin, &setup))
+end
+
+
+ +
+

+ + #post(path, &setup) ⇒ Object + + + + + +

+
+ +

create a new POSTHandler object

+ + +
+
+
+ + +
+ + + + +
+
+
+
+35
+36
+37
+
+
# File 'lib/hyde/dsl/path_constructors.rb', line 35
+
+def post(path, &setup)
+  register(Hyde::POSTHandler.new(path, parent: @origin, &setup))
+end
+
+
+ +
+

+ + #probe(path, &_setup) ⇒ Object + + + + + +

+
+ +

Create a new Probe object

+ + +
+
+
+ + +
+ + + + +
+
+
+
+25
+26
+27
+
+
# File 'lib/hyde/dsl/path_constructors.rb', line 25
+
+def probe(path, &_setup)
+  register(Hyde::Probe.new(path, parent: @origin))
+end
+
+
+ +
+

+ + #put(path, &setup) ⇒ Object + + + + + +

+
+ +

Create a new PUTHandler object

+ + +
+
+
+ + +
+ + + + +
+
+
+
+40
+41
+42
+
+
# File 'lib/hyde/dsl/path_constructors.rb', line 40
+
+def put(path, &setup)
+  register(Hyde::PUTHandler.new(path, parent: @origin, &setup))
+end
+
+
+ +
+

+ + #register(obj) ⇒ Object + + + + + +

+
+ +

Append a Node child object to the list of children

+ + +
+
+
+ + +
+ + + + +
+
+
+
+9
+10
+11
+12
+13
+14
+15
+
+
# File 'lib/hyde/dsl/path_constructors.rb', line 9
+
+def register(obj)
+  unless obj.is_a? Hyde::Node
+    raise StandardError, "register accepts node children only"
+  end
+
+  @origin.children.append(obj)
+end
+
+
+ +
+

+ + #serve(path) ⇒ Object + + + + + +

+
+ +

Create a new GETHandler that serves static files

+ + +
+
+
+ + +
+ + + + +
+
+
+
+75
+76
+77
+
+
# File 'lib/hyde/dsl/path_constructors.rb', line 75
+
+def serve(path)
+  register(Hyde::ServeHandler.new(path, parent: @origin))
+end
+
+
+ +
+

+ + #trace(path, &setup) ⇒ Object + + + + + +

+
+ +

Create a new TRACEHandler object

+ + +
+
+
+ + +
+ + + + +
+
+
+
+60
+61
+62
+
+
# File 'lib/hyde/dsl/path_constructors.rb', line 60
+
+def trace(path, &setup)
+  register(Hyde::TRACEHandler.new(path, parent: @origin, &setup))
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/DSL/PathMethods.html b/doc/Hyde/DSL/PathMethods.html new file mode 100644 index 0000000..2aba23c --- /dev/null +++ b/doc/Hyde/DSL/PathMethods.html @@ -0,0 +1,704 @@ + + + + + + + Module: Hyde::DSL::PathMethods + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: Hyde::DSL::PathMethods + + + +

+
+ + + + + + + + + +
+
Included in:
+
PathBinding
+
+ + + +
+
Defined in:
+
lib/hyde/dsl/path_methods.rb
+
+ +
+ +

Overview

+
+ +

Common path methods

+ + +
+
+
+ + +
+ + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + +
+

Instance Method Details

+ + +
+

+ + #filter(&block) {|request| ... } ⇒ Object + + + + + +

+
+ +

Add a filter to the path. Blocks path access if a filter returns false.

+ + +
+
+
+

Parameters:

+
    + +
  • + + block + + + (#call) + + + +
  • + +
+ +

Yield Parameters:

+ + +
+ + + + +
+
+
+
+55
+56
+57
+58
+
+
# File 'lib/hyde/dsl/path_methods.rb', line 55
+
+def filter(&block)
+  @origin.filter(&block)
+  block
+end
+
+
+ +
+

+ + #index(index) ⇒ Object + + + + + +

+
+ +

Set path index

+ + +
+
+
+

Parameters:

+
    + +
  • + + index + + + (Array, String) + + + +
  • + +
+ + +
+ + + + +
+
+
+
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+
+
# File 'lib/hyde/dsl/path_methods.rb', line 10
+
+def index(index)
+  case index
+  when Array
+    @origin.properties['index'] = index
+  when String
+    @origin.properties['index'] = [index]
+  else
+    raise StandardError, "index should be an Array or a String"
+  end
+end
+
+
+ +
+

+ + #postprocess(&block) {|request, response| ... } ⇒ Object + + + + + +

+
+ +

Add a postprocessor to the path.

+ + +
+
+
+

Parameters:

+
    + +
  • + + block + + + (#call) + + + +
  • + +
+ +

Yield Parameters:

+ + +
+ + + + +
+
+
+
+46
+47
+48
+49
+
+
# File 'lib/hyde/dsl/path_methods.rb', line 46
+
+def postprocess(&block)
+  @origin.postprocess(&block)
+  block
+end
+
+
+ +
+

+ + #preprocess(&block) {|request| ... } ⇒ Object + + + + + +

+
+ +

Add a preprocessor to the path. Does not modify path execution.

+ + +
+
+
+

Parameters:

+
    + +
  • + + block + + + (#call) + + + +
  • + +
+ +

Yield Parameters:

+ + +
+ + + + +
+
+
+
+37
+38
+39
+40
+
+
# File 'lib/hyde/dsl/path_methods.rb', line 37
+
+def preprocess(&block)
+  @origin.preprocess(&block)
+  block
+end
+
+
+ +
+

+ + #remap(path) ⇒ Object + + + + + +

+
+ +

Set root path (without appending matched part).

+ + +
+
+
+

Parameters:

+
    + +
  • + + path + + + (String) + + + + — +
    +

    ath [String

    +
    + +
  • + +
+ + +
+ + + + +
+
+
+
+29
+30
+31
+
+
# File 'lib/hyde/dsl/path_methods.rb', line 29
+
+def remap(path)
+  @origin.remap = path
+end
+
+
+ +
+

+ + #root(path) ⇒ Object + + + + + +

+
+ +

Set root path (appends matched part of the path).

+ + +
+
+
+

Parameters:

+
    + +
  • + + path + + + (String) + + + + — +
    +

    ath [String

    +
    + +
  • + +
+ + +
+ + + + +
+
+
+
+23
+24
+25
+
+
# File 'lib/hyde/dsl/path_methods.rb', line 23
+
+def root(path)
+  @origin.root = path
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/DSL/ProbeMethods.html b/doc/Hyde/DSL/ProbeMethods.html new file mode 100644 index 0000000..7d90e6c --- /dev/null +++ b/doc/Hyde/DSL/ProbeMethods.html @@ -0,0 +1,767 @@ + + + + + + + Module: Hyde::DSL::ProbeMethods + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: Hyde::DSL::ProbeMethods + + + +

+
+ + + + + + + + + +
+
Included in:
+
ProbeBinding
+
+ + + +
+
Defined in:
+
lib/hyde/dsl/probe_methods.rb
+
+ +
+ +

Overview

+
+ +

Common methods for Probe objects

+ + +
+
+
+ + +
+ + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + +
+

Instance Method Details

+ + +
+

+ + #bounceObject + + + + + +

+
+ +

Bounce request to the next handler

+ + +
+
+
+ +

Raises:

+
    + +
  • + + + (UncaughtThrowError) + + + + — +
    +

    throws :break to get out of the callback

    +
    + +
  • + +
+ +
+ + + + +
+
+
+
+31
+32
+33
+
+
# File 'lib/hyde/dsl/probe_methods.rb', line 31
+
+def bounce
+  throw :break
+end
+
+
+ +
+

+ + #die(errorcode, backtrace: nil) ⇒ Object + + + + + +

+
+ +

Stop execution and generate a boilerplate response with the given code

+ + +
+
+
+

Parameters:

+
    + +
  • + + errorcode + + + (Integer) + + + +
  • + +
  • + + backtrace + + + (Array(String), nil) + + + (defaults to: nil) + + +
  • + +
+ +

Raises:

+
    + +
  • + + + (UncaughtThrowError) + + + + — +
    +

    throws :finish to return back to Server

    +
    + +
  • + +
+ +
+ + + + +
+
+
+
+19
+20
+21
+22
+23
+24
+25
+26
+27
+
+
# File 'lib/hyde/dsl/probe_methods.rb', line 19
+
+def die(errorcode, backtrace: nil)
+  throw :finish, [errorcode].append(
+    *(@origin.properties["handle.#{errorcode}"] or
+      @origin.properties["handle.default"]).call(
+        errorcode,
+        backtrace: backtrace
+      )
+  )
+end
+
+
+ +
+

+ + #header(key, value) ⇒ Object + + + + + +

+
+ +

Set response header (generate response if one doesn’t exist yet)

+ + +
+
+
+

Parameters:

+
    + +
  • + + key + + + (String) + + + + — +
    +

    header name

    +
    + +
  • + +
  • + + value + + + (String) + + + + — +
    +

    header value

    +
    + +
  • + +
+ + +
+ + + + +
+
+
+
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+
+
# File 'lib/hyde/dsl/probe_methods.rb', line 47
+
+def header(key, value)
+  return status(value) if key.downcase == "status"
+
+  if key.match(/(?:[(),\/:;<=>?@\[\]{}"]|[^ -~])/)
+    raise StandardError, "header key has invalid characters"
+  end
+
+  if value.match(/[^ -~]/)
+    raise StandardError, "value key has invalid characters"
+  end
+
+  @origin.response = (@origin.response or Hyde::Response.new)
+  key = key.downcase
+  @origin.response.add_header(key, value)
+end
+
+
+ +
+

+ + #remove_header(key, value = nil) ⇒ Object + + + + + +

+
+ +

Delete a header value from the headers hash If no value is provided, deletes all key entries

+ + +
+
+
+

Parameters:

+
    + +
  • + + key + + + (String) + + + + — +
    +

    header name

    +
    + +
  • + +
  • + + value + + + (String, nil) + + + (defaults to: nil) + + + — +
    +

    header value

    +
    + +
  • + +
+ + +
+ + + + +
+
+
+
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+
+
# File 'lib/hyde/dsl/probe_methods.rb', line 67
+
+def remove_header(key, value = nil)
+  return unless @origin.response
+
+  return if key.downcase == "status"
+
+  if key.match(/(?:[(),\/:;<=>?@\[\]{}"]|[^ -~])/)
+    raise StandardError, "header key has invalid characters"
+  end
+
+  if value&.match(/[^ -~]/)
+    raise StandardError, "value key has invalid characters"
+  end
+
+  @origin.response.delete_header(key, value)
+end
+
+
+ +
+

+ + #requestHyde::Request + + + + + +

+
+ +

Get the current request

+ + +
+
+
+ +

Returns:

+ + +
+ + + + +
+
+
+
+11
+12
+13
+
+
# File 'lib/hyde/dsl/probe_methods.rb', line 11
+
+def request
+  @origin.request
+end
+
+
+ +
+

+ + #status(status) ⇒ Object + + + + Also known as: + code + + + + +

+
+ +

Set response status (generate response if one doesn’t exist yet)

+ + +
+
+
+

Parameters:

+
    + +
  • + + status + + + (Integer) + + + + — +
    +

    http status code

    +
    + +
  • + +
+ + +
+ + + + +
+
+
+
+37
+38
+39
+40
+
+
# File 'lib/hyde/dsl/probe_methods.rb', line 37
+
+def status(status)
+  @response = (@response or Hyde::Response.new)
+  @response.status = status
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/GETHandler.html b/doc/Hyde/GETHandler.html new file mode 100644 index 0000000..96dca45 --- /dev/null +++ b/doc/Hyde/GETHandler.html @@ -0,0 +1,366 @@ + + + + + + + Class: Hyde::GETHandler + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Class: Hyde::GETHandler + + + +

+
+ +
+
Inherits:
+
+ Handler + + + show all + +
+
+ + + + + + + + + + + +
+
Defined in:
+
lib/hyde/probe/http_method.rb
+
+ +
+ +

Overview

+
+ +

Probe that executes callback on a GET

+ + +
+
+
+ + +
+ + +

+ Constant Summary + collapse +

+ +
+ +
METHOD = + +
+
"GET"
+ +
+ + + + + + + +

Instance Attribute Summary

+ +

Attributes inherited from Handler

+

#request, #response

+ + + +

Attributes inherited from Probe

+

#properties

+ + + +

Attributes inherited from Node

+

#remap, #root

+ + + +

+ Instance Method Summary + collapse +

+ + + + + + + + + + + + + +

Methods inherited from Handler

+

#initialize

+ + + + + + + + + +

Methods inherited from Probe

+

#initialize

+ + + + + + + + + +

Methods inherited from Node

+

#go, #initialize, #reject

+
+

Constructor Details

+ +

This class inherits a constructor from Hyde::Handler

+ +
+ + +
+

Instance Method Details

+ + +
+

+ + #process(request) ⇒ Boolean + + + + + +

+
+ +

Method callback on successful request navigation. Runs block supplied with object initialization. Request’s #splat and #param are passed to block.

+ +

Callback’s returned should be one of viable responses:

+
  • +

    Response object

    +
  • +

    An array that matches Rack return form

    +
  • +

    An array that matches old (Rack 2.x) return form

    +
  • +

    A string (returned as HTML with code 200)

    +
  • +

    false (bounces the request to next handler)

    +
+ + +
+
+
+

Parameters:

+ + +

Returns:

+
    + +
  • + + + (Boolean) + + + + — +
    +

    true if further navigation is possible

    +
    + +
  • + +
+

Raises:

+
    + +
  • + + + (UncaughtThrowError) + + + + — +
    +

    may raise if die() is called.

    +
    + +
  • + +
+ +
+ + + + +
+
+
+
+26
+27
+28
+29
+30
+31
+32
+
+
# File 'lib/hyde/probe/http_method.rb', line 26
+
+def process(request)
+  unless request.request_method.casecmp(self.class::METHOD).zero?
+    return false
+  end
+
+  super(request)
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/HEADHandler.html b/doc/Hyde/HEADHandler.html new file mode 100644 index 0000000..23d6000 --- /dev/null +++ b/doc/Hyde/HEADHandler.html @@ -0,0 +1,221 @@ + + + + + + + Class: Hyde::HEADHandler + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Class: Hyde::HEADHandler + + + +

+
+ +
+
Inherits:
+
+ GETHandler + + + show all + +
+
+ + + + + + + + + + + +
+
Defined in:
+
lib/hyde/probe/http_method.rb
+
+ +
+ +

Overview

+
+ +

Probe that executes callback on a HEAD

+ + +
+
+
+ + +
+ +

+ Constant Summary + collapse +

+ +
+ +
METHOD = + +
+
"HEAD"
+ +
+ + + + + + + +

Instance Attribute Summary

+ +

Attributes inherited from Handler

+

#request, #response

+ + + +

Attributes inherited from Probe

+

#properties

+ + + +

Attributes inherited from Node

+

#remap, #root

+ + + + + + + + + +

Method Summary

+ +

Methods inherited from GETHandler

+

#process

+ + + + + + + + + +

Methods inherited from Handler

+

#initialize, #process

+ + + + + + + + + +

Methods inherited from Probe

+

#initialize, #process

+ + + + + + + + + +

Methods inherited from Node

+

#go, #initialize, #process, #reject

+
+

Constructor Details

+ +

This class inherits a constructor from Hyde::Handler

+ +
+ + +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/Handler.html b/doc/Hyde/Handler.html new file mode 100644 index 0000000..97826db --- /dev/null +++ b/doc/Hyde/Handler.html @@ -0,0 +1,609 @@ + + + + + + + Class: Hyde::Handler + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Class: Hyde::Handler + + + +

+
+ +
+
Inherits:
+
+ Probe + +
    +
  • Object
  • + + + + + + + +
+ show all + +
+
+ + + + + + + + + + + +
+
Defined in:
+
lib/hyde/probe/handler.rb
+
+ +
+ +

Overview

+
+ +

Probe that executes a callback on request

+ + +
+
+
+ + +
+

Direct Known Subclasses

+

GETHandler

+
+ + + + +

Instance Attribute Summary collapse

+ + + + + + +

Attributes inherited from Probe

+

#properties

+ + + +

Attributes inherited from Node

+

#remap, #root

+ + + +

+ Instance Method Summary + collapse +

+ + + + + + + + + + + + + + + + + + + +

Methods inherited from Node

+

#go, #reject

+
+

Constructor Details

+ +
+

+ + #initialize(path, parent:, &exec) ⇒ Handler + + + + + +

+
+ +

Returns a new instance of Handler.

+ + +
+
+
+

Parameters:

+
    + +
  • + + path + + + (Object) + + + +
  • + +
  • + + parent + + + (Hyde::Node) + + + +
  • + +
  • + + exec + + + (#call) + + + +
  • + +
+ + +
+ + + + +
+
+
+
+12
+13
+14
+15
+16
+17
+
+
# File 'lib/hyde/probe/handler.rb', line 12
+
+def initialize(path, parent:, &exec)
+  super(path, parent: parent)
+  @callback = exec
+  @binding = Hyde::ProbeBinding.new(self)
+  @response = nil
+end
+
+
+ +
+ +
+

Instance Attribute Details

+ + + +
+

+ + #requestObject (readonly) + + + + + +

+
+ +

Returns the value of attribute request.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+20
+21
+22
+
+
# File 'lib/hyde/probe/handler.rb', line 20
+
+def request
+  @request
+end
+
+
+ + + +
+

+ + #responseObject + + + + + +

+
+ +

Returns the value of attribute response.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+19
+20
+21
+
+
# File 'lib/hyde/probe/handler.rb', line 19
+
+def response
+  @response
+end
+
+
+ +
+ + +
+

Instance Method Details

+ + +
+

+ + #process(request) ⇒ Boolean + + + + + +

+
+ +

Method callback on successful request navigation. Runs block supplied with object initialization. Request’s #splat and #param are passed to block.

+ +

Callback’s returned should be one of viable responses:

+
  • +

    Response object

    +
  • +

    An array that matches Rack return form

    +
  • +

    An array that matches old (Rack 2.x) return form

    +
  • +

    A string (returned as HTML with code 200)

    +
  • +

    false (bounces the request to next handler)

    +
+ + +
+
+
+

Parameters:

+ + +

Returns:

+
    + +
  • + + + (Boolean) + + + + — +
    +

    true if further navigation is possible

    +
    + +
  • + +
+

Raises:

+
    + +
  • + + + (UncaughtThrowError) + + + + — +
    +

    may raise if die() is called.

    +
    + +
  • + +
+ +
+ + + + +
+
+
+
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+
+
# File 'lib/hyde/probe/handler.rb', line 36
+
+def process(request)
+  @response = nil
+  return reject(request) unless request.path.match?(/^\/?$/)
+
+  @request = request
+  response = catch(:break) do
+    @binding.instance_exec(*request.splat,
+                           **request.param,
+                           &@callback)
+  end
+  return false unless response
+
+  if @response and [String, File, IO].include? response.class
+    @response.body = response
+    throw :finish, @response
+  end
+  throw :finish, response
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/Node.html b/doc/Hyde/Node.html new file mode 100644 index 0000000..80a0c21 --- /dev/null +++ b/doc/Hyde/Node.html @@ -0,0 +1,714 @@ + + + + + + + Class: Hyde::Node + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Class: Hyde::Node + Abstract + + +

+
+ +
+
Inherits:
+
+ Object + +
    +
  • Object
  • + + + +
+ show all + +
+
+ + + + + + + + + + + +
+
Defined in:
+
lib/hyde/node.rb
+
+ +
+ +

Overview

+
+
+ This class is abstract. +
+
+ +

Abstract class that reacts to request navigation. Does nothing by default, behaviour should be overriden through #reject and #process

+ + +
+
+
+ + +
+

Direct Known Subclasses

+

Path, Probe

+
+ + + + +

Instance Attribute Summary collapse

+ + + + + + +

+ Instance Method Summary + collapse +

+ + + + +
+

Constructor Details

+ +
+

+ + #initialize(path, parent:) ⇒ Node + + + + + +

+
+ +

Returns a new instance of Node.

+ + +
+
+
+

Parameters:

+
    + +
  • + + path + + + (Object) + + + +
  • + +
+ + +
+ + + + +
+
+
+
+12
+13
+14
+15
+16
+17
+
+
# File 'lib/hyde/node.rb', line 12
+
+def initialize(path, parent:)
+  @pattern = Pattern.new(path).freeze
+  @properties = Hyde::Util::Lookup.new(parent&.properties)
+  @root = nil
+  @remap = false
+end
+
+
+ +
+ +
+

Instance Attribute Details

+ + + +
+

+ + #remapObject + + + + + +

+
+ +

Returns the value of attribute remap.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+69
+70
+71
+
+
# File 'lib/hyde/node.rb', line 69
+
+def remap
+  @remap
+end
+
+
+ + + +
+

+ + #rootObject + + + + + +

+
+ +

Returns the value of attribute root.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+69
+70
+71
+
+
# File 'lib/hyde/node.rb', line 69
+
+def root
+  @root
+end
+
+
+ +
+ + +
+

Instance Method Details

+ + +
+

+ + #go(request) ⇒ Boolean + + + + + +

+
+ +

Try to navigate the path. Run method callback in response.

+ + +
+
+
+

Parameters:

+ + +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+
+
# File 'lib/hyde/node.rb', line 38
+
+def go(request)
+  # rejected at pattern
+  return reject(request) unless @pattern.match?(request.path)
+
+  request.push_state
+  path, splat, param = @pattern.match(request.path)
+  do_filepath(request, request.path.delete_suffix(path))
+  request.path = path
+  request.splat.append(*splat)
+  request.param.merge!(param)
+  value = process(request)
+  # rejected at callback - restore state
+  request.pop_state unless value
+  # finally, return process value
+  value
+end
+
+
+ +
+

+ + #process(_request) ⇒ Object + + + + + +

+
+ +

Method callback on successful request navigation

+ + +
+
+
+

Parameters:

+ + +

Returns:

+
    + +
  • + + + + + + + +
    +

    true

    +
    + +
  • + +
+ +
+ + + + +
+
+
+
+65
+66
+67
+
+
# File 'lib/hyde/node.rb', line 65
+
+def process(_request)
+  true
+end
+
+
+ +
+

+ + #reject(_request) ⇒ Object + + + + + +

+
+ +

Method callback on failed request navigation

+ + +
+
+
+

Parameters:

+ + +

Returns:

+
    + +
  • + + + + + + + +
    +

    false

    +
    + +
  • + +
+ +
+ + + + +
+
+
+
+58
+59
+60
+
+
# File 'lib/hyde/node.rb', line 58
+
+def reject(_request)
+  false
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/OPTIONSHandler.html b/doc/Hyde/OPTIONSHandler.html new file mode 100644 index 0000000..22312de --- /dev/null +++ b/doc/Hyde/OPTIONSHandler.html @@ -0,0 +1,221 @@ + + + + + + + Class: Hyde::OPTIONSHandler + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Class: Hyde::OPTIONSHandler + + + +

+
+ +
+
Inherits:
+
+ GETHandler + + + show all + +
+
+ + + + + + + + + + + +
+
Defined in:
+
lib/hyde/probe/http_method.rb
+
+ +
+ +

Overview

+
+ +

Probe that executes callback on a OPTIONS

+ + +
+
+
+ + +
+ +

+ Constant Summary + collapse +

+ +
+ +
METHOD = + +
+
"OPTIONS"
+ +
+ + + + + + + +

Instance Attribute Summary

+ +

Attributes inherited from Handler

+

#request, #response

+ + + +

Attributes inherited from Probe

+

#properties

+ + + +

Attributes inherited from Node

+

#remap, #root

+ + + + + + + + + +

Method Summary

+ +

Methods inherited from GETHandler

+

#process

+ + + + + + + + + +

Methods inherited from Handler

+

#initialize, #process

+ + + + + + + + + +

Methods inherited from Probe

+

#initialize, #process

+ + + + + + + + + +

Methods inherited from Node

+

#go, #initialize, #process, #reject

+
+

Constructor Details

+ +

This class inherits a constructor from Hyde::Handler

+ +
+ + +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/PATCHHandler.html b/doc/Hyde/PATCHHandler.html new file mode 100644 index 0000000..0b44079 --- /dev/null +++ b/doc/Hyde/PATCHHandler.html @@ -0,0 +1,221 @@ + + + + + + + Class: Hyde::PATCHHandler + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Class: Hyde::PATCHHandler + + + +

+
+ +
+
Inherits:
+
+ GETHandler + + + show all + +
+
+ + + + + + + + + + + +
+
Defined in:
+
lib/hyde/probe/http_method.rb
+
+ +
+ +

Overview

+
+ +

Probe that executes callback on a PATCH

+ + +
+
+
+ + +
+ +

+ Constant Summary + collapse +

+ +
+ +
METHOD = + +
+
"PATCH"
+ +
+ + + + + + + +

Instance Attribute Summary

+ +

Attributes inherited from Handler

+

#request, #response

+ + + +

Attributes inherited from Probe

+

#properties

+ + + +

Attributes inherited from Node

+

#remap, #root

+ + + + + + + + + +

Method Summary

+ +

Methods inherited from GETHandler

+

#process

+ + + + + + + + + +

Methods inherited from Handler

+

#initialize, #process

+ + + + + + + + + +

Methods inherited from Probe

+

#initialize, #process

+ + + + + + + + + +

Methods inherited from Node

+

#go, #initialize, #process, #reject

+
+

Constructor Details

+ +

This class inherits a constructor from Hyde::Handler

+ +
+ + +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/POSTHandler.html b/doc/Hyde/POSTHandler.html new file mode 100644 index 0000000..debc523 --- /dev/null +++ b/doc/Hyde/POSTHandler.html @@ -0,0 +1,221 @@ + + + + + + + Class: Hyde::POSTHandler + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Class: Hyde::POSTHandler + + + +

+
+ +
+
Inherits:
+
+ GETHandler + + + show all + +
+
+ + + + + + + + + + + +
+
Defined in:
+
lib/hyde/probe/http_method.rb
+
+ +
+ +

Overview

+
+ +

Probe that executes callback on a POST

+ + +
+
+
+ + +
+ +

+ Constant Summary + collapse +

+ +
+ +
METHOD = + +
+
"POST"
+ +
+ + + + + + + +

Instance Attribute Summary

+ +

Attributes inherited from Handler

+

#request, #response

+ + + +

Attributes inherited from Probe

+

#properties

+ + + +

Attributes inherited from Node

+

#remap, #root

+ + + + + + + + + +

Method Summary

+ +

Methods inherited from GETHandler

+

#process

+ + + + + + + + + +

Methods inherited from Handler

+

#initialize, #process

+ + + + + + + + + +

Methods inherited from Probe

+

#initialize, #process

+ + + + + + + + + +

Methods inherited from Node

+

#go, #initialize, #process, #reject

+
+

Constructor Details

+ +

This class inherits a constructor from Hyde::Handler

+ +
+ + +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/PUTHandler.html b/doc/Hyde/PUTHandler.html new file mode 100644 index 0000000..3989021 --- /dev/null +++ b/doc/Hyde/PUTHandler.html @@ -0,0 +1,221 @@ + + + + + + + Class: Hyde::PUTHandler + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Class: Hyde::PUTHandler + + + +

+
+ +
+
Inherits:
+
+ GETHandler + + + show all + +
+
+ + + + + + + + + + + +
+
Defined in:
+
lib/hyde/probe/http_method.rb
+
+ +
+ +

Overview

+
+ +

Probe that executes callback on a PUT

+ + +
+
+
+ + +
+ +

+ Constant Summary + collapse +

+ +
+ +
METHOD = + +
+
"PUT"
+ +
+ + + + + + + +

Instance Attribute Summary

+ +

Attributes inherited from Handler

+

#request, #response

+ + + +

Attributes inherited from Probe

+

#properties

+ + + +

Attributes inherited from Node

+

#remap, #root

+ + + + + + + + + +

Method Summary

+ +

Methods inherited from GETHandler

+

#process

+ + + + + + + + + +

Methods inherited from Handler

+

#initialize, #process

+ + + + + + + + + +

Methods inherited from Probe

+

#initialize, #process

+ + + + + + + + + +

Methods inherited from Node

+

#go, #initialize, #process, #reject

+
+

Constructor Details

+ +

This class inherits a constructor from Hyde::Handler

+ +
+ + +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/Path.html b/doc/Hyde/Path.html index 5877c85..b2340da 100644 --- a/doc/Hyde/Path.html +++ b/doc/Hyde/Path.html @@ -69,11 +69,13 @@
Inherits:
- Object + Node @@ -94,24 +96,808 @@
Defined in:
-
lib/hyde.rb
+
lib/hyde/path.rb
+

Overview

+
+ +

Primary building block of request navigation.

+ + +
+
+
+ + +
+

Direct Known Subclasses

+

Server

+
+ + +

+ Constant Summary + collapse +

+ +
+ +
Binding = + +
+
Hyde::PathBinding
+ +
+ +

Instance Attribute Summary collapse

+ + + +

Attributes inherited from Node

+

#remap, #root

+ +

+ Instance Method Summary + collapse +

+ + + + + + + + + + + + + +

Methods inherited from Node

+

#go, #reject

+
+

Constructor Details

+ +
+

+ + #initialize(path, parent:, &setup) ⇒ Path + + + + + +

+
+ +

Returns a new instance of Path.

+ + +
+
+
+

Parameters:

+
    + +
  • + + path + + + (Object) + + + + — +
    +

    Object to generate Hyde::Pattern from

    +
    + +
  • + +
  • + + parent + + + (Hyde::Node) + + + + — +
    +

    Parent object to inherit properties to

    +
    + +
  • + +
  • + + setup + + + (#call) + + + + — +
    +

    Setup block

    +
    + +
  • + +
+ + +
+ + + + +
+
+
+
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+
+
# File 'lib/hyde/path.rb', line 27
+
+def initialize(path, parent:, &setup)
+  super(path, parent: parent)
+  # Child nodes array
+  @children = []
+  # Arrays of preprocessors, postprocessors and filters
+  @preprocessors = []
+  @postprocessors = []
+  @filters = []
+
+  binding = Binding.new(self)
+  binding.instance_exec(&setup)
+end
+
+
+ +
+ +
+

Instance Attribute Details

+ + + +
+

+ + #childrenObject (readonly) + + + + + +

+
+ +

Returns the value of attribute children.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+86
+87
+88
+
+
# File 'lib/hyde/path.rb', line 86
+
+def children
+  @children
+end
+
+
+ + + +
+

+ + #propertiesObject (readonly) + + + + + +

+
+ +

Returns the value of attribute properties.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+86
+87
+88
+
+
# File 'lib/hyde/path.rb', line 86
+
+def properties
+  @properties
+end
+
+
+ +
+ + +
+

Instance Method Details

+ + +
+

+ + #filter(&block) {|request| ... } ⇒ Object + + + + + +

+
+ +

Add a filter to the path. Blocks path access if a filter returns false.

+ + +
+
+
+

Parameters:

+
    + +
  • + + block + + + (#call) + + + +
  • + +
+ +

Yield Parameters:

+ + +
+ + + + +
+
+
+
+82
+83
+84
+
+
# File 'lib/hyde/path.rb', line 82
+
+def filter(&block)
+  @filters.append(block)
+end
+
+
+ +
+

+ + #postprocess(&block) {|request, response| ... } ⇒ Object + + + + + +

+
+ +

Add a postprocessor to the path.

+ + +
+
+
+

Parameters:

+
    + +
  • + + block + + + (#call) + + + +
  • + +
+ +

Yield Parameters:

+ + +
+ + + + +
+
+
+
+74
+75
+76
+
+
# File 'lib/hyde/path.rb', line 74
+
+def postprocess(&block)
+  @postprocessors.append(block)
+end
+
+
+ +
+

+ + #preprocess(&block) {|request| ... } ⇒ Object + + + + + +

+
+ +

Add a preprocessor to the path. Does not modify path execution.

+ + +
+
+
+

Parameters:

+
    + +
  • + + block + + + (#call) + + + +
  • + +
+ +

Yield Parameters:

+ + +
+ + + + +
+
+
+
+66
+67
+68
+
+
# File 'lib/hyde/path.rb', line 66
+
+def preprocess(&block)
+  @preprocessors.append(block)
+end
+
+
+ +
+

+ + #process(request) ⇒ Boolean + + + + + +

+
+ +

Method callback on successful request navigation. Finds the next appropriate path to go to.

+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + + — +
    +

    true if further navigation will be done

    +
    + +
  • + +
+

Raises:

+
    + +
  • + + + (UncaughtThrowError) + + + + — +
    +

    by default throws :response if no matches found.

    +
    + +
  • + +
+ +
+ + + + +
+
+
+
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+
+
# File 'lib/hyde/path.rb', line 44
+
+def process(request)
+  return false unless run_filters(request)
+
+  run_preprocessors(request)
+  enqueue_postprocessors(request)
+  @children.each do |x|
+    if (value = x.go(request))
+      return value
+    end
+  end
+  value = index(request)
+  return value if value
+
+  _die(404)
+rescue StandardError => e
+  _die(500, backtrace: [e.to_s] + e.backtrace)
+end
+
+
+ +
+ diff --git a/doc/Hyde/PathBinding.html b/doc/Hyde/PathBinding.html index 79b7d40..3bb71a0 100644 --- a/doc/Hyde/PathBinding.html +++ b/doc/Hyde/PathBinding.html @@ -87,6 +87,11 @@ +
+
Includes:
+
DSL::PathConstructors, DSL::PathMethods
+
+ @@ -94,24 +99,143 @@
Defined in:
-
lib/hyde.rb
+
lib/hyde/path.rb
+

Overview

+
+ +

Protected interface that provides DSL context for setup block.

+ + +
+
+
+ + +
+

Direct Known Subclasses

+

ServerBinding

+
+ + +

+ Instance Method Summary + collapse +

+ + + + + + + + + + + + +

Methods included from DSL::PathMethods

+

#filter, #index, #postprocess, #preprocess, #remap, #root

+ + + + + + + + + +

Methods included from DSL::PathConstructors

+

#connect, #delete, #get, #head, #options, #patch, #path, #post, #probe, #put, #register, #serve, #trace

+
+

Constructor Details

+ +
+

+ + #initialize(path) ⇒ PathBinding + + + + + +

+
+ +

Returns a new instance of PathBinding.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+15
+16
+17
+
+
# File 'lib/hyde/path.rb', line 15
+
+def initialize(path)
+  @origin = path
+end
+
+
+ +
diff --git a/doc/Hyde/Pattern.html b/doc/Hyde/Pattern.html index b3afed9..af2693e 100644 --- a/doc/Hyde/Pattern.html +++ b/doc/Hyde/Pattern.html @@ -275,13 +275,13 @@
 
 
+16
 17
 18
-19
-20
+19 -
# File 'lib/hyde/pattern_matching.rb', line 17
+      
# File 'lib/hyde/pattern_matching.rb', line 16
 
 def initialize(pattern)
   @pattern = patternify(pattern)
@@ -379,6 +379,7 @@
       
 
 
+35
 36
 37
 38
@@ -389,11 +390,10 @@
 43
 44
 45
-46
-47
+46
-
# File 'lib/hyde/pattern_matching.rb', line 36
+      
# File 'lib/hyde/pattern_matching.rb', line 35
 
 def match(input)
   if @pattern.is_a? String
@@ -471,20 +471,20 @@
       
 
 
+52
 53
 54
 55
 56
 57
-58
-59
+58
-
# File 'lib/hyde/pattern_matching.rb', line 53
+      
# File 'lib/hyde/pattern_matching.rb', line 52
 
 def match?(input)
   if @pattern.is_a? String
-    Hyde::PatternMatching.canonicalize(input).start_with? pattern
+    Hyde::PatternMatching.canonicalize(input).start_with? @pattern
   else
     @pattern.match?(input)
   end
@@ -533,12 +533,12 @@
       
 
 
+22
 23
-24
-25
+24
-
# File 'lib/hyde/pattern_matching.rb', line 23
+      
# File 'lib/hyde/pattern_matching.rb', line 22
 
 def static?
   @static
@@ -553,7 +553,7 @@
 
 
       
diff --git a/doc/Hyde/PatternMatching.html b/doc/Hyde/PatternMatching.html
index 68cef9f..b994167 100644
--- a/doc/Hyde/PatternMatching.html
+++ b/doc/Hyde/PatternMatching.html
@@ -232,7 +232,7 @@
 
 
       
diff --git a/doc/Hyde/PatternMatching/Glob.html b/doc/Hyde/PatternMatching/Glob.html
index 3136500..6b028a6 100644
--- a/doc/Hyde/PatternMatching/Glob.html
+++ b/doc/Hyde/PatternMatching/Glob.html
@@ -641,7 +641,7 @@
 
 
       
diff --git a/doc/Hyde/PatternMatching/ReMatch.html b/doc/Hyde/PatternMatching/ReMatch.html
index 541d4cd..843c1ce 100644
--- a/doc/Hyde/PatternMatching/ReMatch.html
+++ b/doc/Hyde/PatternMatching/ReMatch.html
@@ -559,7 +559,7 @@
 
 
       
diff --git a/doc/Hyde/Probe.html b/doc/Hyde/Probe.html
new file mode 100644
index 0000000..2282d75
--- /dev/null
+++ b/doc/Hyde/Probe.html
@@ -0,0 +1,471 @@
+
+
+  
+    
+
+
+  Class: Hyde::Probe
+  
+    — Documentation by YARD 0.9.34
+  
+
+
+  
+
+  
+
+
+
+
+  
+
+  
+
+
+  
+  
+    
+
+    
+ + +

Class: Hyde::Probe + + + +

+
+ +
+
Inherits:
+
+ Node + +
    +
  • Object
  • + + + + + +
+ show all + +
+
+ + + + + + + + + + + +
+
Defined in:
+
lib/hyde/probe.rb
+
+ +
+ +

Overview

+
+ +

Test probe. Also base for all “reactive” nodes.

+ + +
+
+
+ + +
+

Direct Known Subclasses

+

Handler, ServeHandler

+
+ + + + +

Instance Attribute Summary collapse

+
    + +
  • + + + #properties ⇒ Object + + + + + + + + + readonly + + + + + + + + + +
    +

    Returns the value of attribute properties.

    +
    + +
  • + + +
+ + + + + +

Attributes inherited from Node

+

#remap, #root

+ + + +

+ Instance Method Summary + collapse +

+ + + + + + + + + + + + + +

Methods inherited from Node

+

#go, #reject

+
+

Constructor Details

+ +
+

+ + #initialize(path, parent:) ⇒ Probe + + + + + +

+
+ +

Returns a new instance of Probe.

+ + +
+
+
+

Parameters:

+
    + +
  • + + path + + + (Object) + + + +
  • + +
  • + + parent + + + (Hyde::Node) + + + +
  • + +
+ + +
+ + + + +
+
+
+
+23
+24
+25
+
+
# File 'lib/hyde/probe.rb', line 23
+
+def initialize(path, parent:)
+  super(path, parent: parent)
+end
+
+
+ +
+ +
+

Instance Attribute Details

+ + + +
+

+ + #propertiesObject (readonly) + + + + + +

+
+ +

Returns the value of attribute properties.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+27
+28
+29
+
+
# File 'lib/hyde/probe.rb', line 27
+
+def properties
+  @properties
+end
+
+
+ +
+ + +
+

Instance Method Details

+ + +
+

+ + #process(request) ⇒ Boolean + + + + + +

+
+ +

Method callback on successful request navigation. Throws an error upon reaching the path. This behaviour should only be used internally.

+ + +
+
+
+

Parameters:

+ + +

Returns:

+
    + +
  • + + + (Boolean) + + + + — +
    +

    true if further navigation is possible

    +
    + +
  • + +
+

Raises:

+
    + +
  • + + + (StandardError) + + + +
  • + +
+ +
+ + + + +
+
+
+
+35
+36
+37
+38
+39
+40
+41
+42
+
+
# File 'lib/hyde/probe.rb', line 35
+
+def process(request)
+  return reject(request) unless request.path.match?(/^\/?$/)
+
+  raise StandardError, <<~STREND
+    probe reached #{request.splat.inspect}, #{request.param.inspect}
+    #{request.pretty_inspect}
+  STREND
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/ProbeBinding.html b/doc/Hyde/ProbeBinding.html new file mode 100644 index 0000000..84d9a19 --- /dev/null +++ b/doc/Hyde/ProbeBinding.html @@ -0,0 +1,219 @@ + + + + + + + Class: Hyde::ProbeBinding + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Class: Hyde::ProbeBinding + + + +

+
+ +
+
Inherits:
+
+ Object + +
    +
  • Object
  • + + + +
+ show all + +
+
+ + + + + + +
+
Includes:
+
DSL::ProbeMethods
+
+ + + + + + +
+
Defined in:
+
lib/hyde/probe/binding.rb
+
+ +
+ + + + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + + + + + + + + +

Methods included from DSL::ProbeMethods

+

#bounce, #die, #header, #remove_header, #request, #status

+
+

Constructor Details

+ +
+

+ + #initialize(origin) ⇒ ProbeBinding + + + + + +

+
+ +

Returns a new instance of ProbeBinding.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+7
+8
+9
+
+
# File 'lib/hyde/probe/binding.rb', line 7
+
+def initialize(origin)
+  @origin = origin
+end
+
+
+ +
+ + +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/Request.html b/doc/Hyde/Request.html new file mode 100644 index 0000000..9efd6fe --- /dev/null +++ b/doc/Hyde/Request.html @@ -0,0 +1,1505 @@ + + + + + + + Class: Hyde::Request + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Class: Hyde::Request + + + +

+
+ +
+
Inherits:
+
+ Object + +
    +
  • Object
  • + + + +
+ show all + +
+
+ + + + + + + + + + + +
+
Defined in:
+
lib/hyde/request.rb
+
+ +
+ +

Overview

+
+ +

Request wrapper for Rack protocol

+ + +
+
+
+ + +
+ + + +

Instance Attribute Summary collapse

+
    + +
  • + + + #filepath ⇒ Object + + + + + + + + + + + + + + + + +
    +

    Returns the value of attribute filepath.

    +
    + +
  • + + +
  • + + + #headers ⇒ Object + + + + + + + + + readonly + + + + + + + + + +
    +

    Returns the value of attribute headers.

    +
    + +
  • + + +
  • + + + #param ⇒ Object + + + + + + + + + readonly + + + + + + + + + +
    +

    Returns the value of attribute param.

    +
    + +
  • + + +
  • + + + #path ⇒ Object + + + + + + + + + + + + + + + + +
    +

    Returns the value of attribute path.

    +
    + +
  • + + +
  • + + + #path_info ⇒ Object + + + + + + + + + readonly + + + + + + + + + +
    +

    Returns the value of attribute path_info.

    +
    + +
  • + + +
  • + + + #postprocessors ⇒ Object + + + + + + + + + readonly + + + + + + + + + +
    +

    Returns the value of attribute postprocessors.

    +
    + +
  • + + +
  • + + + #query ⇒ Object + + + + + + + + + readonly + + + + + + + + + +
    +

    Returns the value of attribute query.

    +
    + +
  • + + +
  • + + + #request_method ⇒ Object + + + + + + + + + readonly + + + + + + + + + +
    +

    Returns the value of attribute request_method.

    +
    + +
  • + + +
  • + + + #script_name ⇒ Object + + + + + + + + + readonly + + + + + + + + + +
    +

    Returns the value of attribute script_name.

    +
    + +
  • + + +
  • + + + #server_name ⇒ Object + + + + + + + + + readonly + + + + + + + + + +
    +

    Returns the value of attribute server_name.

    +
    + +
  • + + +
  • + + + #server_port ⇒ Object + + + + + + + + + readonly + + + + + + + + + +
    +

    Returns the value of attribute server_port.

    +
    + +
  • + + +
  • + + + #server_protocol ⇒ Object + + + + + + + + + readonly + + + + + + + + + +
    +

    Returns the value of attribute server_protocol.

    +
    + +
  • + + +
  • + + + #splat ⇒ Object + + + + + + + + + readonly + + + + + + + + + +
    +

    Returns the value of attribute splat.

    +
    + +
  • + + +
+ + + + + +

+ Instance Method Summary + collapse +

+ + + + +
+

Constructor Details

+ +
+

+ + #initialize(env) ⇒ Request + + + + + +

+
+ +

Returns a new instance of Request.

+ + +
+
+
+

Parameters:

+
    + +
  • + + env + + + (Array) + + + +
  • + +
+ + +
+ + + + +
+
+
+
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+
+
# File 'lib/hyde/request.rb', line 10
+
+def initialize(env)
+  # Should not be used under regular circumstances or depended upon.
+  @_original_env = env
+  # Rack environment variable bindings. Should be public and frozen.
+  init_request_params(env)
+  # Query parsing
+  @query = Query.new(@query_string)
+  # Pattern matching parameters. Public, readable, unfrozen.
+  @param = {}
+  @splat = []
+  # Traversal route. Public and writable.
+  @path = URI.decode_www_form_component(env["PATH_INFO"].dup)
+  # File serving path. Public and writable.
+  @filepath = "/"
+  # Encapsulates all rack variables. Should not be public.
+  @rack = init_rack_vars(env)
+  # Internal navigation states. Private.
+  @states = []
+  # Postprocessors for current request
+  @postprocessors = []
+end
+
+
+ +
+ +
+

Instance Attribute Details

+ + + +
+

+ + #filepathObject + + + + + +

+
+ +

Returns the value of attribute filepath.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+59
+60
+61
+
+
# File 'lib/hyde/request.rb', line 59
+
+def filepath
+  @filepath
+end
+
+
+ + + +
+

+ + #headersObject (readonly) + + + + + +

+
+ +

Returns the value of attribute headers.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+56
+57
+58
+
+
# File 'lib/hyde/request.rb', line 56
+
+def headers
+  @headers
+end
+
+
+ + + +
+

+ + #paramObject (readonly) + + + + + +

+
+ +

Returns the value of attribute param.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+56
+57
+58
+
+
# File 'lib/hyde/request.rb', line 56
+
+def param
+  @param
+end
+
+
+ + + +
+

+ + #pathObject + + + + + +

+
+ +

Returns the value of attribute path.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+59
+60
+61
+
+
# File 'lib/hyde/request.rb', line 59
+
+def path
+  @path
+end
+
+
+ + + +
+

+ + #path_infoObject (readonly) + + + + + +

+
+ +

Returns the value of attribute path_info.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+56
+57
+58
+
+
# File 'lib/hyde/request.rb', line 56
+
+def path_info
+  @path_info
+end
+
+
+ + + +
+

+ + #postprocessorsObject (readonly) + + + + + +

+
+ +

Returns the value of attribute postprocessors.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+56
+57
+58
+
+
# File 'lib/hyde/request.rb', line 56
+
+def postprocessors
+  @postprocessors
+end
+
+
+ + + +
+

+ + #queryObject (readonly) + + + + + +

+
+ +

Returns the value of attribute query.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+56
+57
+58
+
+
# File 'lib/hyde/request.rb', line 56
+
+def query
+  @query
+end
+
+
+ + + +
+

+ + #request_methodObject (readonly) + + + + + +

+
+ +

Returns the value of attribute request_method.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+56
+57
+58
+
+
# File 'lib/hyde/request.rb', line 56
+
+def request_method
+  @request_method
+end
+
+
+ + + +
+

+ + #script_nameObject (readonly) + + + + + +

+
+ +

Returns the value of attribute script_name.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+56
+57
+58
+
+
# File 'lib/hyde/request.rb', line 56
+
+def script_name
+  @script_name
+end
+
+
+ + + +
+

+ + #server_nameObject (readonly) + + + + + +

+
+ +

Returns the value of attribute server_name.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+56
+57
+58
+
+
# File 'lib/hyde/request.rb', line 56
+
+def server_name
+  @server_name
+end
+
+
+ + + +
+

+ + #server_portObject (readonly) + + + + + +

+
+ +

Returns the value of attribute server_port.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+56
+57
+58
+
+
# File 'lib/hyde/request.rb', line 56
+
+def server_port
+  @server_port
+end
+
+
+ + + +
+

+ + #server_protocolObject (readonly) + + + + + +

+
+ +

Returns the value of attribute server_protocol.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+56
+57
+58
+
+
# File 'lib/hyde/request.rb', line 56
+
+def server_protocol
+  @server_protocol
+end
+
+
+ + + +
+

+ + #splatObject (readonly) + + + + + +

+
+ +

Returns the value of attribute splat.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+56
+57
+58
+
+
# File 'lib/hyde/request.rb', line 56
+
+def splat
+  @splat
+end
+
+
+ +
+ + +
+

Instance Method Details

+ + +
+

+ + #bodynil, String + + + + + +

+
+ +

Returns request body (if POST data exists)

+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (nil, String) + + + +
  • + +
+ +
+ + + + +
+
+
+
+42
+43
+44
+
+
# File 'lib/hyde/request.rb', line 42
+
+def body
+  @body ||= @rack.input&.gets
+end
+
+
+ +
+

+ + #pop_stateObject + + + + + +

+
+ +

Load last navigation state (path, splat, param) from state stack

+ + +
+
+
+ + +
+ + + + +
+
+
+
+52
+53
+54
+
+
# File 'lib/hyde/request.rb', line 52
+
+def pop_state
+  @path, @param, @splat, @filepath = @states.pop
+end
+
+
+ +
+

+ + #push_stateObject + + + + + +

+
+ +

Push current navigation state (path, splat, param) onto state stack

+ + +
+
+
+ + +
+ + + + +
+
+
+
+47
+48
+49
+
+
# File 'lib/hyde/request.rb', line 47
+
+def push_state
+  @states.push([@path, @param.dup, @splat.dup, @filepath.dup])
+end
+
+
+ +
+

+ + #run_postprocessors(response) ⇒ Object + + + + + +

+
+ +

Run postprocessors

+ + +
+
+
+

Parameters:

+ + + +
+ + + + +
+
+
+
+34
+35
+36
+37
+38
+
+
# File 'lib/hyde/request.rb', line 34
+
+def run_postprocessors(response)
+  @postprocessors.each do |postproc|
+    postproc.call(self, response)
+  end
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/Response.html b/doc/Hyde/Response.html new file mode 100644 index 0000000..e5fa4ba --- /dev/null +++ b/doc/Hyde/Response.html @@ -0,0 +1,1177 @@ + + + + + + + Class: Hyde::Response + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Class: Hyde::Response + + + +

+
+ +
+
Inherits:
+
+ Object + +
    +
  • Object
  • + + + +
+ show all + +
+
+ + + + + + + + + + + +
+
Defined in:
+
lib/hyde/response.rb
+
+ +
+ +

Overview

+
+ +

Rack protocol response wrapper.

+ + +
+
+
+ + +
+ + + +

Instance Attribute Summary collapse

+
    + +
  • + + + #body ⇒ Object + + + + + + + + + + + + + + + + +
    +

    Returns the value of attribute body.

    +
    + +
  • + + +
  • + + + #chunk_size ⇒ Object + + + + + + + + + + + + + + + + +
    +

    Returns the value of attribute chunk_size.

    +
    + +
  • + + +
  • + + + #headers ⇒ Object + + + + + + + + + + + + + + + + +
    +

    Returns the value of attribute headers.

    +
    + +
  • + + +
  • + + + #status ⇒ Object + + + + + + + + + + + + + + + + +
    +

    Returns the value of attribute status.

    +
    + +
  • + + +
+ + + + + +

+ Class Method Summary + collapse +

+ + + +

+ Instance Method Summary + collapse +

+ + + + +
+

Constructor Details

+ +
+

+ + #initialize(response = nil) ⇒ Response + + + + + +

+
+ +

Returns a new instance of Response.

+ + +
+
+
+

Parameters:

+
    + +
  • + + response + + + (Array(Integer, Hash, Array), nil) + + + (defaults to: nil) + + +
  • + +
+ + +
+ + + + +
+
+
+
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+
+
# File 'lib/hyde/response.rb', line 11
+
+def initialize(response = nil)
+  if response
+    @status = response[0]
+    @headers = response[1]
+    @body = response[2]
+  else
+    @status = 404
+    @headers = {}
+    @body = []
+  end
+end
+
+
+ +
+ +
+

Instance Attribute Details

+ + + +
+

+ + #bodyObject + + + + + +

+
+ +

Returns the value of attribute body.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+71
+72
+73
+
+
# File 'lib/hyde/response.rb', line 71
+
+def body
+  @body
+end
+
+
+ + + +
+

+ + #chunk_sizeObject + + + + + +

+
+ +

Returns the value of attribute chunk_size.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+8
+9
+10
+
+
# File 'lib/hyde/response.rb', line 8
+
+def chunk_size
+  @chunk_size
+end
+
+
+ + + +
+

+ + #headersObject + + + + + +

+
+ +

Returns the value of attribute headers.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+71
+72
+73
+
+
# File 'lib/hyde/response.rb', line 71
+
+def headers
+  @headers
+end
+
+
+ + + +
+

+ + #statusObject + + + + + +

+
+ +

Returns the value of attribute status.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+71
+72
+73
+
+
# File 'lib/hyde/response.rb', line 71
+
+def status
+  @status
+end
+
+
+ +
+ + +
+

Class Method Details

+ + +
+

+ + .chunk_body(text) ⇒ Array(String) + + + + + +

+
+ +

Turn body into array of chunks

+ + +
+
+
+

Parameters:

+
    + +
  • + + text + + + (String) + + + +
  • + +
+ +

Returns:

+
    + +
  • + + + (Array(String)) + + + +
  • + +
+ +
+ + + + +
+
+
+
+96
+97
+98
+
+
# File 'lib/hyde/response.rb', line 96
+
+def self.chunk_body(text)
+  text.chars.each_slice(@chunk_size).map(&:join)
+end
+
+
+ +
+

+ + .convert(obj) ⇒ Object + + + + + +

+
+ +

Ensure response correctness

+ + +
+
+
+

Parameters:

+ + +

Returns:

+
    + +
  • + + + + + + + +
    +

    Response

    +
    + +
  • + +
+ +
+ + + + +
+
+
+
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+
+
# File 'lib/hyde/response.rb', line 76
+
+def self.convert(obj)
+  case obj
+  when Response
+    obj.validate
+  when Array
+    Response.new(obj).validate
+  when String, File, IO
+    Response.new([200,
+                  {
+                    "content-type" => "text/html"
+                  },
+                  obj]).validate
+  else
+    Response.new([404, {}, []])
+  end
+end
+
+
+ +
+ +
+

Instance Method Details

+ + +
+

+ + #add_header(key, value) ⇒ Object + + + + + +

+
+ +

Add a header to the headers hash

+ + +
+
+
+

Parameters:

+
    + +
  • + + key + + + (String) + + + + — +
    +

    header name

    +
    + +
  • + +
  • + + value + + + (String) + + + + — +
    +

    header value

    +
    + +
  • + +
+ + +
+ + + + +
+
+
+
+49
+50
+51
+52
+53
+54
+55
+56
+57
+
+
# File 'lib/hyde/response.rb', line 49
+
+def add_header(key, value)
+  if @headers[key].is_a? String
+    @headers[key] = [@headers[key], value]
+  elsif @headers[key].is_a? Array
+    @headers[key].append(value)
+  else
+    @headers[key] = value
+  end
+end
+
+
+ +
+

+ + #delete_header(key, value = nil) ⇒ Object + + + + + +

+
+ +

Delete a header value from the headers hash If no value is provided, deletes all key entries

+ + +
+
+
+

Parameters:

+
    + +
  • + + key + + + (String) + + + + — +
    +

    header name

    +
    + +
  • + +
  • + + value + + + (String, nil) + + + (defaults to: nil) + + + — +
    +

    header value

    +
    + +
  • + +
+ + +
+ + + + +
+
+
+
+63
+64
+65
+66
+67
+68
+69
+
+
# File 'lib/hyde/response.rb', line 63
+
+def delete_header(key, value = nil)
+  if value and @response[key]
+    @response[key].delete(value)
+  else
+    @response.delete(key)
+  end
+end
+
+
+ +
+

+ + #finalizeArray(Integer,Hash,Array) + + + + + +

+
+ +

Return internal representation of Rack response

+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Array(Integer,Hash,Array)) + + + +
  • + +
+ +
+ + + + +
+
+
+
+25
+26
+27
+
+
# File 'lib/hyde/response.rb', line 25
+
+def finalize
+  [@status, @headers, @body]
+end
+
+
+ +
+

+ + #validateHyde::Response + + + + + +

+
+ +

Make internal representation conformant

+ + +
+
+
+ +

Returns:

+ + +
+ + + + +
+
+
+
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+
+
# File 'lib/hyde/response.rb', line 31
+
+def validate
+  if [204, 304].include?(@status) or (100..199).include?(@status)
+    @headers.delete "content-length"
+    @headers.delete "content-type"
+    @body = []
+  elsif @headers.empty?
+    @headers = {
+      "content-length" => content_size,
+      "content-type" => "text/html"
+    }
+  end
+  @body = self.class.chunk_body(@body) if @body.is_a? String
+  self
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/ServeHandler.html b/doc/Hyde/ServeHandler.html new file mode 100644 index 0000000..eb34b2e --- /dev/null +++ b/doc/Hyde/ServeHandler.html @@ -0,0 +1,476 @@ + + + + + + + Class: Hyde::ServeHandler + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Class: Hyde::ServeHandler + + + +

+
+ +
+
Inherits:
+
+ Probe + +
    +
  • Object
  • + + + + + + + +
+ show all + +
+
+ + + + + + + + + + + +
+
Defined in:
+
lib/hyde/probe/serve_handler.rb
+
+ +
+ +

Overview

+
+ +

Probe that sends files from a location

+ + +
+
+
+ + +
+ + + +

Instance Attribute Summary collapse

+
    + +
  • + + + #response ⇒ Object + + + + + + + + + + + + + + + + +
    +

    Returns the value of attribute response.

    +
    + +
  • + + +
+ + + + + +

Attributes inherited from Probe

+

#properties

+ + + +

Attributes inherited from Node

+

#remap, #root

+ + + +

+ Instance Method Summary + collapse +

+ + + + + + + + + + + + + + + + + + + +

Methods inherited from Node

+

#go, #reject

+
+

Constructor Details

+ +
+

+ + #initialize(path, parent:) ⇒ ServeHandler + + + + + +

+
+ +

Returns a new instance of ServeHandler.

+ + +
+
+
+

Parameters:

+
    + +
  • + + path + + + (Object) + + + +
  • + +
  • + + parent + + + (Hyde::Node) + + + +
  • + +
  • + + exec + + + (#call) + + + +
  • + +
+ + +
+ + + + +
+
+
+
+12
+13
+14
+
+
# File 'lib/hyde/probe/serve_handler.rb', line 12
+
+def initialize(path, parent:)
+  super(path, parent: parent)
+end
+
+
+ +
+ +
+

Instance Attribute Details

+ + + +
+

+ + #responseObject + + + + + +

+
+ +

Returns the value of attribute response.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+16
+17
+18
+
+
# File 'lib/hyde/probe/serve_handler.rb', line 16
+
+def response
+  @response
+end
+
+
+ +
+ + +
+

Instance Method Details

+ + +
+

+ + #process(request) ⇒ Boolean + + + + + +

+
+ +

Method callback on successful request navigation. Tries to serve files matched by handler

+ + +
+
+
+

Parameters:

+ + +

Returns:

+
    + +
  • + + + (Boolean) + + + + — +
    +

    true if file was found

    +
    + +
  • + +
+ +
+ + + + +
+
+
+
+22
+23
+24
+25
+26
+27
+28
+29
+
+
# File 'lib/hyde/probe/serve_handler.rb', line 22
+
+def process(request)
+  path = File.expand_path(request.filepath)
+  return unless path.start_with? @properties["path"]
+
+  File.open(path.delete_suffix("/"))
+rescue StandardError
+  false
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/Server.html b/doc/Hyde/Server.html new file mode 100644 index 0000000..0166536 --- /dev/null +++ b/doc/Hyde/Server.html @@ -0,0 +1,441 @@ + + + + + + + Class: Hyde::Server + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Class: Hyde::Server + + + +

+
+ +
+
Inherits:
+
+ Path + +
    +
  • Object
  • + + + + + + + +
+ show all + +
+
+ + + + + + + + + + + +
+
Defined in:
+
lib/hyde/server.rb
+
+ +
+ +

Overview

+
+ +

A specialized path that can be used directly as a Rack application.

+ + +
+
+
+ + +
+ +

+ Constant Summary + collapse +

+ +
+ +
Binding = + +
+
ServerBinding
+ +
+ + + + + + + +

Instance Attribute Summary

+ +

Attributes inherited from Path

+

#children, #properties

+ + + +

Attributes inherited from Node

+

#remap, #root

+ + + +

+ Instance Method Summary + collapse +

+ + + + + + + + + + + + + +

Methods inherited from Path

+

#filter, #postprocess, #preprocess, #process

+ + + + + + + + + +

Methods inherited from Node

+

#go, #process, #reject

+
+

Constructor Details

+ +
+

+ + #initialize(parent: nil, &setup) ⇒ Server + + + + + +

+
+ +

Returns a new instance of Server.

+ + +
+
+
+

Parameters:

+
    + +
  • + + parent + + + (Hyde::Node, nil) + + + (defaults to: nil) + + + — +
    +

    Parent object to inherit properties to

    +
    + +
  • + +
  • + + setup + + + (#call) + + + + — +
    +

    Setup block

    +
    + +
  • + +
+ + +
+ + + + +
+
+
+
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+
+
# File 'lib/hyde/server.rb', line 18
+
+def initialize(parent: nil, &setup)
+  super("", parent: parent, &setup)
+  return if parent
+
+  {
+    "index" => [],
+    "handle.default" => proc do |code, backtrace: nil|
+      page = Hyde::Util.default_error_page(code, backtrace)
+      headers = {
+        "content-length": page.length,
+        "content-type": "text/html"
+      }
+      [headers, page]
+    end,
+    "path" => "/"
+  }.each { |k, v| @properties[k] = v unless @properties[k] }
+end
+
+
+ +
+ + +
+

Instance Method Details

+ + +
+

+ + #call(env) ⇒ Array(Integer,Hash,Array) + + + + + +

+
+ +

Rack ingress point. This should not be called under any circumstances twice in the same application, although server nesting for the purpose of creating virtual hosts is allowed.

+ + +
+
+
+

Parameters:

+
    + +
  • + + env + + + (Hash) + + + +
  • + +
+ +

Returns:

+
    + +
  • + + + (Array(Integer,Hash,Array)) + + + +
  • + +
+ +
+ + + + +
+
+
+
+41
+42
+43
+44
+45
+46
+47
+48
+
+
# File 'lib/hyde/server.rb', line 41
+
+def call(env)
+  request = Hyde::Request.new(env)
+  response = catch(:finish) do
+    go(request)
+  end
+  request.run_postprocessors(response)
+  Response.convert(response).finalize
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/ServerBinding.html b/doc/Hyde/ServerBinding.html new file mode 100644 index 0000000..ce91faf --- /dev/null +++ b/doc/Hyde/ServerBinding.html @@ -0,0 +1,162 @@ + + + + + + + Class: Hyde::ServerBinding + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Class: Hyde::ServerBinding + + + +

+
+ +
+
Inherits:
+
+ PathBinding + + + show all + +
+
+ + + + + + + + + + + +
+
Defined in:
+
lib/hyde/server.rb
+
+ +
+ + + + + + + + + + + + + + + +

Method Summary

+ +

Methods inherited from PathBinding

+

#initialize

+ + + + + + + + + +

Methods included from DSL::PathMethods

+

#filter, #index, #postprocess, #preprocess, #remap, #root

+ + + + + + + + + +

Methods included from DSL::PathConstructors

+

#connect, #delete, #get, #head, #options, #patch, #path, #post, #probe, #put, #register, #serve, #trace

+
+

Constructor Details

+ +

This class inherits a constructor from Hyde::PathBinding

+ +
+ + +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/TRACEHandler.html b/doc/Hyde/TRACEHandler.html new file mode 100644 index 0000000..30a8e7e --- /dev/null +++ b/doc/Hyde/TRACEHandler.html @@ -0,0 +1,221 @@ + + + + + + + Class: Hyde::TRACEHandler + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Class: Hyde::TRACEHandler + + + +

+
+ +
+
Inherits:
+
+ GETHandler + + + show all + +
+
+ + + + + + + + + + + +
+
Defined in:
+
lib/hyde/probe/http_method.rb
+
+ +
+ +

Overview

+
+ +

Probe that executes callback on a TRACE

+ + +
+
+
+ + +
+ +

+ Constant Summary + collapse +

+ +
+ +
METHOD = + +
+
"TRACE"
+ +
+ + + + + + + +

Instance Attribute Summary

+ +

Attributes inherited from Handler

+

#request, #response

+ + + +

Attributes inherited from Probe

+

#properties

+ + + +

Attributes inherited from Node

+

#remap, #root

+ + + + + + + + + +

Method Summary

+ +

Methods inherited from GETHandler

+

#process

+ + + + + + + + + +

Methods inherited from Handler

+

#initialize, #process

+ + + + + + + + + +

Methods inherited from Probe

+

#initialize, #process

+ + + + + + + + + +

Methods inherited from Node

+

#go, #initialize, #process, #reject

+
+

Constructor Details

+ +

This class inherits a constructor from Hyde::Handler

+ +
+ + +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/Util.html b/doc/Hyde/Util.html new file mode 100644 index 0000000..c44f07c --- /dev/null +++ b/doc/Hyde/Util.html @@ -0,0 +1,487 @@ + + + + + + + Module: Hyde::Util + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: Hyde::Util + + + +

+
+ + + + + + + + + + + +
+
Defined in:
+
lib/hyde/util/lookup.rb,
+ lib/hyde/util/html.rb,
lib/hyde/util/query.rb
+
+
+ +
+ +

Overview

+
+ +

Various things that exists for purely logical reasons

+ + +
+
+
+ + +

Defined Under Namespace

+

+ + + + + Classes: Lookup, Query + + +

+ + +

+ Constant Summary + collapse +

+ +
+ +
HTTP_STATUS = +
+
+ +

HTTP status codes and descriptions Taken from WEBrick https://github.com/ruby/webrick/blob/master/lib/webrick/httpstatus.rb

+ + +
+
+
+ + +
+
+
{
+  100 => 'Continue',
+  101 => 'Switching Protocols',
+  200 => 'OK',
+  201 => 'Created',
+  202 => 'Accepted',
+  203 => 'Non-Authoritative Information',
+  204 => 'No Content',
+  205 => 'Reset Content',
+  206 => 'Partial Content',
+  207 => 'Multi-Status',
+  300 => 'Multiple Choices',
+  301 => 'Moved Permanently',
+  302 => 'Found',
+  303 => 'See Other',
+  304 => 'Not Modified',
+  305 => 'Use Proxy',
+  307 => 'Temporary Redirect',
+  400 => 'Bad Request',
+  401 => 'Unauthorized',
+  402 => 'Payment Required',
+  403 => 'Forbidden',
+  404 => 'Not Found',
+  405 => 'Method Not Allowed',
+  406 => 'Not Acceptable',
+  407 => 'Proxy Authentication Required',
+  408 => 'Request Timeout',
+  409 => 'Conflict',
+  410 => 'Gone',
+  411 => 'Length Required',
+  412 => 'Precondition Failed',
+  413 => 'Request Entity Too Large',
+  414 => 'Request-URI Too Large',
+  415 => 'Unsupported Media Type',
+  416 => 'Request Range Not Satisfiable',
+  417 => 'Expectation Failed',
+  422 => 'Unprocessable Entity',
+  423 => 'Locked',
+  424 => 'Failed Dependency',
+  426 => 'Upgrade Required',
+  428 => 'Precondition Required',
+  429 => 'Too Many Requests',
+  431 => 'Request Header Fields Too Large',
+  451 => 'Unavailable For Legal Reasons',
+  500 => 'Internal Server Error',
+  501 => 'Not Implemented',
+  502 => 'Bad Gateway',
+  503 => 'Service Unavailable',
+  504 => 'Gateway Timeout',
+  505 => 'HTTP Version Not Supported',
+  507 => 'Insufficient Storage',
+  511 => 'Network Authentication Required'
+}.freeze
+ +
+ + + + + + + + + +

+ Class Method Summary + collapse +

+ + + + + + +
+

Class Method Details

+ + +
+

+ + .default_error_page(code, backtrace) ⇒ String + + + + + +

+
+ +

Default error page for Hyde

+ + +
+
+
+

Parameters:

+
    + +
  • + + code + + + (Integer) + + + + — +
    +

    HTTP Status code

    +
    + +
  • + +
  • + + backtrace + + + (Array(String), nil) + + + + — +
    +

    Message to show in backtrace window

    +
    + +
  • + +
+ +

Returns:

+
    + +
  • + + + (String) + + + +
  • + +
+ +
+ + + + +
+
+
+
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+
+
# File 'lib/hyde/util/html.rb', line 78
+
+def self.default_error_page(code, backtrace)
+  backtrace ||= []
+  errortext = HTTP_STATUS[code]
+  <<~HTMLEOF
+    <!DOCTYPE HTML>
+    <html>
+        <head>
+            <title>#{Util.escape_html(errortext)}</title>
+            <style> .header {padding: 0.5rem; overflow: auto;} .title { font-weight: bolder; font-size: 48px; margin: 10px 10px; text-shadow: 1px 1px 1px #202222, 2px 2px 2px #404444; float: left } body { margin: 0; } .text { font-size 1rem; } .small { color: #7D7D7D; font-size: 12px;} .code { font-family: monospace; font-size: 0.7rem; } </style>
+        </head>
+        <body>
+            <div class="header">
+                <p class="title">HYDE</p>
+                <p style="float: right"><a href="https://adastra7.net/git/yessiest/hyde">Source code</a></p>
+            </div>
+            <div style="padding: 0.5rem">
+                <p class="text">#{Util.escape_html(errortext)}</p>
+                <pre><code class="text code">
+    #{backtrace.map(&Util.method(:escape_html)).join('<br/>')}
+                </code></pre>
+                <hr/>
+                <p class="small">#{Util.escape_html(Hyde::VLINE)}</p>
+            </div>
+        </body>
+    </html>
+  HTMLEOF
+end
+
+
+ +
+

+ + .escape_html(str) ⇒ String + + + + + +

+
+ +

Return string with escaped HTML entities

+ + +
+
+
+

Parameters:

+
    + +
  • + + str + + + (String) + + + +
  • + +
+ +

Returns:

+
    + +
  • + + + (String) + + + +
  • + +
+ +
+ + + + +
+
+
+
+64
+65
+66
+67
+68
+69
+70
+
+
# File 'lib/hyde/util/html.rb', line 64
+
+def self.escape_html(str)
+  str.gsub("&", "&amp;")
+     .gsub("<", "&lt;")
+     .gsub(">", "&gt;")
+     .gsub("\"", "&quot;")
+     .gsub("'", "&#39;")
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/Util/Lookup.html b/doc/Hyde/Util/Lookup.html new file mode 100644 index 0000000..6af3b6f --- /dev/null +++ b/doc/Hyde/Util/Lookup.html @@ -0,0 +1,613 @@ + + + + + + + Class: Hyde::Util::Lookup + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Class: Hyde::Util::Lookup + + + +

+
+ +
+
Inherits:
+
+ Object + +
    +
  • Object
  • + + + +
+ show all + +
+
+ + + + + + + + + + + +
+
Defined in:
+
lib/hyde/util/lookup.rb
+
+ +
+ +

Overview

+
+ +

Value container with recursive lookup

+ + +
+
+
+ + +
+ + + +

Instance Attribute Summary collapse

+
    + +
  • + + + #parent ⇒ Object + + + + + + + + + + + + + + + + +
    +

    Returns the value of attribute parent.

    +
    + +
  • + + +
+ + + + + +

+ Class Method Summary + collapse +

+ + + +

+ Instance Method Summary + collapse +

+ + + + +
+

Constructor Details

+ +
+

+ + #initialize(parent = nil, hash = {}) ⇒ Lookup + + + + + +

+
+ +

Returns a new instance of Lookup.

+ + +
+
+
+

Parameters:

+
    + +
  • + + parent + + + (Lookup, nil) + + + (defaults to: nil) + + +
  • + +
+ + +
+ + + + +
+
+
+
+9
+10
+11
+12
+
+
# File 'lib/hyde/util/lookup.rb', line 9
+
+def initialize(parent = nil, hash = {})
+  @parent = (parent or Hash.new(nil))
+  @storage = hash
+end
+
+
+ +
+ +
+

Instance Attribute Details

+ + + +
+

+ + #parentObject + + + + + +

+
+ +

Returns the value of attribute parent.

+ + +
+
+
+ + +
+ + + + +
+
+
+
+34
+35
+36
+
+
# File 'lib/hyde/util/lookup.rb', line 34
+
+def parent
+  @parent
+end
+
+
+ +
+ + +
+

Class Method Details

+ + +
+

+ + .[](hash) ⇒ Object + + + + + +

+
+ +

Initialize a Lookup from Hash

+ + +
+
+
+

Parameters:

+
    + +
  • + + hash + + + (Hash) + + + +
  • + +
+ + +
+ + + + +
+
+
+
+16
+17
+18
+
+
# File 'lib/hyde/util/lookup.rb', line 16
+
+def self.[](hash)
+  Lookup.new(nil, Hash[hash])
+end
+
+
+ +
+ +
+

Instance Method Details

+ + +
+

+ + #[](key) ⇒ Object? + + + + + +

+
+ +

Get a value by key

+ + +
+
+
+

Parameters:

+
    + +
  • + + key + + + (#hash) + + + + — +
    +

    key for value

    +
    + +
  • + +
+ +

Returns:

+
    + +
  • + + + (Object, nil) + + + +
  • + +
+ +
+ + + + +
+
+
+
+23
+24
+25
+
+
# File 'lib/hyde/util/lookup.rb', line 23
+
+def [](key)
+  @storage[key] or @parent[key]
+end
+
+
+ +
+

+ + #[]=(key, value) ⇒ Object + + + + + +

+
+ +

Set a value by key

+ + +
+
+
+

Parameters:

+
    + +
  • + + key + + + (#hash) + + + + — +
    +

    key for value

    +
    + +
  • + +
  • + + value + + + (Object) + + + + — +
    +

    value value

    +
    + +
  • + +
+ + +
+ + + + +
+
+
+
+30
+31
+32
+
+
# File 'lib/hyde/util/lookup.rb', line 30
+
+def []=(key, value)
+  @storage[key] = value
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/doc/Hyde/Util/Query.html b/doc/Hyde/Util/Query.html new file mode 100644 index 0000000..120361b --- /dev/null +++ b/doc/Hyde/Util/Query.html @@ -0,0 +1,402 @@ + + + + + + + Class: Hyde::Util::Query + + — Documentation by YARD 0.9.34 + + + + + + + + + + + + + + + + + + + +
+ + +

Class: Hyde::Util::Query + + + +

+
+ +
+
Inherits:
+
+ Object + +
    +
  • Object
  • + + + +
+ show all + +
+
+ + + + + + + + + + + +
+
Defined in:
+
lib/hyde/util/query.rb
+
+ +
+ +

Overview

+
+ +

Query string parser

+ + +
+
+
+ + +
+ + + + + + + +

+ Instance Method Summary + collapse +

+ +
    + +
  • + + + #initialize(query) ⇒ Query + + + + + + + constructor + + + + + + + + +
    +

    A new instance of Query.

    +
    + +
  • + + +
  • + + + #parse ⇒ Hash + + + + + + + + + + + + + +
    +

    Better(tm) query parser with Returns a hash with arrays Key semantics:.

    +
    + +
  • + + +
  • + + + #parse_shallow ⇒ Hash + + + + + + + + + + + + + +
    +

    Shallow query parser (does not do PHP-like array keys).

    +
    + +
  • + + +
+ + +
+

Constructor Details

+ +
+

+ + #initialize(query) ⇒ Query + + + + + +

+
+ +

Returns a new instance of Query.

+ + +
+
+
+

Parameters:

+
    + +
  • + + query + + + (String) + + + +
  • + +
+ + +
+ + + + +
+
+
+
+10
+11
+12
+
+
# File 'lib/hyde/util/query.rb', line 10
+
+def initialize(query)
+  @query = query
+end
+
+
+ +
+ + +
+

Instance Method Details

+ + +
+

+ + #parseHash + + + + + +

+
+ +

Better(tm) query parser with Returns a hash with arrays Key semantics:

+
  • +

    ‘key=value` creates a key value pair

    +
  • +

    ‘key[]=value` appends `value` to an array named `key`

    +
  • +

    key=value` sets `value` at `index` of array named `key`

    +
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Hash) + + + +
  • + +
+ +
+ + + + +
+
+
+
+30
+31
+32
+
+
# File 'lib/hyde/util/query.rb', line 30
+
+def parse
+  construct_deep_hash(URI.decode_www_form(@query, Encoding::UTF_8))
+end
+
+
+ +
+

+ + #parse_shallowHash + + + + + +

+
+ +

Shallow query parser (does not do PHP-like array keys)

+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Hash) + + + +
  • + +
+ +
+ + + + +
+
+
+
+16
+17
+18
+19
+20
+
+
# File 'lib/hyde/util/query.rb', line 16
+
+def parse_shallow
+  URI.decode_www_form(@query, Encoding::UTF_8)
+     .sort_by { |array| array[0] }
+     .to_h
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/doc/_index.html b/doc/_index.html index e298db3..fe474d2 100644 --- a/doc/_index.html +++ b/doc/_index.html @@ -76,10 +76,54 @@ + + + + + + + + + + + + + + +
    +
  • U
  • +
      + +
    • + Util + + (Hyde) + +
    • +
@@ -163,7 +413,7 @@ diff --git a/doc/class_list.html b/doc/class_list.html index f991863..5f73cb9 100644 --- a/doc/class_list.html +++ b/doc/class_list.html @@ -43,7 +43,7 @@ diff --git a/doc/file.README.html b/doc/file.README.html index 087fef9..0af2f42 100644 --- a/doc/file.README.html +++ b/doc/file.README.html @@ -67,108 +67,103 @@

A simple "Hello, World!" HTTP API using Hyde

-
require 'Hyde'
+
require 'hyde'
 
-server = Hyde::Server.new Port: 8000 do
-    get "/hello" do |ctx|
-        ctx.response.body = "Hello, World!"
-        ctx.response['Content-Type'] = "text/plain"
-    end
+app = Hyde::Server.new do
+  get "/hello" do
+    header "content-type", "text/plain"
+    "Hello world!"
+  end
 end
 
-server.start
+run app
 

A push/pull stack as an HTTP API

require 'hyde'
 
-Stack = []
+stack = []
 
-server = Hyde::Server.new Port: 8000 do
-    get "pull" do |ctx|
-        ctx.response.body = "#{Stack.pop}"
-        ctx.response["Content-Type"] = "text/plain"
-    end
-    post "push" do |ctx|
-        Stack.push ctx.request.body
-        ctx.response.body = "#{ctx.request.body}"
-        ctx.response["Content-Type"] = "text/plain"
-    end
+app = Hyde::Server.new do
+  get "/pop" do
+    header 'content-type', 'text/plain'
+    stack.pop.to_s
+  end
+  post "/push" do
+    header 'content-type', 'text/plain'
+    stack.push(request.body)
+    request.body
+  end
 end
 
-server.start
+run app
 

Several push/pull buckets

require 'hyde'
 
-Stack = {"bucket_1" => [], "bucket_2" => [], "bucket_3" => []}
+stack = { "1" => [], "2" => [], "3" => [] }
 
-server = Hyde::Server.new Port: 8000 do
-    path ["bucket_1","bucket_2","bucket_3"] do
-        get "pull" do |ctx|
-            bucket_name = (ctx.filepath.match /bucket_[^\/]*/)[0]
-            ctx.response.body = "#{Stack[bucket_name].pop}"
-            ctx.response["Content-Type"] = "text/plain"
-        end
-        post "push" do |ctx|
-            bucket_name = (ctx.filepath.match /bucket_[^\/]*/)[0]
-            Stack[bucket_name].push ctx.request.body
-            ctx.response.body = "#{ctx.request.body}"
-            ctx.response["Content-Type"] = "text/plain"
-        end
+app = Hyde::Server.new do
+  path "bucket_(1|2|3)" do
+    get "pop" do |bucket|
+      header "content-type", "text/plain"
+      stack[bucket].pop.to_s
     end
+    post "push" do |bucket|
+      header "content-type", "text/plain"
+      stack[bucket].push(request.body)
+      request.body
+    end
+  end
 end
 
-server.start
+run app
 

Static file serving (Note: index applies only to /var/www (to the path its defined in))

-
require 'hyde'
+
require 'hyde'
 
-server = Hyde::Server.new Port:8000 do
-    path "static" do
-        root "/var/www"
-        index ["index.html","index.htm"]
-        serve "*/*.html" safe_regexp: false
-        serve "*.html"
-    end
-end
+app = Hyde::Server.new do
+  root "/var/www"
+  index ["index.html","index.htm"]
+  serve "**/*.(html|htm)"
+end
 
-server.start
+run app
 

Logging on a particular path

require 'hyde'
 
-server = Hyde::Server.new Port:8000 do
-    path "unimportant" do
-        get "version" do |ctx|
-            ctx.response.body = '{"version": "the good one"}'
-            ctx.response['Content-Type'] = "application/json"
-        end
+app = Hyde::Server.new do
+  path "unimportant" do
+    get "version" do
+      header "content-type", "text/plain"
+      "1337 (the best one)"
     end
-    path "important" do
-        preprocess do |ctx|
-            # Implement logging logic here
-            puts "Client at #{ctx.request.remote_ip} wanted to access something /important!"
-        end
-        get "answer" do |ctx|
-            ctx.response.body = '{"answer":42}'
-            ctx.response['Content-Type'] = "application/json"
-        end
+  end
+  path "important" do
+    preprocess do |req|
+      # Implement logging logic here
+      puts "Client at #{req.headers['REMOTE_ADDR']} wanted to access something /important!"
     end
+    get "answer" do
+      header "content-type", "application/json"
+      '{"answer":42, "desc":"something important!"}'
+    end
+  end
 end
 
-server.start
+run app
 
-

And a lot more to come (hopefully)

+

And a lot more to be found in /examples in this repo.

Documentation

@@ -195,7 +190,7 @@ server.start diff --git a/doc/index.html b/doc/index.html index cb12e47..9ae2507 100644 --- a/doc/index.html +++ b/doc/index.html @@ -67,108 +67,103 @@

A simple "Hello, World!" HTTP API using Hyde

-
require 'Hyde'
+
require 'hyde'
 
-server = Hyde::Server.new Port: 8000 do
-    get "/hello" do |ctx|
-        ctx.response.body = "Hello, World!"
-        ctx.response['Content-Type'] = "text/plain"
-    end
+app = Hyde::Server.new do
+  get "/hello" do
+    header "content-type", "text/plain"
+    "Hello world!"
+  end
 end
 
-server.start
+run app
 

A push/pull stack as an HTTP API

require 'hyde'
 
-Stack = []
+stack = []
 
-server = Hyde::Server.new Port: 8000 do
-    get "pull" do |ctx|
-        ctx.response.body = "#{Stack.pop}"
-        ctx.response["Content-Type"] = "text/plain"
-    end
-    post "push" do |ctx|
-        Stack.push ctx.request.body
-        ctx.response.body = "#{ctx.request.body}"
-        ctx.response["Content-Type"] = "text/plain"
-    end
+app = Hyde::Server.new do
+  get "/pop" do
+    header 'content-type', 'text/plain'
+    stack.pop.to_s
+  end
+  post "/push" do
+    header 'content-type', 'text/plain'
+    stack.push(request.body)
+    request.body
+  end
 end
 
-server.start
+run app
 

Several push/pull buckets

require 'hyde'
 
-Stack = {"bucket_1" => [], "bucket_2" => [], "bucket_3" => []}
+stack = { "1" => [], "2" => [], "3" => [] }
 
-server = Hyde::Server.new Port: 8000 do
-    path ["bucket_1","bucket_2","bucket_3"] do
-        get "pull" do |ctx|
-            bucket_name = (ctx.filepath.match /bucket_[^\/]*/)[0]
-            ctx.response.body = "#{Stack[bucket_name].pop}"
-            ctx.response["Content-Type"] = "text/plain"
-        end
-        post "push" do |ctx|
-            bucket_name = (ctx.filepath.match /bucket_[^\/]*/)[0]
-            Stack[bucket_name].push ctx.request.body
-            ctx.response.body = "#{ctx.request.body}"
-            ctx.response["Content-Type"] = "text/plain"
-        end
+app = Hyde::Server.new do
+  path "bucket_(1|2|3)" do
+    get "pop" do |bucket|
+      header "content-type", "text/plain"
+      stack[bucket].pop.to_s
     end
+    post "push" do |bucket|
+      header "content-type", "text/plain"
+      stack[bucket].push(request.body)
+      request.body
+    end
+  end
 end
 
-server.start
+run app
 

Static file serving (Note: index applies only to /var/www (to the path its defined in))

-
require 'hyde'
+
require 'hyde'
 
-server = Hyde::Server.new Port:8000 do
-    path "static" do
-        root "/var/www"
-        index ["index.html","index.htm"]
-        serve "*/*.html" safe_regexp: false
-        serve "*.html"
-    end
-end
+app = Hyde::Server.new do
+  root "/var/www"
+  index ["index.html","index.htm"]
+  serve "**/*.(html|htm)"
+end
 
-server.start
+run app
 

Logging on a particular path

require 'hyde'
 
-server = Hyde::Server.new Port:8000 do
-    path "unimportant" do
-        get "version" do |ctx|
-            ctx.response.body = '{"version": "the good one"}'
-            ctx.response['Content-Type'] = "application/json"
-        end
+app = Hyde::Server.new do
+  path "unimportant" do
+    get "version" do
+      header "content-type", "text/plain"
+      "1337 (the best one)"
     end
-    path "important" do
-        preprocess do |ctx|
-            # Implement logging logic here
-            puts "Client at #{ctx.request.remote_ip} wanted to access something /important!"
-        end
-        get "answer" do |ctx|
-            ctx.response.body = '{"answer":42}'
-            ctx.response['Content-Type'] = "application/json"
-        end
+  end
+  path "important" do
+    preprocess do |req|
+      # Implement logging logic here
+      puts "Client at #{req.headers['REMOTE_ADDR']} wanted to access something /important!"
     end
+    get "answer" do
+      header "content-type", "application/json"
+      '{"answer":42, "desc":"something important!"}'
+    end
+  end
 end
 
-server.start
+run app
 
-

And a lot more to come (hopefully)

+

And a lot more to be found in /examples in this repo.

Documentation

@@ -195,7 +190,7 @@ server.start diff --git a/doc/method_list.html b/doc/method_list.html index 4ddfb6b..43b0bf2 100644 --- a/doc/method_list.html +++ b/doc/method_list.html @@ -44,6 +44,70 @@
    +
  • +
    + [] + Hyde::Util::Lookup +
    +
  • + + +
  • +
    + #[] + Hyde::Util::Lookup +
    +
  • + + +
  • +
    + #[]= + Hyde::Util::Lookup +
    +
  • + + +
  • +
    + #add_header + Hyde::Response +
    +
  • + + +
  • +
    + #body + Hyde::Request +
    +
  • + + +
  • +
    + #body + Hyde::Response +
    +
  • + + +
  • +
    + #bounce + Hyde::DSL::ProbeMethods +
    +
  • + + +
  • +
    + #call + Hyde::Server +
    +
  • + +
  • can_convert? @@ -68,6 +132,262 @@
  • +
  • +
    + #children + Hyde::Path +
    +
  • + + +
  • +
    + chunk_body + Hyde::Response +
    +
  • + + +
  • +
    + #chunk_size + Hyde::Response +
    +
  • + + +
  • +
    + #connect + Hyde::DSL::PathConstructors +
    +
  • + + +
  • +
    + convert + Hyde::Response +
    +
  • + + +
  • +
    + default_error_page + Hyde::Util +
    +
  • + + +
  • +
    + #delete + Hyde::DSL::PathConstructors +
    +
  • + + +
  • +
    + #delete_header + Hyde::Response +
    +
  • + + +
  • +
    + #die + Hyde::DSL::ProbeMethods +
    +
  • + + +
  • +
    + escape_html + Hyde::Util +
    +
  • + + +
  • +
    + #filepath + Hyde::Request +
    +
  • + + +
  • +
    + #filter + Hyde::Path +
    +
  • + + +
  • +
    + #filter + Hyde::DSL::PathMethods +
    +
  • + + +
  • +
    + #finalize + Hyde::Response +
    +
  • + + +
  • +
    + #get + Hyde::DSL::PathConstructors +
    +
  • + + +
  • +
    + #go + Hyde::Node +
    +
  • + + +
  • +
    + #head + Hyde::DSL::PathConstructors +
    +
  • + + +
  • +
    + #header + Hyde::DSL::ProbeMethods +
    +
  • + + +
  • +
    + #headers + Hyde::Request +
    +
  • + + +
  • +
    + #headers + Hyde::Response +
    +
  • + + +
  • +
    + #index + Hyde::DSL::PathMethods +
    +
  • + + +
  • +
    + #initialize + Hyde::Node +
    +
  • + + +
  • +
    + #initialize + Hyde::PathBinding +
    +
  • + + +
  • +
    + #initialize + Hyde::Path +
    +
  • + + +
  • +
    + #initialize + Hyde::Probe +
    +
  • + + +
  • +
    + #initialize + Hyde::Server +
    +
  • + + +
  • +
    + #initialize + Hyde::Request +
    +
  • + + +
  • +
    + #initialize + Hyde::Response +
    +
  • + + +
  • +
    + #initialize + Hyde::Util::Query +
    +
  • + + +
  • +
    + #initialize + Hyde::Util::Lookup +
    +
  • + + +
  • +
    + #initialize + Hyde::ProbeBinding +
    +
  • + + +
  • +
    + #initialize + Hyde::Handler +
    +
  • + +
  • #initialize @@ -77,6 +397,14 @@
  • +
    + #initialize + Hyde::ServeHandler +
    +
  • + + +
  • #initialize Hyde::PatternMatching::Glob @@ -84,7 +412,7 @@
  • -
  • +
  • #initialize Hyde::PatternMatching::ReMatch @@ -92,7 +420,7 @@
  • -
  • +
  • #match Hyde::Pattern @@ -100,7 +428,7 @@
  • -
  • +
  • #match Hyde::PatternMatching::Glob @@ -108,7 +436,7 @@
  • -
  • +
  • #match Hyde::PatternMatching::ReMatch @@ -116,7 +444,7 @@
  • -
  • +
  • #match? Hyde::Pattern @@ -124,7 +452,7 @@
  • -
  • +
  • #match? Hyde::PatternMatching::Glob @@ -132,7 +460,7 @@
  • -
  • +
  • #match? Hyde::PatternMatching::ReMatch @@ -140,6 +468,382 @@
  • +
  • +
    + #options + Hyde::DSL::PathConstructors +
    +
  • + + +
  • +
    + #param + Hyde::Request +
    +
  • + + +
  • +
    + #parent + Hyde::Util::Lookup +
    +
  • + + +
  • +
    + #parse + Hyde::Util::Query +
    +
  • + + +
  • +
    + #parse_shallow + Hyde::Util::Query +
    +
  • + + +
  • +
    + #patch + Hyde::DSL::PathConstructors +
    +
  • + + +
  • +
    + #path + Hyde::Request +
    +
  • + + +
  • +
    + #path + Hyde::DSL::PathConstructors +
    +
  • + + +
  • +
    + #path_info + Hyde::Request +
    +
  • + + +
  • +
    + #pop_state + Hyde::Request +
    +
  • + + +
  • +
    + #post + Hyde::DSL::PathConstructors +
    +
  • + + +
  • +
    + #postprocess + Hyde::Path +
    +
  • + + +
  • +
    + #postprocess + Hyde::DSL::PathMethods +
    +
  • + + +
  • +
    + #postprocessors + Hyde::Request +
    +
  • + + +
  • +
    + #preprocess + Hyde::Path +
    +
  • + + +
  • +
    + #preprocess + Hyde::DSL::PathMethods +
    +
  • + + +
  • +
    + #probe + Hyde::DSL::PathConstructors +
    +
  • + + +
  • +
    + #process + Hyde::Node +
    +
  • + + +
  • +
    + #process + Hyde::Path +
    +
  • + + +
  • +
    + #process + Hyde::Probe +
    +
  • + + +
  • +
    + #process + Hyde::Handler +
    +
  • + + +
  • +
    + #process + Hyde::GETHandler +
    +
  • + + +
  • +
    + #process + Hyde::ServeHandler +
    +
  • + + +
  • +
    + #properties + Hyde::Path +
    +
  • + + +
  • +
    + #properties + Hyde::Probe +
    +
  • + + +
  • +
    + #push_state + Hyde::Request +
    +
  • + + +
  • +
    + #put + Hyde::DSL::PathConstructors +
    +
  • + + +
  • +
    + #query + Hyde::Request +
    +
  • + + +
  • +
    + #register + Hyde::DSL::PathConstructors +
    +
  • + + +
  • +
    + #reject + Hyde::Node +
    +
  • + + +
  • +
    + #remap + Hyde::Node +
    +
  • + + +
  • +
    + #remap + Hyde::DSL::PathMethods +
    +
  • + + +
  • +
    + #remove_header + Hyde::DSL::ProbeMethods +
    +
  • + + +
  • +
    + #request + Hyde::Handler +
    +
  • + + +
  • +
    + #request + Hyde::DSL::ProbeMethods +
    +
  • + + +
  • +
    + #request_method + Hyde::Request +
    +
  • + + +
  • +
    + #response + Hyde::Handler +
    +
  • + + +
  • +
    + #response + Hyde::ServeHandler +
    +
  • + + +
  • +
    + #root + Hyde::Node +
    +
  • + + +
  • +
    + #root + Hyde::DSL::PathMethods +
    +
  • + + +
  • +
    + #run_postprocessors + Hyde::Request +
    +
  • + + +
  • +
    + #script_name + Hyde::Request +
    +
  • + + +
  • +
    + #serve + Hyde::DSL::PathConstructors +
    +
  • + + +
  • +
    + #server_name + Hyde::Request +
    +
  • + + +
  • +
    + #server_port + Hyde::Request +
    +
  • + + +
  • +
    + #server_protocol + Hyde::Request +
    +
  • + + +
  • +
    + #splat + Hyde::Request +
    +
  • + +
  • #static? @@ -148,6 +852,38 @@
  • +
  • +
    + #status + Hyde::Response +
    +
  • + + +
  • +
    + #status + Hyde::DSL::ProbeMethods +
    +
  • + + +
  • +
    + #trace + Hyde::DSL::PathConstructors +
    +
  • + + +
  • +
    + #validate + Hyde::Response +
    +
  • + +
diff --git a/doc/top-level-namespace.html b/doc/top-level-namespace.html index 96455f7..6ebc842 100644 --- a/doc/top-level-namespace.html +++ b/doc/top-level-namespace.html @@ -100,7 +100,7 @@ diff --git a/examples/form/form.ru b/examples/form/form.ru new file mode 100644 index 0000000..ccb7806 --- /dev/null +++ b/examples/form/form.ru @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/lib") +require 'hyde' +require 'hyde/util/multipart' +require 'hyde/util/header' + +app = Hyde::Server.new do + root ENV["PWD"] + index ["index.html"] + post "/" do + _, opts = Hyde::Util.parse_value(request.headers["content-type"]) + puts Hyde::Util::MultipartParser.new( + request.input, opts["boundary"] + ).to_h.pretty_inspect + bounce + end + serve "*.html" +end + +run app diff --git a/examples/form/index.html b/examples/form/index.html new file mode 100644 index 0000000..bb209c2 --- /dev/null +++ b/examples/form/index.html @@ -0,0 +1,27 @@ + + + + Form upload test + + + +

Form upload test

+
+

Please enter the following details:

+

+ + + + + + + +
+ + + + diff --git a/examples/form/lib b/examples/form/lib new file mode 120000 index 0000000..58677dd --- /dev/null +++ b/examples/form/lib @@ -0,0 +1 @@ +../../lib \ No newline at end of file diff --git a/examples/query/config.ru b/examples/query/config.ru new file mode 100644 index 0000000..588afb6 --- /dev/null +++ b/examples/query/config.ru @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/lib") +require_relative 'lib/hyde' + +app = Hyde::Server.new do + get "/hello" do + name = request.query["name"] + if name.is_a? String + "Hello #{name.downcase.capitalize}!" + elsif name.is_a? Array + "Hello #{name.map { |x| x.downcase.capitalize }.join(', ')}!" + else + "Hello user!" + end + end +end + +run app diff --git a/examples/query/lib b/examples/query/lib new file mode 120000 index 0000000..58677dd --- /dev/null +++ b/examples/query/lib @@ -0,0 +1 @@ +../../lib \ No newline at end of file diff --git a/examples/query/readme.txt b/examples/query/readme.txt new file mode 100644 index 0000000..1295126 --- /dev/null +++ b/examples/query/readme.txt @@ -0,0 +1,6 @@ +This example illustrates a basic API that responds with "Hello !" and receives arrays and strings as parameter. + +P.S. there is at least *one* vulnerability in this exmaple. +If you don't know which one you definitely want to read about XSS before it's too late +(https://owasp.org/www-community/attacks/xss/) + diff --git a/lib/hyde/request.rb b/lib/hyde/request.rb index 6681294..27e0b85 100644 --- a/lib/hyde/request.rb +++ b/lib/hyde/request.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'uri' +require_relative 'util/query' module Hyde # Request wrapper for Rack protocol @@ -11,6 +12,8 @@ module Hyde @_original_env = env # Rack environment variable bindings. Should be public and frozen. init_request_params(env) + # Query parsing + @query = Hyde::Util::Query.new(@query_string) # Pattern matching parameters. Public, readable, unfrozen. @param = {} @splat = [] @@ -37,7 +40,13 @@ module Hyde # Returns request body (if POST data exists) # @return [nil, String] def body - @body ||= @rack.input&.gets + @body ||= @rack.input&.read + end + + # Returns raw Rack input object + # @return [IO] (May not entirely be compatible with IO, see Rack/SPEC.rdoc) + def input + @rack.input end # Push current navigation state (path, splat, param) onto state stack @@ -52,7 +61,7 @@ module Hyde attr_reader :request_method, :script_name, :path_info, :server_name, :server_port, :server_protocol, :headers, :param, :splat, - :postprocessors + :postprocessors, :query attr_accessor :path, :filepath private @@ -63,6 +72,7 @@ module Hyde @request_method = env["REQUEST_METHOD"] @script_name = env["SCRIPT_NAME"] @path_info = env["PATH_INFO"] + @query_string = env["QUERY_STRING"] @server_name = env["SERVER_NAME"] @server_port = env["SERVER_PORT"] @server_protocol = env["SERVER_PROTOCOL"] @@ -111,10 +121,12 @@ module Hyde headers = env.filter_map do |name, value| [name.delete_prefix("HTTP_"), value] if name.start_with?("HTTP_") end.to_h - headers.merge!({ "CONTENT_TYPE" => env["CONTENT_TYPE"], - "CONTENT_LENGTH" => env["CONTENT_LENGTH"], + headers.merge!({ "CONTENT-TYPE" => env["CONTENT_TYPE"], + "CONTENT-LENGTH" => env["CONTENT_LENGTH"], "REMOTE_ADDR" => env["REMOTE_ADDR"] }) - headers.freeze + headers.transform_keys do |x| + x.downcase.gsub("_", "-") if x.is_a? String + end.freeze end end end diff --git a/lib/hyde/util/header.rb b/lib/hyde/util/header.rb new file mode 100644 index 0000000..54671c1 --- /dev/null +++ b/lib/hyde/util/header.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +require 'uri' + +module Hyde + module Util + # Parse parametrized header values + # @param input [String] + # @param sep [String, Regexp] + # @return [Array(String, Hash)] + def self.parse_value(input, sep = ";") + parts = input.split(sep).map { |x| URI.decode_uri_component(x).strip } + base = parts.shift + opts = parts.map do |raw| + key, value = raw.match(/^([^=]*)(?:=(.*)|)\Z/).to_a[1..] + [key, ((value&.match?(/^".*"$/) ? value[1..-2] : value) or true)] + end.to_h + [base, opts] + end + + # Construct a parametrized header value + # @param input [String] + # @param opts [Hash] + # @return [String] + def self.make_value(input, opts, sep = ";") + unless input.match?(/^[\w!#$%&'*+-.^_`|~]*=?[^[:cntrl:]\\",;]+$/) + raise StandardError, "input contains invalid characters" + end + + output = input + opts.each do |key, value| + output += if value.is_a? String + "#{sep} #{key}=#{value}" + else + "#{sep} #{key}" + end + end + output + end + end +end diff --git a/lib/hyde/util/html.rb b/lib/hyde/util/html.rb index ed797f2..867815f 100644 --- a/lib/hyde/util/html.rb +++ b/lib/hyde/util/html.rb @@ -58,7 +58,10 @@ module Hyde 511 => 'Network Authentication Required' }.freeze - # Return string with escaped HTML entities + # Return string with escaped HTML entities. + # @note Do **not** use this to inject untrusted input into JavaScript code + # or CSS style of the page. + # This function is not adequate to prevent string interpolation. # @param str [String] # @return [String] def self.escape_html(str) diff --git a/lib/hyde/util/multipart.rb b/lib/hyde/util/multipart.rb new file mode 100644 index 0000000..8b589ad --- /dev/null +++ b/lib/hyde/util/multipart.rb @@ -0,0 +1,165 @@ +# frozen_string_literal: false + +require 'uri' +require 'stringio' +require 'tempfile' +require_relative 'header' + +module Hyde + module Util + # Valid element of form data with headers + # @!attribute headers [Hash] headers recevied from form data + # @!attribute name [String] name of the form part + # @!attribute data [String,nil] Data received in the field through form data + # @!attribute filename [String,nil] Original name of the sent file + # @!attribute filetype [String,nil] MIME-type of the file + # @!attribute tempfile [File,nil] Temporary file for storing sent file data. + FormPart = Struct.new(:data, :name, :filename, + :filetype, :tempfile, :headers) do + # Is this form part a file or plain data? + # @return [Boolean] + def file? + !tempfile.nil? + end + + # If FormPart is not a file, simplify to string. + # @return [FormPart, String] + def simplify + file? ? self : self.data + end + end + + # A very naive implementation of a Multipart form parser. + class MultipartParser + include Hyde::Util::ParserCommon + def initialize(io, boundary) + @input = io.is_a?(String) ? StringIO.new(io) : io + @boundary = boundary + @state = :idle + @data = [] + end + + # lord forgive me for what i'm about to do + # TODO: replace the god method with a state machine object + # rubocop:disable Metrics/* + + # Parse multipart formdata + # @return [Array] + def parse + return @data unless @data.empty? + + while (line = @input.gets) + case @state + when :idle # waiting for valid boundary + if line == "--#{@boundary}\r\n" + # transition to :headers on valid boundary + @state = :headers + @data.append(FormPart.new(*([nil] * 5), {})) + end + when :headers # after valid boundary - checking for headers + if line == "\r\n" + # prepare form field and transition to :data or :file + @state = file?(@data[-1].headers) ? :file : :data + if @state == :data + setup_data_meta(@data[-1]) + else + setup_file_meta(@data[-1]) + end + next + end + push_header(line, @data[-1].headers) + when :data, :file # after headers - processing form data + if @data[-1].headers.empty? + # transition to :idle on empty headers + @state = :idle + next + end + if ["--#{@boundary}\r\n", "--#{@boundary}--\r\n"].include? line + # finalize and transition to either :headers or :idle + if @state == :file + @data[-1].tempfile.truncate(@data[-1].tempfile.size - 2) + @data[-1].tempfile.close + else + @data[-1].data.delete_suffix! "\r\n" + end + @state = line == "--#{@boundary}\r\n" ? :headers : :idle + @data.append(FormPart.new(*([nil] * 5), {})) + next + end + if @state == :data + @data[-1].data ||= "" + @data[-1].data << line + else + @data[-1].tempfile << line + end + end + end + @state = :idle + @data.pop + @data.freeze + end + # rubocop:enable Metrics/* + + # Return a hash of current form. + # (equivalent to Query.parse but for multipart/form-data) + # @return [Hash] + def to_h + flatten(sort(gen_hash(parse))) + end + + private + + def gen_hash(array) + hash = {} + array.each do |formpart| + key = formpart.name.to_s + if key.match?(/.*\[\d*\]\Z/) + new_key, index = key.match(/(.*)\[(\d*)\]\Z/).to_a[1..] + hash[new_key] = [] unless hash[new_key] + hash[new_key].append([index, formpart.simplify]) + else + hash[key] = formpart.simplify + end + end + hash + end + + # Setup file metadata + # @part part [FormPart] + def setup_file_meta(part) + part.name = part.headers.dig("content-disposition", 1, "name") + part.filename = part.headers.dig("content-disposition", 1, "filename") + part.filetype = part.headers["content-type"] + part.tempfile = Tempfile.new + end + + # Setup plain metadata + # @part part [FormPart] + def setup_data_meta(part) + part.name = part.headers.dig("content-disposition", 1, "name") + end + + # Analyze headers to check if current data part is a file. + # @param headers_hash [Hash] + # @return [Boolean] + def file?(headers_hash) + if headers_hash.dig("content-disposition", 1, "filename") and + headers_hash['content-type'] + return true + end + + false + end + + # Parse a header and append it to headers_hash + # @param line [String] + # @param headers_hash [Hash] + def push_header(line, headers_hash) + return unless line.match(/^[\w!#$%&'*+-.^_`|~]+:.*\r\n$/) + + k, v = line.match(/^([\w!#$%&'*+-.^_`|~]+):(.*)\r\n$/).to_a[1..] + headers_hash[k.downcase] = Hyde::Util.parse_value(v) + end + end + end +end diff --git a/lib/hyde/util/query.rb b/lib/hyde/util/query.rb new file mode 100644 index 0000000..24858f0 --- /dev/null +++ b/lib/hyde/util/query.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +require 'uri' +require_relative 'sorting' + +module Hyde + module Util + # Query string parser + class Query + include Hyde::Util::ParserCommon + # @param query [String] + def initialize(query) + @query = query + end + + # Shallow query parser (does not do PHP-like array keys) + # @return [Hash] + def parse_shallow + URI.decode_www_form(@query, Encoding::UTF_8) + .sort_by { |array| array[0] } + .to_h + end + + # Better(tm) query parser with + # Returns a hash with arrays + # Key semantics: + # + # - `key=value` creates a key value pair + # - `key[]=value` appends `value` to an array named `key` + # - `key[index]=value` sets `value` at `index` of array named `key` + # @return [Hash] + def parse + construct_deep_hash(URI.decode_www_form(@query, Encoding::UTF_8)) + end + + # Get key from query + # @param key [String] + # @return [String,Array] + def [](key) + (@cache ||= parse)[key] + end + + private + + # Construct a hash with array support + def construct_deep_hash(array) + flatten(sort(group(array))) + end + + # Assign values to keys in a new hash and group arrayable keys + def group(array) + hash = {} + array.each do |key, value| + if key.match?(/.*\[\d*\]\Z/) + new_key, index = key.match(/(.*)\[(\d*)\]\Z/).to_a[1..] + hash[new_key] = [] unless hash[new_key] + hash[new_key].append([index, value]) + else + hash[key] = value + end + end + hash + end + end + end +end diff --git a/lib/hyde/util/sorting.rb b/lib/hyde/util/sorting.rb new file mode 100644 index 0000000..a9a1af4 --- /dev/null +++ b/lib/hyde/util/sorting.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +module Hyde + module Util + # Internal library for generating form hashes + module ParserCommon + private + + # Sort key-value pair arrays + def sort(hash) + hash.filter { |_, v| v.is_a? Array }.each do |_, value| + value.sort_by! { |array| array[0].to_i } + end + hash + end + + # Flatten key-value pair arrays + def flatten(hash) + hash.transform_values do |value| + if value.is_a? Array + new_array = [] + value.each do |k, v| + if k.match?(/\d+/) and k.to_i < new_array.size + new_array[k.to_i] = v + else + new_array.append(v) + end + end + new_array + else + value + end + end.to_h + end + end + end +end diff --git a/test/Hyde_Util_Query.rb b/test/Hyde_Util_Query.rb new file mode 100644 index 0000000..eb9472c --- /dev/null +++ b/test/Hyde_Util_Query.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +require_relative "../lib/hyde/util/query" +require "test/unit" + +class TestQuery < Test::Unit::TestCase + include Hyde::Util + def test_query + test1 = Query.new("key1=1&key2=2&key3[]=1&key3[]=2&key3[]=3") + assert_equal({"key1"=>"1","key2"=>"2","key3"=>["1","2","3"]},test1.parse) + test2 = Query.new("key1[1]=1&key1[500]=3&key1[50]=2") + assert_equal({"key1"=>["1","2","3"]},test2.parse) + test3 = Query.new("array[]=1&array[]=2&array[0]=0&array[500]=3") + assert_equal({"array"=>["0","2","3"]},test3.parse) + end +end