Water 5-System Interfaces-HTTP
class server
Contract
Parameter keyDefault valueType
rootreq
port80integer
server_base_urinulltype.<one_of request_or_response.uri string/>
listentrueboolean
multi_threadfalseboolean
debugfalseboolean
root_folderfalseboolean
host_name"localhost"string
extensionnull
hostopt
relative_urifalseboolean
default_serverfalseboolean
headeropt
return_typeopt
machinenull
envnull
session_id_cookie_name"my_session_id"string
session_cookie_name"my_session"string
sessionsopt
session_typetrueboolean
a_requestopttype.<one_of request_or_response.uri string/>
a_responsenull
requested_objectnull
subjectopt
argsnull
Water Contract
<class server
  root          =req
  port          =80
  server_base_uri=null=<type.one_of request_or_response.uri string/>
  listen        =true
  multi_thread  =false
  debug         =false
  root_folder   =false
  host_name     ="localhost"
  extension     =null
  host          =opt
  relative_uri  =false
  default_server=false
  _default_server=<server root=wob port=8081 listen=true multi_thread=false host_name="localhost" host="localhost:8081" default_server=true sessions=<thing 374058681=<wob _name="my" cookie=<thing my_session_id=873225448/> _last_used=<datetime year=2007 month=10 day=13 hour=19 minute=18 second=36 millisecond=448/> _created_on=<datetime year=2007 month=10 day=13 hour=19 minute=18 second=36 millisecond=444/> id=374058681/> 457689001=<wob _name="my" cookie=<thing my_session_id=873225448/> _last_used=<datetime year=2007 month=10 day=13 hour=19 minute=19 second=28 millisecond=50/> _created_on=<datetime year=2007 month=10 day=13 hour=19 minute=19 second=28 millisecond=46/> id=457689001/> 552925765=<wob _name="my" cookie=<thing my_session_id=873225448/> _last_used=<datetime year=2007 month=10 day=13 hour=19 minute=18 second=21 millisecond=465/> _created_on=<datetime year=2007 month=10 day=13 hour=19 minute=18 second=21 millisecond=461/> id=552925765/> 777539830=<wob _name="my" cookie=<thing my_session_id=873225448/> _last_used=<datetime year=2007 month=10 day=13 hour=19 minute=18 second=43 millisecond=763/> _created_on=<datetime year=2007 month=10 day=13 hour=19 minute=18 second=43 millisecond=759/> id=777539830/> 774370541=<wob _name="my" cookie=<thing my_session_id=873225448/> _last_used=<datetime year=2007 month=10 day=13 hour=19 minute=10 second=7 millisecond=17/> _created_on=<datetime year=2007 month=10 day=13 hour=19 minute=10 second=7 millisecond=12/> id=774370541/> 509312100=<wob _name="my" cookie=<thing my_session_id=873225448/> _last_used=<datetime year=2007 month=10 day=13 hour=19 minute=18 second=27 millisecond=122/> _created_on=<datetime year=2007 month=10 day=13 hour=19 minute=18 second=27 millisecond=119/> id=509312100/> 535645858=<wob _name="my" cookie=<thing my_session_id=873225448/> _last_used=<datetime year=2007 month=10 day=13 hour=19 minute=18 second=37 millisecond=730/> _created_on=<datetime year=2007 month=10 day=13 hour=19 minute=18 second=37 millisecond=725/> id=535645858/> 705696771=<wob _name="my" cookie=<thing my_session_id=873225448/> _last_used=<datetime year=2007 month=10 day=13 hour=19 minute=18 second=42 millisecond=65/> _created_on=<datetime year=2007 month=10 day=13 hour=19 minute=18 second=42 millisecond=61/> id=705696771/> 313031867=<wob _name="my" cookie=<thing my_session_id=873225448/> _last_used=<datetime year=2007 month=10 day=13 hour=19 minute=18 second=42 millisecond=834/> _created_on=<datetime year=2007 month=10 day=13 hour=19 minute=18 second=42 millisecond=829/> id=313031867/> 741656256=<wob _name="my" cookie=<thing my_session_id=873225448/> _last_used=<datetime year=2007 month=10 day=13 hour=19 minute=15 second=14 millisecond=319/> _created_on=<datetime year=2007 month=10 day=13 hour=19 minute=15 second=14 millisecond=315/> id=741656256/> 214992087=<wob _name="my" cookie=<thing my_session_id=873225448/> _last_used=<datetime year=2007 month=10 day=13 hour=19 minute=18 second=39 millisecond=613/> _created_on=<datetime year=2007 month=10 day=13 hour=19 minute=18 second=39 millisecond=609/> id=214992087/> 503552892=<wob _name="my" cookie=<thing/> _last_used=<datetime year=2007 month=10 day=13 hour=19 minute=44 second=32 millisecond=283/> _created_on=<datetime year=2007 month=10 day=13 hour=19 minute=44 second=32 millisecond=280/> id=503552892/>/> limit_access=ide.only_local_requests thread=<ja.org.waterlang.Server/> _name="localhost:8081"/>
  header        =opt
  return_type   =opt
  machine       =null
  env           =null
  session_id_cookie_name="my_session_id"
  session_cookie_name="my_session"
  sessions      =opt
  session_type  =true
  a_request     =opt=<type.one_of request_or_response.uri string/>
  a_response    =null
  requested_object=null
  subject       =opt
  args          =null
  _part_name_key="host"
