]> gitweb.factorcode.org Git - factor.git/commitdiff
Implement flash scopes, improved validation and login page, improved http-post
authorSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Thu, 5 Jun 2008 00:54:05 +0000 (19:54 -0500)
committerSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Thu, 5 Jun 2008 00:54:05 +0000 (19:54 -0500)
34 files changed:
extra/furnace/actions/actions.factor
extra/furnace/asides/asides.factor [new file with mode: 0644]
extra/furnace/auth/login/login.factor
extra/furnace/auth/login/login.xml
extra/furnace/flash/flash.factor [new file with mode: 0644]
extra/furnace/flows/flows.factor [deleted file]
extra/furnace/furnace-tests.factor
extra/furnace/furnace.factor
extra/furnace/sessions/sessions.factor
extra/html/components/components.factor
extra/html/templates/chloe/chloe-tests.factor
extra/html/templates/chloe/chloe.factor
extra/html/templates/chloe/test/test10.xml [new file with mode: 0644]
extra/html/templates/chloe/test/test11.xml [new file with mode: 0644]
extra/http/http-tests.factor
extra/http/http.factor
extra/http/server/cgi/cgi.factor
extra/http/server/server-tests.factor [new file with mode: 0644]
extra/http/server/server.factor
extra/webapps/factor-website/factor-website.factor
extra/webapps/pastebin/paste.xml
extra/webapps/pastebin/pastebin-common.xml
extra/webapps/pastebin/pastebin.factor
extra/webapps/planet/planet-common.xml
extra/webapps/planet/planet.factor
extra/webapps/todo/todo.factor
extra/webapps/todo/todo.xml
extra/webapps/user-admin/user-admin.factor
extra/webapps/user-admin/user-admin.xml
extra/webapps/wiki/changes.xml
extra/webapps/wiki/wiki-common.xml
extra/webapps/wiki/wiki.factor
extra/xml-rpc/example.factor
extra/xml-rpc/xml-rpc.factor

index 5e237b02a85e55027225affdce371ddbec0022cb..7340a532e9409b79d60879e4ade97f0218c0a3c0 100755 (executable)
@@ -2,13 +2,15 @@
 ! See http://factorcode.org/license.txt for BSD license.\r
 USING: accessors sequences kernel assocs combinators\r
 validators http hashtables namespaces fry continuations locals\r
-io arrays math boxes\r
+io arrays math boxes splitting urls\r
 xml.entities\r
 http.server\r
 http.server.responses\r
 furnace\r
+furnace.flash\r
 html.elements\r
 html.components\r
+html.components\r
 html.templates.chloe\r
 html.templates.chloe.syntax ;\r
 IN: furnace.actions\r
@@ -39,47 +41,67 @@ TUPLE: action rest-param init display validate submit ;
 : <action> ( -- action )\r
     action new-action ;\r
 \r
+: flashed-variables ( -- seq )\r
+    { validation-messages named-validation-messages } ;\r
+\r
 : handle-get ( action -- response )\r
-    blank-values\r
-    [ init>> call ]\r
-    [ display>> call ]\r
-    bi ;\r
+    '[\r
+        ,\r
+        [ init>> call ]\r
+        [ drop flashed-variables restore-flash ]\r
+        [ display>> call ]\r
+        tri\r
+    ] with-exit-continuation ;\r
 \r
 : validation-failed ( -- * )\r
-    request get method>> "POST" =\r
-    [ action get display>> call ] [ <400> ] if exit-with ;\r
+    request get method>> "POST" = [ f ] [ <400> ] if exit-with ;\r
 \r
-: handle-post ( action -- response )\r
-    init-validation\r
-    blank-values\r
-    [ validate>> call ]\r
-    [ submit>> call ] bi ;\r
+: (handle-post) ( action -- response )\r
+    [ validate>> call ] [ submit>> call ] bi ;\r
 \r
-: handle-rest-param ( arg -- )\r
-    dup length 1 > action get rest-param>> not or\r
-    [ <404> exit-with ] [\r
-        action get rest-param>> associate rest-param set\r
-    ] if ;\r
+: param ( name -- value )\r
+    params get at ;\r
 \r
-M: action call-responder* ( path action -- response )\r
-    dup action set\r
-    '[\r
-        , dup empty? [ drop ] [ handle-rest-param ] if\r
+: revalidate-url-key "__u" ;\r
 \r
-        init-validation\r
-        ,\r
-        request get\r
-        [ request-params rest-param get assoc-union params set ]\r
-        [ method>> ] bi\r
-        {\r
-            { "GET" [ handle-get ] }\r
-            { "HEAD" [ handle-get ] }\r
-            { "POST" [ handle-post ] }\r
-        } case\r
-    ] with-exit-continuation ;\r
+: check-url ( url -- ? )\r
+    request get url>>\r
+    [ [ protocol>> ] [ host>> ] [ port>> ] tri 3array ] bi@ = ;\r
 \r
-: param ( name -- value )\r
-    params get at ;\r
+: revalidate-url ( -- url/f )\r
+    revalidate-url-key param dup [ >url dup check-url swap and ] when ;\r
+\r
+: handle-post ( action -- response )\r
+    '[\r
+        form-nesting-key params get at " " split\r
+        [ , (handle-post) ]\r
+        [ swap '[ , , nest-values ] ] reduce\r
+        call\r
+    ] with-exit-continuation\r
+    [\r
+        revalidate-url\r
+        [ flashed-variables <flash-redirect> ] [ <403> ] if*\r
+    ] unless* ;\r
+\r
+: handle-rest-param ( path action -- assoc )\r
+    rest-param>> dup [ associate ] [ 2drop f ] if ;\r
+\r
+: init-action ( path action -- )\r
+    blank-values\r
+    init-validation\r
+    handle-rest-param\r
+    request get request-params assoc-union params set ;\r
+\r
+M: action call-responder* ( path action -- response )\r
+    [ init-action ] keep\r
+    request get method>> {\r
+        { "GET" [ handle-get ] }\r
+        { "HEAD" [ handle-get ] }\r
+        { "POST" [ handle-post ] }\r
+    } case ;\r
+\r
+M: action modify-form\r
+    drop request get url>> revalidate-url-key hidden-form-field ;\r
 \r
 : check-validation ( -- )\r
     validation-failed? [ validation-failed ] when ;\r
