Messages from %l to %g

This commit is contained in:
Elliot Glaysher 2018-09-20 16:36:04 -07:00
parent 36841a5280
commit e172e601f2
2 changed files with 203 additions and 36 deletions

View File

@ -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)

View File

@ -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: {<actual>}"]~
::
%+ weld
(expect-eq !>(wire.expected) !>(p.actual))
::
=/ note=note:light-gate q.actual
?. ?=([%g %deal *] note)
[%leaf "bad move, not a %deal: {<actual>}"]~
::
%+ 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)
--