/>
A call to server creates an http server on the given port (default 80) that serves out the object given as the first argument, the 'root_object'.
<server root=<H1>Hello World</H1> port=8080/>
Once a server is running you can call it from water like so:
<resource "http://localhost:8080"/>.content
"<h1>Hello World</h1>"
Use an extension to get back a formatted value:
<resource "http://localhost:8080/.htm"/>.content
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">&#13;
<h1>Hello World</h1>'
Or call it from a web browser like so:
<open_browser_window "http://localhost:8080"/>
"http://localhost:8080"
Server can serve out static objects as well:
<server <thing temp=76 humidity=51/> port=8080/>
<resource "http://localhost:8080/temp.xml"/>.content
76
<resource "http://localhost:8080/humidity"/>.<execute/>
51
A more useful thing to do is to serve a method like so:
<server plus port=8080/>
<resource "http://localhost:8080/?0=4&1=5"/>.<execute/>
9
Call/invoke from browser:
<open_browser_window "http://localhost:8080/?0=4&1=5"/>
The question mark in the url indicates that we are calling a method. We are passing 4 as the value of the 0 parameter and we are passing 5 as the value of the 1 parameter. Since plus takes _vector_fields args, we can pass as many as we like:
<resource "http://localhost:8080/?0=4&1=5&2=6"/>.<execute/>
15
We can also make our web service look like a local method like so:
wob.<set remote_plus=<resource "http://localhost:8080"/>/>
<remote_plus 0=3 1=4/>
7
<remote_plus 3 4/>7
<server <thing add=plus multiply=times/> port=8080/>
<resource "http://localhost:8080/add?0=4&1=5"/>.<execute/>
9
Its time to build an interactive web page and a server that can read user input. First we define a class that's going to have one method for each of the two pages we are going to serve. Each method returns a hypertext object. The server will call to_html on this object and deliver the resulting string to the browser.
<class my_first_app>  <!-- define the app -->
    <method htm_class>
      <FORM action="/simple_action.htm">
        Type in some text:<INPUT name="a_value"/>
        <INPUT type="submit" value="Do It"/>
      </FORM>
    </method>
  
    <method simple_action a_value=req>
      <H1> You entered: <do a_value/> </H1>
    </method>
  </class>
my_first_app.<simple_action a_value="hi ben"/>

You entered: hi ben