diff --git a/extra/furnace/asides/asides.factor b/extra/furnace/asides/asides.factor
new file mode 100644 (file)
index 0000000..f6b4e2c
--- /dev/null
@@ -0,0 +1,73 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors namespaces sequences arrays kernel
+assocs assocs.lib hashtables math.parser urls combinators
+furnace http http.server http.server.filters furnace.sessions
+html.elements html.templates.chloe.syntax ;
+IN: furnace.asides
+
+TUPLE: asides < filter-responder ;
+
+C: <asides> asides
+
+: begin-aside* ( -- id )
+    request get
+    [ url>> ] [ post-data>> ] [ method>> ] tri 3array
+    asides sget set-at-unique
+    session-changed ;
+
+: end-aside-post ( url post-data -- response )
+    request [
+        clone
+            swap >>post-data
+            swap >>url
+    ] change
+    request get url>> path>> split-path
+    asides get responder>> call-responder ;
+
+ERROR: end-aside-in-get-error ;
+
+: end-aside* ( url id -- response )
+    request get method>> "POST" = [ end-aside-in-get-error ] unless
+    asides sget at [
+        first3 {
+            { "GET" [ drop <redirect> ] }
+            { "HEAD" [ drop <redirect> ] }
+            { "POST" [ end-aside-post ] }
+        } case
+    ] [ <redirect> ] ?if ;
+
+SYMBOL: aside-id
+
+: aside-id-key "__a" ;
+
+: begin-aside ( -- )
+    begin-aside* aside-id set ;
+
+: end-aside ( default -- response )
+    aside-id [ f ] change end-aside* ;
+
+M: asides call-responder*
+    dup asides set
+    aside-id-key request get request-params at aside-id set
+    call-next-method ;
+
+M: asides init-session*
+    H{ } clone asides sset
+    call-next-method ;
+
+M: asides link-attr ( tag -- )
+    drop
+    "aside" optional-attr {
+        { "none" [ aside-id off ] }
+        { "begin" [ begin-aside ] }
+        { "current" [ ] }
+        { f [ ] }
+    } case ;
+
+M: asides modify-query ( query responder -- query' )
+    drop
+    aside-id get [ aside-id-key associate assoc-union ] when* ;
+
+M: asides modify-form ( responder -- )
+    drop aside-id get aside-id-key hidden-form-field ;
index 58ab47e3e1c6fb871b9cc995bb23afbe549123b5..d0c4e00953a3700c5e0df37982f1aed64895a8bb 100755 (executable)
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.\r
 USING: accessors quotations assocs kernel splitting\r
 combinators sequences namespaces hashtables sets\r
-fry arrays threads qualified random validators\r
+fry arrays threads qualified random validators words\r
 io\r
 io.sockets\r
 io.encodings.utf8\r
@@ -26,14 +26,29 @@ furnace.auth
 furnace.auth.providers\r
 furnace.auth.providers.db\r
 furnace.actions\r
-furnace.flows\r
+furnace.asides\r
+furnace.flash\r
 furnace.sessions\r
 furnace.boilerplate ;\r
 QUALIFIED: smtp\r
 IN: furnace.auth.login\r
 \r
+: word>string ( word -- string )\r
+    [ word-vocabulary ] [ drop ":" ] [ word-name ] tri 3append ;\r
+\r
+: words>strings ( seq -- seq' )\r
+    [ word>string ] map ;\r
+\r
+: string>word ( string -- word )\r
+    ":" split1 swap lookup ;\r
+\r
+: strings>words ( seq -- seq' )\r
+    [ string>word ] map ;\r
+\r
 TUPLE: login < dispatcher users checksum ;\r
 \r
+TUPLE: protected < filter-responder description capabilities ;\r
+\r
 : users ( -- provider )\r
     login get users>> ;\r
 \r
@@ -64,7 +79,7 @@ M: user-saver dispose
 \r
 ! ! ! Login\r
 : successful-login ( user -- response )\r
-    username>> set-uid URL" $login" end-flow ;\r
+    username>> set-uid URL" $login" end-aside ;\r
 \r
 : login-failed ( -- * )\r
     "invalid username or password" validation-error\r
@@ -72,6 +87,13 @@ M: user-saver dispose
 \r
 : <login-action> ( -- action )\r
     <page-action>\r
+        [\r
+            protected fget [\r
+                [ description>> "description" set-value ]\r
+                [ capabilities>> words>strings "capabilities" set-value ] bi\r
+            ] when*\r
+        ] >>init\r
+\r
         { login "login" } >>template\r
 \r
         [\r
@@ -177,7 +199,7 @@ M: user-saver dispose
 \r
             drop\r
 \r
-            URL" $login" end-flow\r
+            URL" $login" end-aside\r
         ] >>submit ;\r
 \r
 ! ! ! Password recovery\r
@@ -290,23 +312,23 @@ SYMBOL: lost-password-from
     <action>\r
         [\r
             f set-uid\r
-            URL" $login" end-flow\r
+            URL" $login" end-aside\r
         ] >>submit ;\r
 \r
 ! ! ! Authentication logic\r
-\r
-TUPLE: protected < filter-responder capabilities ;\r
-\r
-C: <protected> protected\r
+: <protected> ( responder -- protected )\r
+    protected new\r
+        swap >>responder ;\r
 \r
 : show-login-page ( -- response )\r
-    begin-flow\r
-    URL" $login/login" <redirect> ;\r
+    begin-aside\r
+    URL" $login/login" { protected } <flash-redirect> ;\r
 \r
 : check-capabilities ( responder user -- ? )\r
     [ capabilities>> ] bi@ subset? ;\r
 \r
 M: protected call-responder* ( path responder -- response )\r
+    dup protected set\r
     uid dup [\r
         users get-user 2dup check-capabilities [\r
             [ logged-in-user set ] [ save-user-after ] bi\r
@@ -337,7 +359,9 @@ M: login call-responder* ( path responder -- response )
 ! ! ! Configuration\r
 \r
 : allow-edit-profile ( login -- login )\r
-    <edit-profile-action> f <protected> <login-boilerplate>\r
+    <edit-profile-action> <protected>\r
+        "edit your profile" >>description\r
+    <login-boilerplate>\r
         "edit-profile" add-responder ;\r
 \r
 : allow-registration ( login -- login )\r
index a52aed59d7bb74bb7f8df2ec7fc8680d027b4412..a7ac92bf442b76a6a57bf562c4e9afd90e854fc6 100644 (file)
@@ -4,6 +4,19 @@
 
        <t:title>Login</t:title>
 
+       <t:if t:value="description">
+               <p>You must log in to <t:label t:name="description" />.</p>
+       </t:if>
+
+       <t:if t:value="capabilities">
+               <p>Your user must have the following capabilities:</p>
+               <ul>
+                       <t:each t:name="capabilities">
+                               <li><t:label t:name="value" /></li>
+                       </t:each>
+               </ul>
+       </t:if>
+
        <t:form t:action="login">
 
                <table>
diff --git a/extra/furnace/flash/flash.factor b/extra/furnace/flash/flash.factor
new file mode 100644 (file)
index 0000000..21fd20c
--- /dev/null
@@ -0,0 +1,38 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: namespaces assocs assocs.lib kernel sequences urls
+http http.server http.server.filters http.server.redirection
+furnace furnace.sessions ;
+IN: furnace.flash
+
+: flash-id-key "__f" ;
+
+TUPLE: flash-scopes < filter-responder ;
+
+C: <flash-scopes> flash-scopes
+
+SYMBOL: flash-scope
+
+: fget ( key -- value ) flash-scope get at ;
+
+M: flash-scopes call-responder*
+    flash-id-key
+    request get request-params at
+    flash-scopes sget at flash-scope set
+    call-next-method ;
+
+M: flash-scopes init-session*
+    H{ } clone flash-scopes sset
+    call-next-method ;
+
+: make-flash-scope ( seq -- id )
+    [ dup get ] H{ } map>assoc flash-scopes sget set-at-unique
+    session-changed ;
+
+: <flash-redirect> ( url seq -- response )
+    make-flash-scope
+    [ clone ] dip flash-id-key set-query-param
+    <redirect> ;
+
+: restore-flash ( seq -- )
+    [ flash-scope get key? ] filter [ [ fget ] keep set ] each ;
diff --git a/extra/furnace/flows/flows.factor b/extra/furnace/flows/flows.factor
deleted file mode 100644 (file)
index eb98c1a..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-! Copyright (C) 2008 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: accessors namespaces sequences arrays kernel
-assocs assocs.lib hashtables math.parser urls combinators
-furnace http http.server http.server.filters furnace.sessions
-html.elements html.templates.chloe.syntax ;
-IN: furnace.flows
-
-TUPLE: flows < filter-responder ;
-
-C: <flows> flows
-
-: begin-flow* ( -- id )
-    request get
-    [ url>> ] [ post-data>> ] [ method>> ] tri 3array
-    flows sget set-at-unique
-    session-changed ;
-
-: end-flow-post ( url post-data -- response )
-    request [
-        clone
-            "POST" >>method
-            swap >>post-data
-            swap >>url
-    ] change
-    request get url>> path>> split-path
-    flows get responder>> call-responder ;
-
-: end-flow* ( url id -- response )
-    flows sget at [
-        first3 {
-            { "GET" [ drop <redirect> ] }
-            { "HEAD" [ drop <redirect> ] }
-            { "POST" [ end-flow-post ] }
-        } case
-    ] [ <redirect> ] ?if ;
-
-SYMBOL: flow-id
-
-: flow-id-key "factorflowid" ;
-
-: begin-flow ( -- )
-    begin-flow* flow-id set ;
-
-: end-flow ( default -- response )
-    flow-id get end-flow* ;
-
-M: flows call-responder*
-    dup flows set
-    flow-id-key request get request-params at flow-id set
-    call-next-method ;
-
-M: flows init-session*
-    H{ } clone flows sset
-    call-next-method ;
-
-M: flows link-attr ( tag -- )
-    drop
-    "flow" optional-attr {
-        { "none" [ flow-id off ] }
-        { "begin" [ begin-flow ] }
-        { "current" [ ] }
-        { f [ ] }
-    } case ;
-
-M: flows modify-query ( query responder -- query' )
-    drop
-    flow-id get [ flow-id-key associate assoc-union ] when* ;
-
-M: flows hidden-form-field ( responder -- )
-    drop
-    flow-id get [
-        <input
-            "hidden" =type
-            flow-id-key =name
-            =value
-        input/>
-    ] when* ;
index 5cf2dad9ad76048df8a9a077b9f2c000d3f4d221..f07fe620d8e7baedca5a1b749d1757d44429f577 100644 (file)
@@ -1,6 +1,7 @@
 IN: furnace.tests
 USING: http.server.dispatchers http.server.responses
-http.server furnace tools.test kernel namespaces accessors ;
+http.server furnace tools.test kernel namespaces accessors
+io.streams.string ;
 TUPLE: funny-dispatcher < dispatcher ;
 
 : <funny-dispatcher> funny-dispatcher new-dispatcher ;
@@ -28,3 +29,7 @@ M: base-path-check-responder call-responder*
     V{ } responder-nesting set
     "a/b/c" split-path main-responder get call-responder body>>
 ] unit-test
+
+[ "<input type='hidden' name='foo' value='&amp;&amp;&amp;' />" ]
+[ [ "&&&" "foo" hidden-form-field ] with-string-writer ]
+unit-test
index 370c4f84a32b4793294265050df94b6718dd7f9c..f61ec5ff402113a2684345c895edac45fb1a5e16 100644 (file)
@@ -6,6 +6,7 @@ vocabs.loader classes
 fry urls multiline
 xml
 xml.data
+xml.entities
 xml.writer
 xml.utilities
 html.components
@@ -64,15 +65,19 @@ M: object modify-query drop ;
         { "POST" [ <permanent-redirect> ] }
     } case ;
 
-GENERIC: hidden-form-field ( responder -- )
+GENERIC: modify-form ( responder -- )
 
-M: object hidden-form-field drop ;
+M: object modify-form drop ;
 
 : request-params ( request -- assoc )
     dup method>> {
         { "GET" [ url>> query>> ] }
         { "HEAD" [ url>> query>> ] }
-        { "POST" [ post-data>> ] }
+        { "POST" [
+            post-data>>
+            dup content-type>> "application/x-www-form-urlencoded" =
+            [ content>> ] [ drop f ] if
+        ] }
     } case ;
 
 SYMBOL: exit-continuation
@@ -128,20 +133,34 @@ CHLOE: a
     [ drop </a> ]
     tri ;
 
+: hidden-form-field ( value name -- )
+    over [
+        <input
+            "hidden" =type
+            =name
+            object>string =value
+        input/>
+    ] [ 2drop ] if ;
+
+: form-nesting-key "factorformnesting" ;
+
+: form-magic ( tag -- )
+    [ modify-form ] each-responder
+    nested-values get " " join f like form-nesting-key hidden-form-field
+    "for" optional-attr [ hidden render ] when* ;
+
 : form-start-tag ( tag -- )
     [
         [
             <form
-            "POST" =method
-            [ link-attrs ]
-            [ "action" required-attr resolve-base-path =action ]
-            [ tag-attrs non-chloe-attrs-only print-attrs ]
-            tri
+                "POST" =method
+                [ link-attrs ]
+                [ "action" required-attr resolve-base-path =action ]
+                [ tag-attrs non-chloe-attrs-only print-attrs ]
+                tri
             form>
-        ] [
-            [ hidden-form-field ] each-responder
-            "for" optional-attr [ hidden render ] when*
-        ] bi
+        ]
+        [ form-magic ] bi
     ] with-scope ;
 
 CHLOE: form
@@ -167,17 +186,3 @@ CHLOE: button
         [ [ children>string 1array ] dip "button" tag-named set-tag-children ]
         [ nip ]
     } 2cleave process-chloe-tag ;
-
-: attr>word ( value -- word/f )
-    dup ":" split1 swap lookup
-    [ ] [ "No such word: " swap append throw ] ?if ;
-
-: attr>var ( value -- word/f )
-    attr>word dup symbol? [
-        "Must be a symbol: " swap append throw
-    ] unless ;
-
-: if-satisfied? ( tag -- ? )
-    "code" required-attr attr>word execute ;
-
-CHLOE: if dup if-satisfied? [ process-tag-children ] [ drop ] if ;
index 5ea389c87eec62a5708eef24d222ce6306b8cc5b..16fefe42fc95d050fe1294622857454de70b61a2 100755 (executable)
@@ -109,14 +109,14 @@ M: session-saver dispose
     [ session set ] [ save-session-after ] bi
     sessions get responder>> call-responder ;
 
-: session-id-key "factorsessid" ;
+: session-id-key "__s" ;
 
 : cookie-session-id ( request -- id/f )
     session-id-key get-cookie
     dup [ value>> string>number ] when ;
 
 : post-session-id ( request -- id/f )
-    session-id-key swap post-data>> at string>number ;
+    session-id-key swap request-params at string>number ;
 
 : request-session-id ( -- id/f )
     request get dup method>> {
@@ -137,13 +137,8 @@ M: session-saver dispose
 : put-session-cookie ( response -- response' )
     session get id>> number>string <session-cookie> put-cookie ;
 
-M: sessions hidden-form-field ( responder -- )
-    drop
-    <input
-        "hidden" =type
-        session-id-key =name
-        session get id>> number>string =value
-    input/> ;
+M: sessions modify-form ( responder -- )
+    drop session get id>> session-id-key hidden-form-field ;
 
 M: sessions call-responder* ( path responder -- response )
     sessions set
index c013007a144b114b58e45167190b2cf98ea3e363..90a00ed4ef3cd87cb56200c0d3b4ef3c05efc713 100644 (file)
@@ -29,22 +29,30 @@ SYMBOL: values
 : deposit-slots ( destination names -- )
     [ <mirror> ] dip deposit-values ;
 
-: with-each-index ( seq quot -- )
-    '[
+: with-each-index ( name quot -- )
+    [ value ] dip '[
         [
-            values [ clone ] change
+            blank-values
             1+ "index" set-value @
         ] with-scope
     ] each-index ; inline
 
-: with-each-value ( seq quot -- )
+: with-each-value ( name quot -- )
     '[ "value" set-value @ ] with-each-index ; inline
 
-: with-each-object ( seq quot -- )
+: with-each-object ( name quot -- )
     '[ from-object @ ] with-each-index ; inline
 
-: with-values ( object quot -- )
-    '[ blank-values , from-object @ ] with-scope ; inline
+SYMBOL: nested-values
+
+: with-values ( name quot -- )
+    '[
+        ,
+        [ nested-values [ swap prefix ] change ]
+        [ value blank-values from-object ]
+        bi
+        @
+    ] with-scope ; inline
 
 : nest-values ( name quot -- )
     swap [
index d4c02061b2c5ef38c11d61308d5088a9561b66dc..e50f65141ebaebbbdafbf37ec09765aa1134d785 100644 (file)
@@ -148,3 +148,23 @@ TUPLE: person first-name last-name ;
         "test9" test-template call-template
     ] run-template
 ] unit-test
+
+[ ] [ H{ { "a" H{ { "b" "c" } } } } values set ] unit-test
+
+[ "<form method='POST' action='foo'><input type='hidden' name='factorformnesting' value='a'/></form>" ] [
+    [
+        "test10" test-template call-template
+    ] run-template
+] unit-test
+
+[ ] [ blank-values ] unit-test
+
+[ ] [
+    H{ { "first-name" "RBaxter" } { "last-name" "Unknown" } } "person" set-value
+] unit-test
+
+[ "<table><tr><td>RBaxter</td><td>Unknown</td></tr></table>" ] [
+    [
+        "test11" test-template call-template
+    ] run-template [ blank? not ] filter
+] unit-test
index 9e0aa3fe1d533b55aa84c4ec3badcdf85577c36c..cb56bd71ce5e3a3aa8b5a60e5405f991d57cccea 100644 (file)
@@ -68,7 +68,7 @@ CHLOE: odd "index" value odd? [ process-tag-children ] [ drop ] if ;
 
 : (bind-tag) ( tag quot -- )
     [
-        [ "name" required-attr value ] keep
+        [ "name" required-attr ] keep
         '[ , process-tag-children ]
     ] dip call ; inline
 
@@ -85,6 +85,17 @@ CHLOE: comment drop ;
 
 CHLOE: call-next-template drop call-next-template ;
 
+: attr>word ( value -- word/f )
+    dup ":" split1 swap lookup
+    [ ] [ "No such word: " swap append throw ] ?if ;
+
+: if-satisfied? ( tag -- ? )
+    [ "code" optional-attr [ attr>word execute ] [ t ] if* ]
+    [ "value" optional-attr [ value ] [ t ] if* ]
+    bi and ;
+
+CHLOE: if dup if-satisfied? [ process-tag-children ] [ drop ] if ;
+
 CHLOE-SINGLETON: label
 CHLOE-SINGLETON: link
 CHLOE-SINGLETON: farkup
diff --git a/extra/html/templates/chloe/test/test10.xml b/extra/html/templates/chloe/test/test10.xml
new file mode 100644 (file)
index 0000000..33fe200
--- /dev/null
@@ -0,0 +1,3 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0"><t:bind t:name="a"><t:form t:action="foo"/></t:bind></t:chloe>
diff --git a/extra/html/templates/chloe/test/test11.xml b/extra/html/templates/chloe/test/test11.xml
new file mode 100644 (file)
index 0000000..f74256b
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <table>
+               <t:bind t:name="person">
+                       <tr>
+                               <td><t:label t:name="first-name"/></td>
+                               <td><t:label t:name="last-name"/></td>
+                       </tr>
+               </t:bind>
+       </table>
+
+</t:chloe>
index 471d7e276bcc03bde8e8dae04b5f2816faa2c390..c1d5b46aa450d5dad7cd37e8dfb82f57d57e78fb 100755 (executable)
@@ -1,15 +1,16 @@
 USING: http tools.test multiline tuple-syntax
 io.streams.string kernel arrays splitting sequences
-assocs io.sockets db db.sqlite continuations urls ;
+assocs io.sockets db db.sqlite continuations urls hashtables ;
 IN: http.tests
 
 : lf>crlf "\n" split "\r\n" join ;
 
 STRING: read-request-test-1
-GET http://foo/bar HTTP/1.1
+POST http://foo/bar HTTP/1.1
 Some-Header: 1
 Some-Header: 2
 Content-Length: 4
+Content-type: application/octet-stream
 
 blah
 ;
@@ -17,10 +18,10 @@ blah
 [
     TUPLE{ request
         url: TUPLE{ url protocol: "http" port: 80 path: "/bar" }
-        method: "GET"
+        method: "POST"
         version: "1.1"
-        header: H{ { "some-header" "1; 2" } { "content-length" "4" } }
-        post-data: "blah"
+        header: H{ { "some-header" "1; 2" } { "content-length" "4" } { "content-type" "application/octet-stream" } }
+        post-data: TUPLE{ post-data content: "blah" raw: "blah" content-type: "application/octet-stream" }
         cookies: V{ }
     }
 ] [
@@ -30,8 +31,9 @@ blah
 ] unit-test
 
 STRING: read-request-test-1'
-GET /bar HTTP/1.1
+POST /bar HTTP/1.1
 content-length: 4
+content-type: application/octet-stream
 some-header: 1; 2
 
 blah
@@ -87,7 +89,7 @@ blah
         code: 404
         message: "not found"
         header: H{ { "content-type" "text/html; charset=UTF8" } }
-        cookies: V{ }
+        cookies: { }
         content-type: "text/html"
         content-charset: "UTF8"
     }
