From e172e601f25b6fdb19f80b74e8591aba8fa382e2 Mon Sep 17 00:00:00 2001 From: Elliot Glaysher Date: Thu, 20 Sep 2018 16:36:04 -0700 Subject: [PATCH] Messages from %l to %g --- sys/vane/light.hoon | 108 ++++++++++++++++++++++--------- tests/sys/vane/light.hoon | 131 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 203 insertions(+), 36 deletions(-) diff --git a/sys/vane/light.hoon b/sys/vane/light.hoon index 4affc48d1..d9db1145c 100644 --- a/sys/vane/light.hoon +++ b/sys/vane/light.hoon @@ -118,14 +118,14 @@ :: +http-method: exhaustive list of http verbs :: +$ http-method - $? %'CONNECT' - %'DELETE' - %'GET' - %'HEAD' - %'OPTIONS' - %'POST' - %'PUT' - %'TRACE' + $? _'CONNECT' + _'DELETE' + _'GET' + _'HEAD' + _'OPTIONS' + _'POST' + _'PUT' + _'TRACE' == :: +http-request: a single http-request :: @@ -174,6 +174,13 @@ :: :: $% [%build our=@p live=? schematic=schematic:ford] + == == + :: %g: to gall + :: + $: %g + :: + :: + $% [%deal id=sock data=cush:gall] == == == -- :: more structures @@ -208,6 +215,13 @@ :: the :binding into a (map (unit @t) (trie knot =action)). :: bindings=(list [=binding =duct =action]) + :: outstanding: open http connections not fully complete + :: + :: This refers to outstanding connections where the connection to + :: outside is opened and we are currently waiting on ford or an app to + :: produce the results. + :: + outstanding=(map duct action) == :: +action: the action to take when a binding matches an incoming request :: @@ -229,6 +243,23 @@ :: utilities :: |% +:: +file-not-found-page: 404 page for when all other options failed +:: +++ file-not-found-page + |= url=@t + ^- octs + %- as-octs:mimes:html + %- crip + %- en-xml:html + ;html + ;head + ;title:"404 Not Found" + == + ;body + ;h1:"Not Found" + ;p:"The requested URL {<(trip url)>} was not found on this server." + == + == :: +get-header: returns the value for :header, if it exists in :header-list :: ++ get-header @@ -247,28 +278,52 @@ ++ per-server-event |= [[our=@p =duct now=@da scry=sley] state=server-state] |% + :: +request: starts handling an inbound http request + :: ++ request |= [secure=? =address =http-request] ^- [(list move) server-state] :: =+ host=(get-header 'Host' header-list.http-request) =+ action=(get-action-for-binding host url.http-request) + :: if no action matches, send the built in 404 page. :: ?~ action - ~& %no-match-for-request - :: todo: return a reconstruction of the apache 404 page here - :: - [~ state] + :_ state + :_ ~ + :+ duct %give + :* %http-response %start + status-code=404 + :: TODO: Content-Length? + headers=['Content-Type' 'text/html']~ + data=[~ (file-not-found-page url.http-request)] + complete=%.y + == + :: record that we started an asynchronous response + :: + =. outstanding.state (~(put by outstanding.state) duct u.action) :: ?- -.u.action :: %gen + :: TODO: when we get here, we need to make sure that the generator has + :: been compiled. + :: ~& [%i-should-run-a-generator generator.u.action] [~ state] :: %app - ~& [%i-should-run-an-app app.u.action] - [~ state] + :_ state + :_ ~ + :^ duct %pass /run-app/[app.u.action] + ^- note + :^ %g %deal [our our] + :: todo: i don't entirely understand gall; there's a way to make a gall + :: use a %handle arm instead of a sub-%poke with the + :: %handle-http-request type. + :: + ^- cush:gall + [app.u.action %poke %handle-http-request !>([secure address http-request])] == :: +add-binding: conditionally add a pairing between binding and action :: @@ -311,16 +366,6 @@ ^- ? &(=(item-binding binding) =(item-duct duct)) == - - :: - :: Split string by parsing rule delimiter. - ++ split - |* {str/tape delim/cord} - ^- (list tape) - %+ fall - (rust str (more (jest delim) (star ;~(less (jest delim) next)))) - [str ~] - :: +get-action-for-binding: finds an action for an incoming web request :: ++ get-action-for-binding @@ -352,12 +397,8 @@ raw-host :: url is the raw thing passed over the 'Request-Line'. :: - :: We need to handle both the form 'http://one.com/two/three' and - :: '/two/three', but we're punting for now and just doing a split on - :: '/'. - :: =/ parsed-url=(list @t) - (turn (split (trip url) '/') crip) + q:(need (rush url apat:de-purl:html)) :: =/ bindings bindings.state |- @@ -366,8 +407,13 @@ ~ :: ?: ?& =(site.binding.i.bindings host) - =(`0 (find path.binding.i.bindings parsed-url)) - == + ?| :: root directory + :: + &(=(~ parsed-url) =(~ path.binding.i.bindings)) + :: everything else + :: + =(`0 (find path.binding.i.bindings parsed-url)) + == == `action.i.bindings :: $(bindings t.bindings) diff --git a/tests/sys/vane/light.hoon b/tests/sys/vane/light.hoon index 66bed5962..5796682fe 100644 --- a/tests/sys/vane/light.hoon +++ b/tests/sys/vane/light.hoon @@ -152,8 +152,51 @@ results3 results4 == +:: tests that when we have no match, that we fall back to the built-in 404 :: -++ test-basic-request +++ test-builtin-four-oh-four + :: + =^ results1 light-gate + %- light-call :* + light-gate + now=~1111.1.1 + scry=*sley + call-args=[duct=~[/init] ~ [%init ~nul]] + expected-moves=~ + == + :: when there's no configuration and nothing matches, expect 404 + :: + =^ results2 light-gate + %- light-call :* + light-gate + now=~1111.1.1 + scry=*sley + ^= call-args + :* duct=~[/http-blah] ~ + %inbound-request + %.n + [%ipv4 .192.168.1.1] + ['GET' '/' ~ ~] + == + ^= expectec-moves + ^- (list move:light-gate) + :~ :* duct=~[/http-blah] + %give + %http-response + %start + 404 + ['Content-Type' 'text/html']~ + [~ (file-not-found-page:light-gate '/')] + complete=%.y + == == + == + :: + ;: weld + results1 + results2 + == +:: +++ test-basic-app-request :: =^ results1 light-gate %- light-call :* @@ -173,15 +216,42 @@ call-args=[duct=~[/app1] ~ [%connect [~ /] %app1]] expected-moves=[duct=~[/app1] %give %bound %.y [~ /]]~ == - :: + :: outside requests a path that app1 has bound to :: =^ results3 light-gate - %- light-call :* + %- light-call-with-comparator :* light-gate now=~1111.1.3 scry=*sley - call-args=[duct=~[/http-blah] ~ [%inbound-request %.n [%ipv4 .192.168.1.1]]] - expectec-moves=~ + ^= call-args + :* duct=~[/http-blah] ~ + %inbound-request + %.n + [%ipv4 .192.168.1.1] + ['GET' '/' ~ ~] + == + ^= comparator + |= moves=(list move:light-gate) + ^- tang + :: + ?. ?=([* ~] moves) + [%leaf "wrong number of moves: {<(lent moves)>}"]~ + :: + :: + =/ move=move:light-gate i.moves + =/ =duct duct.move + =/ card=(wind note:light-gate gift:able:light-gate) card.move + :: + %+ weld + (expect-eq !>(~[/http-blah]) !>(duct)) + :: + %+ expect-gall-deal + :+ /run-app/app1 [~nul ~nul] + ^- cush:gall + :* %app1 %poke %handle-http-request + !>([%.n [%ipv4 .192.168.1.1] ['GET' '/' ~ ~]]) + == + card == ;: weld results1 @@ -208,4 +278,55 @@ !> moves :: [output light-gate] +:: +++ light-call-with-comparator + |= $: light-gate=_light-gate + now=@da + scry=sley + call-args=[=duct type=* wrapped-task=(hobo task:able:light-gate)] + move-comparator=$-((list move:light-gate) tang) + == + ^- [tang _light-gate] + :: + =/ light-core (light-gate now=now eny=0xdead.beef scry=scry) + :: + =^ moves light-gate (call:light-core call-args) + :: + =/ output=tang (move-comparator moves) + :: + [output light-gate] +:: +++ expect-gall-deal + |= $: expected=[wire=path id=sock data=cush:gall] + actual=(wind note:light-gate gift:able:light-gate) + == + ^- tang + :: + ?. ?=(%pass -.actual) + [%leaf "bad move, not a %pass: {}"]~ + :: + %+ weld + (expect-eq !>(wire.expected) !>(p.actual)) + :: + =/ note=note:light-gate q.actual + ?. ?=([%g %deal *] note) + [%leaf "bad move, not a %deal: {}"]~ + :: + %+ weld + (expect-eq !>(id.expected) !>(id.note)) + :: + %+ weld + (expect-eq !>(p.data.expected) !>(p.data.note)) + :: todo: handle other deals + :: + ?. ?=([%poke *] q.data.note) + [%leaf "todo: can only handle %poke right now"]~ + ?. ?=([%poke *] q.data.expected) + [%leaf "todo: can only handle %poke right now"]~ + :: + %+ weld + (expect-eq !>(p.p.q.data.expected) !>(p.p.q.data.note)) + :: compare the payload vases + :: + (expect-eq q.p.q.data.expected q.p.q.data.note) --