Launch the server:
<server my_first_app port=9090/>
<open_browser_window "http://localhost:9090"/>
When we call the server with no path in the url as we have done above, the server looks for a htm_large method in the server root which will call htm_class when showing the class. So the page we see in the browser contains one text input field and one submit button named "Do it". The user then types in some text and clicks on the button. Notice the value of the action attribute to the FORM object in the htm_class method. That is the method that the server will call in response to the user clicking on the submit button. In this case its called simple_action Note that in the form action, it must be preceded by a slash. The arguments passed to the method will be from the controls, i.e. input tags in the content of the FORM call. The mapping between the method parameters and the controls in the FORM is: For each parameter in the method, look for a corresponding control of that name. If it finds one, use the value of that control as the value to pass in to the the method. Above you'll see the input attribute of name="a_value" and note that the simple_action method has a corresponding parameter a_value The browser passes only strings from the web page to the server, but the Water server converts strings into data so that strings that look like numbers or booleans are converted into numbers or booleans before being passed to the method. If the method has a required argument that is not supplied by the browser, error. If the method has an optional argument that is not supplied by the browser, its value is simply the default value of the parameter like normal method calls. If the form has a control with no name, nothing will be sent to the server The Water server can pass values from all HTML controls to Water methods including checkboxes, radio buttons, password fields, text areas and select tags. Checkboxes are particularly tricky because browsers do not pass back anything for a checkbox that is unchecked. To deal with such situations, when you are defining a method that will take the value of a checkbox, give it a default value of false and/or declare it to be of type boolean The server will then makes sure it gets passed true or false Here is an example with many different control types:
<class lotsa_controls>
 <method htm_class>
  <form action="/register_user">
   Your first name: <input type="text" name="first_name" value="Joe"/> <BR/>
   Enter your password: <input type="password" name="a_password"/> <BR/>
   <input type="checkbox" name="likes_ice_cream" checked=false/> 
       Do you like ice cream? <BR/>
   <input type="radio" name="flavor" checked=false value="ya"/> chocolate <BR/>
   <input type="radio" name="flavor" checked=true value="nah"/> vanilla   <BR/>
   Sport of choice? <select name="sport" size=1> <br/>
                       <option>baseball</>
                       <option>basketball</>
                       <option>knitting</>
                    </select> <br/>  
   Who do you admire?<TEXTAREA name="admire" cols=40 rows=3>Jimmy Page</TEXTAREA>  <BR/>
   <INPUT type="hidden" name="user_id" value="user_143"/> 
   <INPUT type="submit" name="registration" value="Register Me"/> 
   <INPUT type="submit" name="registration" value="Do Not Register Me"/>
 </form>
</method>

<method register_user first_name=req a_password=req 
     flavor=req sport=req admire=req user_id=req registration=req
     likes_ice_cream=false=boolean 
>  
  <vector first_name " " a_password " " likes_ice_cream " " flavor
          " " sport " " admire " " user_id " " registration/>
  </>
 </class>
<server lotsa_controls/>
<open_browser_window "http://localhost"/>
The browser will show a page with: If the user clicks the "Register Me" button without changing any of the controls, the second page will have on it: Joe false nah baseball Jimmy Page user_143 Register Me Clicking the checkbox, choosing basketball, replacing Jimmy Page with Jeff Beck and clicking on the Do Not Register Me button will show: Joe true nah basketball Jeff Beck user_143 Do Not Register Me Remember that each method that generates a hypertext object for a server must return that object. In most cases this means that the object must be made by the LAST expression in the body of the method.

Conversion of arguments

The Water server uses the types of fields for automatically converting string argument values into other objects. If you do not want the conversion to occur, set the type of a field to string If a field has a default value but no type, the conversion will be based on the type of the default value. For example, if the default value is true , then the field type is considered boolean and a string value of "off" will be converted to false . The conversion process calls from on the type and the first argument is the submitted string value. The converted value is returned and passed to the method. If the field type is thing , a value that starts and ends with angle-brackets will be converted into an object. At no time will any methods or constructors be called during the conversion due to security issues.