@@ -172,7 +174,7 @@ test-db [
 [ ] [
     [
         <dispatcher>
-            <action> <protected>
+            <action> <protected>
             <login>
             <sessions>
             "" add-responder
@@ -219,3 +221,56 @@ test-db [
 [ "Hi" ] [ "http://localhost:1237/" http-get ] unit-test
 
 [ "Goodbye" ] [ "http://localhost:1237/quit" http-get ] unit-test
+
+USING: html.components html.elements xml xml.utilities validators
+furnace furnace.flash ;
+
+SYMBOL: a
+
+[ ] [
+    [
+        <dispatcher>
+            <action>
+                [ a get-global "a" set-value ] >>init
+                [ [ <html> "a" <field> render </html> ] "text/html" <content> ] >>display
+                [ { { "a" [ v-integer ] } } validate-params ] >>validate
+                [ "a" value a set-global URL" " <redirect> ] >>submit
+            <flash-scopes>
+            <sessions>
+            >>default
+            add-quit-action
+        test-db <db-persistence>
+        main-responder set
+
+        [ 1237 httpd ] "HTTPD test" spawn drop
+    ] with-scope
+] unit-test
+
+[ ] [ 100 sleep ] unit-test
+
+3 a set-global
+
+: test-a string>xml "input" tag-named "value" swap at ;
+
+[ "3" ] [
+    "http://localhost:1237/" http-get*
+    swap dup cookies>> "cookies" set session-id-key get-cookie
+    value>> "session-id" set test-a
+] unit-test
+
+[ "4" ] [
+    H{ { "a" "4" } { "__u" "http://localhost:1237/" } } "session-id" get session-id-key associate assoc-union
+    "http://localhost:1237/" <post-request> "cookies" get >>cookies http-request nip test-a
+] unit-test
+
+[ 4 ] [ a get-global ] unit-test
+
+! Test flash scope
+[ "xyz" ] [
+    H{ { "a" "xyz" } { "__u" "http://localhost:1237/" } } "session-id" get session-id-key associate assoc-union
+    "http://localhost:1237/" <post-request> "cookies" get >>cookies http-request nip test-a
+] unit-test
+
+[ 4 ] [ a get-global ] unit-test
+
+[ "Goodbye" ] [ "http://localhost:1237/quit" http-get ] unit-test
index e8f7189f7524b81a9835472d2176ea30d93391c7..7499796b77285501df59977d905fd3c061bb65e1 100755 (executable)
@@ -10,7 +10,7 @@ io io.server io.sockets.secure
 
 unicode.case unicode.categories qualified
 
-urls html.templates ;
+urls html.templates xml xml.data xml.writer ;
 
 EXCLUDE: fry => , ;
 
@@ -132,7 +132,6 @@ url
 version
 header
 post-data
-post-data-type
 cookies ;
 
 : set-header ( request/response value key -- request/response )
@@ -177,19 +176,27 @@ cookies ;
 : header ( request/response key -- value )
     swap header>> at ;
 
-SYMBOL: max-post-request
+TUPLE: post-data raw content content-type ;
 
-1024 256 * max-post-request set-global
+: <post-data> ( raw content-type -- post-data )
+    post-data new
+        swap >>content-type
+        swap >>raw ;
 
-: content-length ( header -- n )
-    "content-length" swap at string>number dup [
-        dup max-post-request get > [
-            "content-length > max-post-request" throw
-        ] when
-    ] when ;
+: parse-post-data ( post-data -- post-data )
+    [ ] [ raw>> ] [ content-type>> ] tri {
+        { "application/x-www-form-urlencoded" [ query>assoc ] }
+        { "text/xml" [ string>xml ] }
+        [ drop ]
+    } case >>content ;
 
 : read-post-data ( request -- request )
-    dup header>> content-length [ read >>post-data ] when* ;
+    dup method>> "POST" = [
+        [ ]
+        [ "content-length" header string>number read ]
+        [ "content-type" header ] tri
+        <post-data> parse-post-data >>post-data
+    ] when ;
 
 : extract-host ( request -- request )
     [ ] [ url>> ] [ "host" header parse-host ] tri
@@ -197,13 +204,6 @@ SYMBOL: max-post-request
     ensure-port
     drop ;
 
-: extract-post-data-type ( request -- request )
-    dup "content-type" header >>post-data-type ;
-
-: parse-post-data ( request -- request )
-    dup post-data-type>> "application/x-www-form-urlencoded" =
-    [ dup post-data>> query>assoc >>post-data ] when ;
-
 : extract-cookies ( request -- request )
     dup "cookie" header [ parse-cookies >>cookies ] when* ;
 
@@ -225,8 +225,6 @@ SYMBOL: max-post-request
     read-post-data
     detect-protocol
     extract-host
-    extract-post-data-type
-    parse-post-data
     extract-cookies ;
 
 : write-method ( request -- request )
@@ -238,12 +236,6 @@ SYMBOL: max-post-request
 : write-version ( request -- request )
     "HTTP/" write dup request-version write crlf ;
 
-: unparse-post-data ( request -- request )
-    dup post-data>> dup sequence? [ drop ] [
-        assoc>query >>post-data
-        "application/x-www-form-urlencoded" >>post-data-type
-    ] if ;
-
 : url-host ( url -- string )
     [ host>> ] [ port>> ] bi dup "http" protocol-port =
     [ drop ] [ ":" swap number>string 3append ] if ;
@@ -251,13 +243,33 @@ SYMBOL: max-post-request
 : write-request-header ( request -- request )
     dup header>> >hashtable
     over url>> host>> [ over url>> url-host "host" pick set-at ] when
-    over post-data>> [ length "content-length" pick set-at ] when*
-    over post-data-type>> [ "content-type" pick set-at ] when*
+    over post-data>> [
+        [ raw>> length "content-length" pick set-at ]
+        [ content-type>> "content-type" pick set-at ]
+        bi
+    ] when*
     over cookies>> f like [ unparse-cookies "cookie" pick set-at ] when*
     write-header ;
 
+GENERIC: >post-data ( object -- post-data )
+
+M: post-data >post-data ;
+
+M: string >post-data "application/octet-stream" <post-data> ;
+
+M: byte-array >post-data "application/octet-stream" <post-data> ;
+
+M: xml >post-data xml>string "text/xml" <post-data> ;
+
+M: assoc >post-data assoc>query "application/x-www-form-urlencoded" <post-data> ;
+
+M: f >post-data ;
+
+: unparse-post-data ( request -- request )
+    [ >post-data ] change-post-data ;
+
 : write-post-data ( request -- request )
-    dup post-data>> [ write ] when* ;
+    dup method>> "POST" = [ dup post-data>> raw>> write ] when ; 
 
 : write-request ( request -- )
     unparse-post-data
@@ -307,7 +319,7 @@ body ;
 
 : read-response-header
     read-header >>header
-    extract-cookies
+    dup "set-cookie" header parse-cookies >>cookies
     dup "content-type" header [
         parse-content-type [ >>content-type ] [ >>content-charset ] bi*
     ] when* ;
index cf8a35f141ce67d1de0f247d024837d0e23820b0..a6d894879029f49fd43d9c13098e516636e027b2 100755 (executable)
@@ -35,8 +35,10 @@ IN: http.server.cgi
         request get "accept" header "HTTP_ACCEPT" set\r
 \r
         post? [\r
-            request get post-data-type>> "CONTENT_TYPE" set\r
-            request get post-data>> length number>string "CONTENT_LENGTH" set\r
+            request get post-data>> raw>>\r
+            [ "CONTENT_TYPE" set ]\r
+            [ length number>string "CONTENT_LENGTH" set ]\r
+            bi\r
         ] when\r
     ] H{ } make-assoc ;\r
 \r
@@ -51,7 +53,7 @@ IN: http.server.cgi
     "CGI output follows" >>message\r
     swap '[\r
         , output-stream get swap <cgi-process> <process-stream> [\r
-            post? [ request get post-data>> write flush ] when\r
+            post? [ request get post-data>> raw>> write flush ] when\r
             input-stream get swap (stream-copy)\r
         ] with-stream\r
     ] >>body ;\r
diff --git a/extra/http/server/server-tests.factor b/extra/http/server/server-tests.factor
new file mode 100644 (file)
index 0000000..c29912b
--- /dev/null
@@ -0,0 +1,4 @@
+USING: http http.server math sequences continuations tools.test ;
+IN: http.server.tests
+
+[ t ] [ [ \ + first ] [ <500> ] recover response? ] unit-test
index 756a0de0ff5e30609ea69a59022eba9cd754f935..10d6070f7b09e13b8d74e7d0f07e674955e1116c 100755 (executable)
@@ -40,7 +40,7 @@ main-responder global [ <404> <trivial-responder> or ] change-at
 
 : <500> ( error -- response )
     500 "Internal server error" <trivial-response>
-    development-mode get [ swap '[ , http-error. ] >>body ] [ drop ] if ;
+    swap development-mode get [ '[ , http-error. ] >>body ] [ drop ] if ;
 
 : do-response ( response -- )
     dup write-response
index 853af6e84520bf2b9687545f8e47de0e53d28411..cd6dde255c7b8e5d821ae41a9074e02bb4a566af 100644 (file)
@@ -6,7 +6,8 @@ namespaces db db.sqlite smtp
 http.server
 http.server.dispatchers
 furnace.db
-furnace.flows
+furnace.asides
+furnace.flash
 furnace.sessions
 furnace.auth.login
 furnace.auth.providers.db
@@ -53,8 +54,7 @@ TUPLE: factor-website < dispatcher ;
         allow-edit-profile
     <boilerplate>
         { factor-website "page" } >>template
-    <flows>
-    <sessions>
+    <asides> <flash-scopes> <sessions>
     test-db <db-persistence> ;
 
 : init-factor-website ( -- )
index 9f35d83fd8d4e18f583c87723f27d0062ab3b6ff..453f7b590b08bad34435706d4cc0e621aea9fa2c 100644 (file)
@@ -28,7 +28,7 @@
 
                <pre class="description"><t:code t:name="contents" t:mode="mode"/></pre>
 
-               <t:button t:action="$pastebin/delete-annotation" t:for="aid" class="link-button link">Delete Annotation</t:button>
+               <t:button t:action="$pastebin/delete-annotation" t:for="id" class="link-button link">Delete Annotation</t:button>
 
        </t:bind-each>
 
 
                <h2>New Annotation</h2>
 
-               <t:form t:action="$pastebin/new-annotation" t:for="id">
+               <t:form t:action="$pastebin/new-annotation" t:for="parent">
 
                        <table>
                                <tr><th class="field-label">Summary: </th><td><t:field t:name="summary" /></td></tr>
                                <tr><th class="field-label">Author: </th><td><t:field t:name="author" /></td></tr>
                                <tr><th class="field-label">Mode: </th><td><t:choice t:name="mode" t:choices="modes" /></td></tr>
-                               <tr><th class="field-label big-field-label">Body:</th><td><t:textarea t:name="contents" t:rows="20" t:cols="60" /></td></tr>
+                               <tr><th class="field-label big-field-label">Body: </th><td><t:textarea t:name="contents" t:rows="20" t:cols="60" /></td></tr>
                                <tr><th class="field-label">Captcha: </th><td><t:field t:name="captcha" /></td></tr>
                                <tr>
                                <td></td>
index 5ef44ad6ce2e57916aa46625c874632b66d0a230..a27a1290dd69aed3d097a92e8694b965cfa12a16 100644 (file)
                <t:if t:code="furnace.sessions:uid">
 
                        <t:if t:code="furnace.auth.login:allow-edit-profile?">
-                               | <t:a t:href="$login/edit-profile" t:flow="begin">Edit Profile</t:a>
+                               | <t:a t:href="$login/edit-profile" t:aside="begin">Edit Profile</t:a>
                        </t:if>
 
-                       | <t:button t:action="$login/logout" t:flow="begin" class="link-button link">Logout</t:button>
+                       | <t:button t:action="$login/logout" t:aside="begin" class="link-button link">Logout</t:button>
 
                </t:if>
 
index 69650b4d73f83d45962406eaf4ed85a7b6af429b..06cdd5adf055ade545a94a5903fb4fe1d9eeff43 100644 (file)
@@ -132,7 +132,7 @@ M: annotation entity-link
 
             "id" value
             "new-annotation" [
-                "id" set-value
+                "parent" set-value
                 mode-names "modes" set-value
                 "factor" "mode" set-value
             ] nest-values
@@ -212,12 +212,12 @@ M: annotation entity-link
         ] >>display
 
         [
-            { { "id" [ v-integer ] } } validate-params
+            { { "parent" [ v-integer ] } } validate-params
             validate-entity
         ] >>validate
 
         [
-            "id" value f <annotation>
+            "parent" value f <annotation>
             [ deposit-entity-slots ]
             [ insert-tuple ]
             [ entity-link <redirect> ]
@@ -246,9 +246,13 @@ can-delete-pastes? define-capability
         <paste-action> "paste" add-responder
         <paste-feed-action> "paste.atom" add-responder
         <new-paste-action> "new-paste" add-responder
-        <delete-paste-action> { can-delete-pastes? } <protected> "delete-paste" add-responder
+        <delete-paste-action> <protected>
+            "delete pastes" >>description
+            { can-delete-pastes? } >>capabilities "delete-paste" add-responder
         <new-annotation-action> "new-annotation" add-responder
-        <delete-annotation-action> { can-delete-pastes? } <protected> "delete-annotation" add-responder
+        <delete-annotation-action> <protected>
+            "delete annotations" >>description
+            { can-delete-pastes? } >>capabilities "delete-annotation" add-responder
     <boilerplate>
         { pastebin "pastebin-common" } >>template ;
 
index e92f88c2c22b55ae93b5200cd7863f393f45a527..34ee73da677feb9b69a48a8462f46a72e32a3bcb 100644 (file)
 
                <t:if t:code="furnace.sessions:uid">
                        <t:if t:code="furnace.auth.login:allow-edit-profile?">
-                               | <t:a t:href="$login/edit-profile" t:flow="begin">Edit Profile</t:a>
+                               | <t:a t:href="$login/edit-profile" t:aside="begin">Edit Profile</t:a>
                        </t:if>
        
-                       | <t:button t:action="$login/logout" t:flow="begin" class="link-button link">Logout</t:button>
+                       | <t:button t:action="$login/logout" t:aside="begin" class="link-button link">Logout</t:button>
                </t:if>
        </div>
 
index c5fa5e25d44bcd3ca22a2e861fa35c29919aa121..3c0e2ad26782721e0c7735d8e96949db76d0882d 100755 (executable)
@@ -198,7 +198,10 @@ can-administer-planet-factor? define-capability
     planet-factor new-dispatcher
         <planet-action> "list" add-main-responder
         <feed-action> "feed.xml" add-responder
-        <planet-factor-admin> { can-administer-planet-factor? } <protected> "admin" add-responder
+        <planet-factor-admin> <protected>
+            "administer Planet Factor" >>description
+            { can-administer-planet-factor? } >>capabilities
+        "admin" add-responder
     <boilerplate>
         { planet-factor "planet-common" } >>template ;
 
index 3600e2f874b58fce996735bf7fe0d310d3a5bd29..1cecbc10948dc3b9d35425949d9815f1def1c9db 100755 (executable)
@@ -122,4 +122,5 @@ todo "TODO"
         <delete-action> "delete" add-responder
     <boilerplate>
         { todo-list "todo" } >>template
-    f <protected> ;
+    <protected>
+        "view your todo list" >>description ;
index 3dd0b9a7d13b279b1a0938f50219d8017ddb2508..e087fbfcfc2b4fd58ed85a0bfaae6c7f6e291faf 100644 (file)
@@ -9,10 +9,10 @@
                | <t:a t:href="$todo-list/new">Add Item</t:a>
 
                <t:if t:code="furnace.auth.login:allow-edit-profile?">
-                       | <t:a t:href="$login/edit-profile" t:flow="begin">Edit Profile</t:a>
+                       | <t:a t:href="$login/edit-profile" t:aside="begin">Edit Profile</t:a>
                </t:if>
 
-               | <t:button t:action="$login/logout" t:flow="begin" class="link-button link">Logout</t:button>
+               | <t:button t:action="$login/logout" t:aside="begin" class="link-button link">Logout</t:button>
        </div>
 
        <h1><t:write-title /></h1>
index b8687274f095a744f149adac11f12915714b58be..78c972fa3422f5bb00afbf0a683b48b3a12a39db 100644 (file)
@@ -18,18 +18,6 @@ IN: webapps.user-admin
 
 TUPLE: user-admin < dispatcher ;
 
-: word>string ( word -- string )
-    [ word-vocabulary ] [ drop ":" ] [ word-name ] tri 3append ;
-
-: words>strings ( seq -- seq' )
-    [ word>string ] map ;
-
-: string>word ( string -- word )
-    ":" split1 swap lookup ;
-
-: strings>words ( seq -- seq' )
-    [ string>word ] map ;
-
 : <user-list-action> ( -- action )
     <page-action>
         [ f <user> select-tuples "users" set-value ] >>init
@@ -156,7 +144,9 @@ can-administer-users? define-capability
         <delete-user-action> "delete" add-responder
     <boilerplate>
         { user-admin "user-admin" } >>template
-    { can-administer-users? } <protected> ;
+    <protected>
+        "administer users" >>description
+        { can-administer-users? } >>capabilities ;
 
 : make-admin ( username -- )
     <user>
index 93a701a6963734cb60eb26166f333a7959597bb0..9cb9ef0a0acabc87d2af8c3985993ef425f1884b 100644 (file)
@@ -7,10 +7,10 @@
                | <t:a t:href="$user-admin/new">Add User</t:a>
 
                <t:if t:code="furnace.auth.login:allow-edit-profile?">
-                       | <t:a t:href="$login/edit-profile" t:flow="begin">Edit Profile</t:a>
+                       | <t:a t:href="$login/edit-profile" t:aside="begin">Edit Profile</t:a>
                </t:if>
 
-               | <t:button t:action="$login/logout" t:flow="begin" class="link-button link">Logout</t:button>
+               | <t:button t:action="$login/logout" t:aside="begin" class="link-button link">Logout</t:button>
        </div>
 
        <h1><t:write-title /></h1>
index 95fb0de2feb89392132965d2db5234d0097036ea..5b3e9de2c4f914a292087228a0d7b114055d07cd 100644 (file)
@@ -7,7 +7,7 @@
        <ul>
                <t:bind-each t:name="changes">
                        <li>
-                               <t:a t:href="title" t:query="title"><t:label t:name="title" /></t:a>
+                               <t:a t:href="view" t:query="title"><t:label t:name="title" /></t:a>
                                on
                                <t:a t:href="revision" t:query="id"><t:label t:name="date" /></t:a>
                                by
index 67a5b91c934d3c873130d6d050abbf3cde7f815c..c3d203cd2e5399501f0e7566c3ad69a9fc95e2a8 100644 (file)
                <t:if t:code="furnace.sessions:uid">
 
                        <t:if t:code="furnace.auth.login:allow-edit-profile?">
-                               | <t:a t:href="$login/edit-profile" t:flow="begin">Edit Profile</t:a>
+                               | <t:a t:href="$login/edit-profile" t:aside="begin">Edit Profile</t:a>
                        </t:if>
 
-                       | <t:button t:action="$login/logout" t:flow="begin" class="link-button link">Logout</t:button>
+                       | <t:button t:action="$login/logout" t:aside="begin" class="link-button link">Logout</t:button>
 
                </t:if>
 
index 6dcf89e208514eb547d7f1bf10842e248eaad77f..dd2e1291f95f5248e557da3c1a76343c6f3d634f 100644 (file)
@@ -214,6 +214,10 @@ revision "REVISIONS" {
 
         { wiki "user-edits" } >>template ;
 
+SYMBOL: can-delete-wiki-articles?
+
+can-delete-wiki-articles? define-capability
+
 : <wiki> ( -- dispatcher )
     wiki new-dispatcher
         <dispatcher>
@@ -222,7 +226,9 @@ revision "REVISIONS" {
             <view-revision-action> "revision" add-responder
             <list-revisions-action> "revisions" add-responder
             <diff-action> "diff" add-responder
-            <edit-article-action> { } <protected> "edit" add-responder
+            <edit-article-action> <protected>
+                "edit wiki articles" >>description
+                "edit" add-responder
         <boilerplate>
             { wiki "page-common" } >>template
         >>default
@@ -230,6 +236,9 @@ revision "REVISIONS" {
         <user-edits-action> "user-edits" add-responder
         <list-articles-action> "articles" add-responder
         <list-changes-action> "changes" add-responder
-        <delete-action> { } <protected> "delete" add-responder
+        <delete-action> <protected>
+            "delete wiki articles" >>description
+            { can-delete-wiki-articles? } >>capabilities
+        "delete" add-responder
     <boilerplate>
         { wiki "wiki-common" } >>template ;
index 0223dfde699e9b98c1c842dc106a524208e3c085..836a85d52de6fb5716569da1a83fc9393f41e216 100644 (file)
@@ -22,6 +22,6 @@ USING: kernel hashtables xml-rpc xml calendar sequences
     put-http-response ;
 
 : test-rpc-arith
-    "add" { 1 2 } <rpc-method> send-rpc xml>string
-    "text/xml" swap "http://localhost:8080/responder/rpc/"
+    "add" { 1 2 } <rpc-method> send-rpc
+    "http://localhost:8080/responder/rpc/"
     http-post ;
index d41f66739cb0469a378d7acb2f46065848f7fcec..4b96d1331603e55128bf7e82a67cbb9023d37519 100755 (executable)
@@ -158,8 +158,7 @@ TAG: array xml>item
 
 : post-rpc ( rpc url -- rpc )
     ! This needs to do something in the event of an error
-    >r "text/xml" swap send-rpc xml>string r> http-post
-    2nip string>xml receive-rpc ;
+    >r send-rpc r> http-post nip string>xml receive-rpc ;
 
 : invoke-method ( params method url -- )
     >r swap <rpc-method> r> post-rpc ;