Serving Files

The Water server can also serve out files simila to the way a standard server does. Here's how to make a server that can only server out one file. (Not something you usually want to do, but instructive none the less.)
Example: serve one file only
<server <file "logical://user/images/wrightplane.jpg"/> port=8080/>
<open_browser_window "http://localhost:8080"/>
"http://localhost:8080"
The one file should be shown in the browser. Next a more usual case of serving a folder by having the folder be the server root object.
Example: serve a folder
<server <folder "logical://user"/> port=8080/>
<open_browser_window "http://localhost:8080/images/wrightplane.jpg"/>
"http://localhost:8080/images/wrightplane.jpg"
Again the requested file, ad1.jpg should show as an image in the file. We can also have a file be the value of a field inside an object that we are serving like so: test case a file inside an object like so
Example: Serve a file inside an object
thing.<set my_file=<file "logical://user/images/wrightplane.jpg"/>/>
<server wob port=8080/>
<open_browser_window "http://localhost:8080/thing/my_file.jpg"/>
"http://localhost:8080/thing/my_file"
Above we are serving out wob, the root object. We have set wonb.thing.my_file to a Water file object. Our url form the browser, http://localhost:8080/thing/my_file references that file and it should be shown in the browser. Instead of just a file being served out, a folder can be part of a path of an object being servered out. In this case, the path elements after the folder must all be subfolders, except that the last one must be a file. So below wob.thing.my_fold executes to a folder, the water user folder, and we go down into the images subfolder and find the file ad1.jpg, which should be shown in the browser.
Example: serve a nested folder
thing.<set my_fold=<folder "logical://user"/>/>
<server wob port=8080/>
<open_browser_window "http://localhost:8080/thing/my_fold/images/wrightplane.jpg"/>
"http://localhost:8080/thing/my_fold/images/wrightplane.jpg"
You can decide how to divide up the subfolders between the object in the Water object tree in the "my_fold" field and the url passed to the browser. Below we make the url passed to the browser shorter by including "images" in my_fold .
Example: serve a nested folder
thing.<set my_fold=<folder "logical://user/images"/>/>
<server wob port=8080/>
<open_browser_window "http://localhost:8080/thing/my_fold/wrightplane.jpg"/>
"http://localhost:8080/thing/my_fold/images/wrightplane.jpg"

Methods Returning Files

If a method that the server calls reurns a file, that file is served out.
Example: method returns file that is serverd.
<method get_image>
 <file "logical://user/images/wrightplane.jpg"/>
</> 
<server wob port=8080/>
<open_browser_window "http://localhost:8080/get_image?"/>
"http://localhost:8080/get_image?"
We can parameterize our method so that it serves out a different file depending on its argument. Here the method dictates the folder, but the argument to it tells us which file in the folder is to be served.
Example: parametize method that servers a file
<method get_image filename=req=string>
 <file <join "logical://user/images/" filename/> />
</>
 <server wob port=8080/>
 <open_browser_window "http://localhost:8080/get_image?filename=wrightplane.jpg"/>
"http://localhost:8080/get_image?filename=ad2.jpg"
Below we wrap some HTML around the image and use an IMG tag to tell the server to get the image. The src of the IMG tag references the get_image method which produces our image. Note that our get_image method is very simple but it can contain any Water code to dynamically compute what image is to be served.
Example: use img src with url to method to get the file.
<method get_image filename=req=string>
 <file <join "logical://user/images/" filename/> />
</>
<method test_image>
<DIV>
 Here's an image:
 <IMG src="/get_image?filename=wrightplane.jpg"/>
</DIV>
</method>

<server wob port=8080/>
<open_browser_window "http://localhost:8080/test_image.htm?"/>
"http://localhost:8080/test_image.htm?"