Permalink
Browse files

added log_wrap_size, configurable wrap size for all logs, fixed a bug…

… introduced by jb for ssi, major doics overhaul again, redid yaws docs using CSS only,

git-svn-id: https://erlyaws.svn.sourceforge.net/svnroot/erlyaws/trunk/yaws@785 9fbdc01b-0d2c-0410-bfb7-fb27d70d8b52
  • Loading branch information...
1 parent 1f9e495 commit bea8261794c7410614024e3467abeb9203d6a613 @klacke committed Nov 19, 2004
View
1 include/yaws.hrl
@@ -55,6 +55,7 @@
max_num_cached_bytes = 1000000, %% 1 MEG
max_size_cached_file = 8000,
large_file_chunk_size = 10240,
+ log_wrap_size = 1000000, % wrap logs after 1M
cache_refresh_secs = 30, % seconds (auto zero when debug)
include_dir = [],
phpexe = "php",
View
5 man/yaws.conf.5
@@ -95,6 +95,11 @@ a command line flag to yaws.
\fB auth_log = true | false\fR
Enable or disable the auth log. Default is true.
+.TP
+\B log_wrap_size = Integer\fR
+The logs written by yaws are all wrap logs, the default value at the
+size where they wrap around and the original gets renamed to File.old
+is 1000000, 1 M. This value can changed.
.TP
\fB copy_error_log = true | false\fR
View
5 scripts/yaws.conf.template
@@ -49,6 +49,11 @@ trace = false
copy_error_log = true
+# Logs are wrap logs
+
+log_wrap_size = 1000000
+
+
# If yaws is started as root, it can, once it has opened
# all relevant sockets for listening, change the uid to a
# user with lower accessrights than root
View
3 src/yaws_api.erl
@@ -1227,7 +1227,8 @@ ehtml_expand(Ch) when Ch >= 0, Ch =< 255 -> yaws_api:htmlize_char(Ch);
ehtml_expand(Bin) when binary(Bin) -> yaws_api:htmlize(Bin);
ehtml_expand({ssi,File, Del, Bs}) ->
- case yaws_server:ssi(File, Del, Bs) of
+ UT = get(yaws_ut),
+ case yaws_server:ssi(File, Del, Bs, UT#urltype.dir) of
{error, Rsn} ->
io_lib:format("ERROR: ~p~n",[Rsn]);
X ->
View
44 src/yaws_config.erl
@@ -256,6 +256,15 @@ fload(FD, globals, GC, C, Cs, Lno, Chars) ->
fload(FD, globals, GC#gconf{runmods = [Mod|GC#gconf.runmods]},
C, Cs, Lno+1, Next);
+ ["log_wrap_size", '=', Int] ->
+ case (catch list_to_integer(Int)) of
+ I when integer(I) ->
+ fload(FD, globals, GC#gconf{log_wrap_size = I},
+ C, Cs, Lno+1, Next);
+ _ ->
+ {error, ?F("Expect integer at line ~w", [Lno])}
+ end;
+
["include_dir", '=', Incdir] ->
Dir = filename:absname(Incdir),
case is_dir(Dir) of
@@ -838,3 +847,38 @@ ssl_start() ->
Err ->
error_logger:format("Failed to start ssl: ~p~n", [Err])
end.
+
+
+
+%% search for an SC within Pairs that have the same, listen,port,ssl,severname
+%% Return {Pid, SC} or false
+%% Pairs is the pairs in yaws_server #state{}
+search_sconf(NewSC, Pairs) ->
+ case lists:zf(
+ fun({Pid, [SC|ScList]}) ->
+ case eq_prop(NewSC, SC) of
+ true ->
+ case lists:key_search(NewSC#sconf.servername,
+ #sconf.servername, ScList) of
+ {value, Found} ->
+ {true, {Pid, Found}};
+ false ->
+ false
+ end;
+ false ->
+ false
+ end
+ end, Pairs) of
+ [] ->
+ false;
+ [{Pid, Found}] ->
+ {Pid, Found}
+ end.
+
+
+eq_prop(S, NewSc) ->
+ (S#sconf.listen == NewSc#sconf.listen)
+ and
+ (S#sconf.port == NewSc#sconf.port) and
+ (S#sconf.ssl == NewSc#sconf.ssl).
+
View
24 src/yaws_log.erl
@@ -25,12 +25,16 @@
-include_lib("yaws/include/yaws_api.hrl").
-include("yaws_debug.hrl").
+%% 1 meg log we wrap
+-define(WRAP_LOG_SIZE, 1000000).
+
-record(state, {
running,
dir,
now,
tracefd,
+ log_wrap_size = ?WRAP_LOG_SIZE,
tty_trace = false,
copy_errlog,
auth_log,
@@ -167,6 +171,7 @@ handle_call({setdir, GC, Sconfs}, _From, State)
S2 = State#state{running = true,
dir = Dir,
now = fmtnow(),
+ log_wrap_size = GC#gconf.log_wrap_size,
copy_errlog = Copy,
auth_log = AuthLog,
alogs = L},
@@ -335,8 +340,6 @@ tty_trace(Str, State) ->
%% {stop, Reason, State} (terminate/2 is called)
%%----------------------------------------------------------------------
--define(WRAP_LOG_SIZE, 400000).
-
handle_info(secs3, State) ->
{noreply, State#state{now = fmtnow()}};
@@ -345,44 +348,45 @@ handle_info(secs3, State) ->
handle_info(minute10, State) ->
L = lists:map(
fun(AL) ->
- wrap(AL)
+ wrap(AL, State)
end, State#state.alogs),
Dir = State#state.dir,
E = filename:join([Dir, "report.log"]),
case file:read_file_info(E) of
- {ok, FI} when FI#file_info.size > ?WRAP_LOG_SIZE,
+ {ok, FI} when FI#file_info.size > State#state.log_wrap_size,
State#state.copy_errlog == true ->
gen_event:call(error_logger, yaws_log_file_h, wrap);
_ ->
ok
end,
{noreply, State#state{alogs= L,
- auth_log = wrap(State#state.auth_log)}}.
+ auth_log = wrap(State#state.auth_log, State)}}.
-wrap_p(AL) when record(AL, alog) ->
+wrap_p(AL, State) when record(AL, alog) ->
{ok, FI} = file:read_file_info(AL#alog.filename),
if
- FI#file_info.size > ?WRAP_LOG_SIZE ->
+ FI#file_info.size > State#state.log_wrap_size->
true;
true ->
false
end;
-wrap_p(_) ->
+wrap_p(_,_) ->
false.
-wrap(AL) ->
- case (catch wrap_p(AL)) of
+wrap(AL, State) ->
+ case (catch wrap_p(AL, State)) of
true ->
file:close(AL#alog.fd),
Old = [AL#alog.filename, ".old"],
file:delete(Old),
file:rename(AL#alog.filename, Old),
{ok, Fd2} = file:open(AL#alog.filename, [write, raw]),
+ error_logger:info_msg("Wrap log ~p",[AL#alog.filename]),
AL#alog{fd = Fd2};
false ->
AL;
View
12 src/yaws_server.erl
@@ -236,8 +236,6 @@ handle_call(getconf, _From, State) ->
-
-
%%----------------------------------------------------------------------
%% Func: handle_cast/2
%% Returns: {noreply, State} |
@@ -614,7 +612,6 @@ acceptor0(GS, Top) ->
acceptor0(GS, Top)
end;
{error, timeout} ->
- ?Debug("SSL timeout~n", []),
Top ! {self(), done_client, 0},
receive
{Top, stop} ->
@@ -1802,13 +1799,16 @@ handle_out_reply({yssi, Yfile}, _LineNo, YawsFile, UT, [ARG]) ->
handle_out_reply({html, Html}, _LineNo, _YawsFile, _UT, _A) ->
accumulate_content(Html);
-handle_out_reply({ehtml, E}, _LineNo, _YawsFile, _UT, A) ->
- case safe_ehtml_expand(E) of
+handle_out_reply({ehtml, E}, _LineNo, _YawsFile, UT, A) ->
+ put(yaws_ut, UT),
+ Res = case safe_ehtml_expand(E) of
{ok, Val} ->
accumulate_content(Val);
{error, ErrStr} ->
handle_crash(A,ErrStr)
- end;
+ end,
+ erase(yaws_ut),
+ Res;
handle_out_reply({content, MimeType, Cont}, _LineNo,_YawsFile, _UT, _A) ->
yaws:outh_set_content_type(MimeType),
View
2 vsn.mk
@@ -1,2 +1,2 @@
-YAWS_VSN=1.49
+YAWS_VSN=1.50
View
40 www/EXHEAD
@@ -1,40 +0,0 @@
-<IMG SRC="/icons/yaws_head.gif" WIDTH="600" ALT="YAWS">
-<br><br>
-
-<table bgcolor="#B6b6a5" border="2" cellpadding="5" cellspacing="0" width="100%">
-<tr border="2">
- <td> <A HREF="/index.yaws">Top Page</a> </td>
- <td> <A HREF="/simple.yaws">Simple</a></td>
- <td> <A HREF="/dynamic.yaws">Dynamic content</a></td>
- <td> <A HREF="/query.yaws">Query part of url</a> </td>
- <td> <A HREF="/form.yaws">Forms</a> </td>
- <td> <A HREF="/redirect.yaws">Redirect</a> </td>
- <td> <A HREF="/arg.yaws">Arg</a> </td>
-
-
-</tr>
-<tr border="2">
- <td> <A HREF="/ssi.yaws">Server side include</a> </td>
- <td> <A HREF="/bindings.yaws">Bindings</a> </td>
-
- <td> <A HREF="/upload0.yaws">File upload</a> </td>
- <td> <A HREF="/cookies.yaws">Cookies</a> </td>
- <td> <A HREF="/pcookie.yaws">Persistent Cookies</a> </td>
- <td> <A HREF="/session.yaws">Cookie sessions</a> </td>
- <td> <A HREF="/appmods.yaws">Appmods</a> </td>
-
-
-
-</tr>
-
-<tr border="2">
- <td> <A HREF="/stream.yaws">Streaming data</a> </td>
- <td> <A HREF="/shopingcart/index.yaws">Tiny shopping cart</a> </td>
- <td> <A HREF="/embed.yaws">Embedding Yaws</a> </td>
-</tr>
-
-
-</table>
-<hr>
-
-
View
22 www/TOPTAB
@@ -1,22 +0,0 @@
-<IMG SRC="icons/yaws_head.gif" WIDTH="600" ALT="YAWS">
-<br><br>
-
-<table bgcolor="#B6b6a5" border="2" cellpadding="5" cellspacing="0" width="100%">
-
-<tr border="2">
- <td> <A HREF="index.yaws">Top Page</a> </td>
- <td> <A HREF="configuration.yaws">Build Config & Run</a></td>
- <td> <A HREF="dynamic.yaws">Dynamic content</a> </td>
- <td> <A HREF="examples.yaws">Examples</a> </td>
-</tr>
-
-<tr border="1">
- <td> <A HREF="contribs.yaws">Contribs/Apps</a> </td>
- <td> <A HREF="download">Download </a> </td>
- <td> <A HREF="contact.yaws">Contact </a> </td>
- <td> <A HREF="doc.yaws">Documentation</a> </td>
-
-</tr>
-
-</table>
-<hr>
View
2 www/api.yaws
@@ -17,7 +17,7 @@ regular erlang system.
Here we describe the functions available in the yaws_api module
-<a href="man.yaws?page=yaws_api"> man page for <tt>yaws_api (5)</tt> </a>
+<a href="yman.yaws?page=yaws_api"> man page for <tt>yaws_api (5)</tt> </a>
<erl>
View
12 www/appmods.yaws
@@ -17,9 +17,10 @@ ssi(File) ->
out(A) ->
- [{ssi, "HEAD", [],[]},
- {ssi, "EXHEAD", [],[]},
+ [{ssi, "TAB.inc", [],[]},
{ehtml,
+ {'div', [{id, "entry"}],
+
[{h1, [], "Appmods (Application modules)"},
{p, [],
@@ -69,15 +70,16 @@ A#arg.querydata = \"a=b\""),
"Appmods would typically be used by webapplications that want to provide the illusion of proper paths to the browser. "}
- ]}].
+ ]
+ }},
+ {ssi, "END2",[],[]}
+ ].
</erl>
-</html>
-
View
76 www/arg.yaws
@@ -1,45 +1,99 @@
-<html>
+
+<erl>
+
+out(A) ->
+ {ssi, "TAB.inc", [],[]}.
+
+</erl>
+
+<div id="entry">
<h2> The Arg </h2>
-<p>This page displays the Arg #argument structure
+<p>This page displays the Arg #arg structure
supplied to the out/1 function.
-<p> The code is in file <a href="code.yaws?file=/arg.yaws">arg.yaws</a>
+
+<p> The #arg structure is a very important datastructure for the
+yaws programmer. It is the main mechanism whereby the server can pass
+data to the web application. There are several data items
+which is of interest to the webapplication, such as which headers
+were sent from the client, etc.
+The #arg recored is defined in <tt>yaws_api.hrl</tt> and is defined as:
+
+<div class="box">
+<pre>
+
+
+-record(arg, {
+ clisock, %% the socket leading to the peer client
+ headers, %% headers
+ req, %% request
+ clidata, %% The client data (as a binary in POST requests)
+ server_path, %% The normalized server path
+ querydata, %% Was the URL on the form of ...?query (GET reqs)
+ appmoddata, %% the remainder of the path leading up to the query
+ docroot, %% where's the data
+ fullpath, %% full deep path to yaws file
+ cont, %% Continuation for chunked multipart uploads
+ state, %% State for use by users of the out/1 callback
+ pid, %% pid of the yaws worker process
+ opaque, %% useful to pass static data
+ appmod_prepath, %% path in front of: <appmod><appmoddata>
+ pathinfo %% Set to 'd/e' when calling c.yaws for the request
+ %% http://some.host/a/b/c.yaws/d/e
+ }).
+</pre>
+</div>
+
+<p> As we have seen is several previous examples, the <tt> out/1</tt> function
+defined in .yaws files, gets inviked with a single argument which is
+a #arg{} record, fitting the specific HTTP request being served.
+
+
+<p> The code to display the #arg{} record
+is in defined in file <a href="code.yaws?file=/arg.yaws">arg.yaws</a>
+
<erl>
out(A) ->
Req = A#arg.req,
H = yaws_api:reformat_header(A#arg.headers),
{ehtml,
- [{h4,[], "The headers passed to us were:"},
+ [{h5,[], "The headers passed to us were:"},
{hr},
{ol, [],lists:map(fun(S) -> {li,[], {p,[],S}} end,H)},
- {h4, [], "The request"},
+ {h5, [], "The request"},
{ul,[],
[{li,[], f("method: ~s", [Req#http_request.method])},
{li,[], f("path: ~p", [Req#http_request.path])},
{li,[], f("version: ~p", [Req#http_request.version])}]},
{hr},
- {h4, [], "Other items"},
+ {h5, [], "Other items"},
{ul,[],
[{li, [], f("clisock from: ~p", [inet:peername(A#arg.clisock)])},
{li,[], f("docroot: ~s", [A#arg.docroot])},
{li,[], f("fullpath: ~s", [A#arg.fullpath])}]},
{hr},
- {h4, [], "Parsed query data"},
+ {h5, [], "Parsed query data"},
{pre,[], f("~p", [yaws_api:parse_query(A)])},
{hr},
- {h4,[], "Parsed POST data "},
+ {h5,[], "Parsed POST data "},
{pre,[], f("~p", [yaws_api:parse_post(A)])}]}.
</erl>
-</html>
-
-
+
+
+</div>
+
+
+<erl>
+out(A) -> {ssi, "END2",[],[]}.
+</erl>
+
View
12 www/bindings.yaws
@@ -1,10 +1,10 @@
<erl>
out(A) ->
- [{ssi, "HEAD", [],[]},
- {ssi, "EXHEAD", [],[]}].
+ {ssi, "TAB.inc", [],[]}.
</erl>
+<div id="entry">
<h2> Bindings </h2>
<p>
Bindings are the opposite of <a href="ssi.yaws"> Server Side Includes (SSI)</a>.
@@ -92,7 +92,8 @@ foo = foo (hit me)
</div>
-And is rendered as:
+<p> And is rendered as:
+
<div class="box">
<p>foo</p>
<p><font size="4">foo != baz</font></p>
@@ -107,9 +108,12 @@ foo = foo (hit me)
+</div>
-</html>
+<erl>
+out(A) -> {ssi, "END2",[],[]}.
+</erl>
View
27 www/code.yaws
@@ -2,27 +2,38 @@
<erl>
out(A) ->
- Head = yaws_api:ssi(A#arg.docroot, ["/HEAD", "/EXHEAD"]),
{Code, F} = case queryvar(A, "file") of
{ok, Fname} ->
+ io:format(" ~p ~p~n", [Fname, undot(Fname)]),
case file:read_file(A#arg.docroot ++ undot(Fname)) of
{ok, B} ->
- {yaws_api:pre_ssi_string(binary_to_list(B),"box"), Fname};
+ C = {'div',
+ [],
+ {pre, [], B}},
+ {C, Fname};
_ ->
{[], "Can't read " ++ Fname }
end;
undefined ->
{[], "Bad request"}
end,
- Trail = yaws_api:ssi(A#arg.docroot, ["/END"]),
- [Head, {ehtml, {h2, [], F}}, Code, Trail].
+ {ehtml, {html, [],
+ {'div',
+ [],
+ [{h2, [], F},
+ Code]}}}.
-
-undot([$., $. |T]) ->
- undot(T);
+%% remove sick characters
+undot(".." ++ T) ->
+ undot([$.|T]);
undot([H|T]) ->
- [H|undot(T)];
+ case lists:member(H, " &;'!\\?<>\"()$") of
+ true ->
+ undot(T);
+ false ->
+ [H|undot(T)]
+ end;
undot([]) ->
[].
View
34 www/configuration.yaws
@@ -7,20 +7,20 @@ box(Str) ->
out(A) ->
- [{ssi, "HEAD", [],[]},
- {ssi, "TOPTAB", [],[]},
+ [{ssi, "TAB.inc", [],[]},
{ehtml,
- [{h2,[],"Build and install"},
- {p,[], ["Yaws is hosted by the excellent source code site SourceForge ",
- {a ,[{href,"http://sourceforge.net"}],
- {img, [{src,"http://sourceforge.net/sflogo.php?group_id=45637&type=1"},
- {width,"88"},
- {height,"31"},
- {border,"0"},
- {alt,"SourceForge.net Logo"}]}},
- " The Yaws SourceForge www page is ",
- {a ,[{href,"http://sourceforge.net/projects/erlyaws/"}],
- "http://sourceforge.net/projects/erlyaws"}
+ [{'div', [{id, "entry"}],
+ [{h1,[],"Build and install"},
+ {p,[], ["Yaws is hosted by the excellent source code site SourceForge ",
+ {a ,[{href,"http://sourceforge.net"}],
+ {img, [{src,"http://sourceforge.net/sflogo.php?group_id=45637&type=1"},
+ {width,"88"},
+ {height,"31"},
+ {border,"0"},
+ {alt,"SourceForge.net Logo"}]}},
+ " The Yaws SourceForge www page is ",
+ {a ,[{href,"http://sourceforge.net/projects/erlyaws/"}],
+ "http://sourceforge.net/projects/erlyaws"}
]},
{p,[], ["To cvs check out the latest source first install an ",
{a, [{href,"http://www.erlang.org"}],"Erlang"},
@@ -64,7 +64,7 @@ out(A) ->
{p,[], ["The yaws executable is a shell script which invokes the "
"erlang system and instructs it to start yaws. "
" The command line flags for yaws are documented in ",
- {a,[{href, "man.yaws?page=yaws"}],
+ {a,[{href, "yman.yaws?page=yaws"}],
["man page for ",
{tt, [], "yaws (1)"}]}]},
@@ -88,7 +88,7 @@ out(A) ->
"on whether we run yaws as a standalone daemon or if we run yaws as an "
" embedded application inside another Erlang program. "]},
{p,[],["The yaws configuration is described in ",
- {a, [{href,"man.yaws?page=yaws.conf"}],
+ {a, [{href,"yman.yaws?page=yaws.conf"}],
["man page for ",
{tt,[], "yaws.conf (5)"}]}]},
@@ -105,8 +105,8 @@ out(A) ->
{tt, [], "{embedded, true}"},
" The embedded mode is fully described at ",
{a, [{url, "embed.yaws"}], "embed.yaws"}]}
- ]},
- {ssi, "END",[],[]}
+ ]}]},
+ {ssi, "END2",[],[]}
].
</erl>
View
9 www/contact.yaws
@@ -2,11 +2,11 @@
<erl>
out(A) ->
- yaws_api:ssi(A#arg.docroot, ["/HEAD", "/TOPTAB"]).
+ {ssi, "TAB.inc",[],[]}.
</erl>
-
+<div id="entry">
<H2>Contact</H2>
@@ -23,6 +23,9 @@ Cell: +46 0702097763
</pre>
+
+</div>
+
<erl>
-out(A) -> yaws_api:ssi(A#arg.docroot, ["/END"]).
+out(A) -> {ssi, "END2",[],[]}.
</erl>
View
10 www/contribs.yaws
@@ -1,13 +1,12 @@
<erl>
-
out(A) ->
- yaws_api:ssi(A#arg.docroot, ["/HEAD", "/TOPTAB"]).
-
+ {ssi, "TAB.inc", [],[]}.
</erl>
+<div id="entry">
-<H2>Contributions and Applications</H2>
+<h1>Contributions and Applications</h1>
<p>This is a list of (some of) the currently known
Yaws applications.
@@ -52,9 +51,10 @@ easy to configure and run.
+</div>
<erl>
-out(A) -> yaws_api:ssi(A#arg.docroot, ["/END"]).
+out(A) -> {ssi, "END2",[],[]}.
</erl>
View
19 www/cookies.yaws
@@ -1,7 +1,10 @@
<erl>
-out(A) -> yaws_api:ssi(A#arg.docroot, ["/HEAD", "/EXHEAD"]).
+out(A) ->
+ {ssi, "TAB.inc", [],[]}.
</erl>
+<div id="entry">
+
<h1>Yaws and Cookies</h1>
@@ -37,11 +40,21 @@ A correct definition of cookies can be found at Netscapes
<p>The code to set the cookie looks like:
<erl>
-out(A) -> yaws_api:pre_ssi_files(A#arg.docroot, ["setcookie.yaws"]).
+out(A) ->
+ {ok, B} = file:read_file(A#arg.docroot ++ "/setcookie.yaws"),
+ {ehtml,
+ {'div', [{class, "box"}],
+ {pre,[], B}}}.
+
</erl>
-</html>
+</div>
+
+
+<erl>
+out(A) -> {ssi, "END2",[],[]}.
+</erl>
View
20 www/doc.yaws
@@ -2,16 +2,22 @@
<erl>
out(A) ->
- yaws_api:ssi(A#arg.docroot, ["/HEAD", "/TOPTAB"]).
-
+ {ssi, "TAB.inc",[],[]}.
</erl>
-<H2>Documentation</h2>
+<div id="entry">
+
+<h2>Documentation</h2>
<h3> User manual </h3>
+<p> The version of the usermanual is currently getting a bit old.
+There are several features of yaws which are yet not properly described
+in the user manual, they are all described in the Example collection or
+man pages though.
+
<ul>
<li> <a href="yaws.pdf"> yaws.pdf</a>
<li> <a href="yaws.ps"> yaws.ps</a>
@@ -22,21 +28,21 @@ out(A) ->
<ul>
<li>
-<a href="man.yaws?page=yaws_api"> man page for yaws_api (5) </a>
+<a href="yman.yaws?page=yaws_api"> man page for yaws_api (5) </a>
<li>
-<a href="man.yaws?page=yaws.conf"> man page for Yaws config file </a>
+<a href="yman.yaws?page=yaws.conf"> man page for Yaws config file </a>
<li>
-<a href="man.yaws?page=yaws"> man page for yaws</a>
+<a href="yman.yaws?page=yaws"> man page for yaws</a>
</ul>
<erl>
-out(A) -> yaws_api:ssi(A#arg.docroot, ["/END"]).
+ out(_) -> {ssi, "END2", [],[]}.
</erl>
View
198 www/dynamic.yaws
@@ -16,19 +16,20 @@ ssi(File) ->
{ssi, File,[],[]}}}.
out(A) ->
- [{ssi, "HEAD", [],[]},
- {ssi, "TOPTAB", [],[]},
- {ehtml,
- [{h1, [],"Generating Dynamic Content"},
- {p,[], ["Yaws has very nice support for generating dynamic content on the fly. "
- "We use embedded erlang code to generate the content. The Erlang code "
- "is separated from the HTML code by ",
- {pre, [], "<erl>"},
- " and ",
- {pre, [], "</erl>"},
- "markers. For example: "]},
-
- box("
+ [{ssi, "TAB.inc", [],[]},
+ {ehtml,
+ [{'div', [{id, "entry"}],
+ [
+ {h1, [],"Generating Dynamic Content"},
+ {p,[], ["Yaws has very nice support for generating dynamic content on the fly. "
+ "We use embedded erlang code to generate the content. The Erlang code "
+ "is separated from the HTML code by ",
+ {tt, [], "<erl>"},
+ " and ",
+ {tt, [], "</erl>"},
+ " markers. For example: "]},
+
+ box("
<html>
<h1>Foobar</h1>
\<erl>
@@ -42,46 +43,46 @@ out(A) ->
</html>
"),
- {p,[], ["Is a very small example where we have a HTML document with embedded "
- "erlang code. A file which contains embedded erlang code must have the file "
- "suffix ",
- {tt, [], ".yaws"}]},
- {br},
-
- {p, [], "The embedded erlang code can return the different values which will "
- " trigger the yaws webserver to do different things. We list some of the simple "
- " return values here: "},
-
- {ul, [],
- [{li,[],
- [{p, [],
- [{tt,[],"{html, DeepCharOrBinaryList}"},
- " Which will make the value of ",
- {tt, [],"DeepCharOrBinaryList"},
- " be substituted into the HTML document."]}]},
- {li,[],
- {p,[],
- [{tt,[],"{ehtml, ErlangTermStructure}"}]}}]},
-
- {p, [],
- ["It is often more convenient to return "
- "erlang terms which are then transformed to HTML instead "
- "of returning plain HTML in string form using the ",
- {tt,[], "html"}, " tag "]},
-
-
- {p,[],
- ["Using the ehtml return value, we can return deep structured "
- " erlang terms that correspond directly to HTML code. For example: "]},
-
- box("
-{table, [{bgcolor, tan}],
+ {p,[], ["Is a very small example where we have a HTML document with embedded "
+ "erlang code. A file which contains embedded erlang code must have the file "
+ "suffix ",
+ {tt, [], ".yaws"}]},
+ {br},
+
+ {p, [], "The embedded erlang code can return the different values which will "
+ " trigger the yaws webserver to do different things. We list some of the simple "
+ " return values here: "},
+
+ {ul, [],
+ [{li,[],
+ [{p, [],
+ [{tt,[],"{html, DeepCharOrBinaryList}"},
+ " Which will make the value of ",
+ {tt, [],"DeepCharOrBinaryList"},
+ " be substituted into the HTML document."]}]},
+ {li,[],
+ {p,[],
+ [{tt,[],"{ehtml, ErlangTermStructure}"}]}}]},
+
+ {p, [],
+ ["It is often more convenient to return "
+ "erlang terms which are then transformed to HTML instead "
+ "of returning plain HTML in string form using the ",
+ {tt,[], "html"}, " tag "]},
+
+
+ {p,[],
+ ["Using the ehtml return value, we can return deep structured "
+ " erlang terms that correspond directly to HTML code. For example: "]},
+
+ box("
+{table, [{bgcolor, \"tan\"}],
{tr, []
[{td, [{width, \"70%\"}], {p, [{class=\"foo\"}], \"Hi there\"}}]}}
"),
- {p, [], "Corresponds to the following HTML code: "},
- box("
+ {p, [], "Corresponds to the following HTML code: "},
+ box("
<table bgcolor=\"tan\">
<tr>
<td width=\"70%\">
@@ -91,49 +92,49 @@ out(A) ->
</table>
"),
- {ul, [],
- [{li,[],
- {p,[],
- [{tt,[], "{header, Header}"},
- " If a " ,
- {tt, [], "header"},
- " structure is returned, an additional header is inserted among the HTTP headers generated by yaws. "
- "This is used to insert for example Set-Cookie headers. The ",
- {tt,[], "Header"}, " variable must not be newline terminated."]}},
-
- {li,[],
- {p,[],
- [{tt,[], "{allheaders, Header}"},
- " If an ",
- {tt, [], "allheaders"},
- " structure is returned, all previous headers that have been generated, including those "
- "default hedaers generated by yaws itself are erased, and replaced by "
- "the headers in ",
+ {ul, [],
+ [{li,[],
+ {p,[],
+ [{tt,[], "{header, Header}"},
+ " If a " ,
+ {tt, [], "header"},
+ " structure is returned, an additional header is inserted among the HTTP headers generated by yaws. "
+ "This is used to insert for example Set-Cookie headers. The ",
+ {tt,[], "Header"}, " variable must not be newline terminated."]}},
+
+ {li,[],
+ {p,[],
+ [{tt,[], "{allheaders, Header}"},
+ " If an ",
+ {tt, [], "allheaders"},
+ " structure is returned, all previous headers that have been generated, including those "
+ "default hedaers generated by yaws itself are erased, and replaced by "
+ "the headers in ",
{tt, [], "Headers"},
- ". The variable ",
+ ". The variable ",
{tt,[], "Headers"},
- " must be a list of ",
- {tt, [], "{header, Str}"},
- " tuples. The ",
- {tt, [], "Str"},
- " must not be newline terminated. "]}},
-
-
- {li,[],
- {p,[],
- [{tt, [], "{status, StatusCodeInt} "},
- "Is used to force yaws to return a different status code than the "
+ " must be a list of ",
+ {tt, [], "{header, Str}"},
+ " tuples. The ",
+ {tt, [], "Str"},
+ " must not be newline terminated. "]}},
+
+
+ {li,[],
+ {p,[],
+ [{tt, [], "{status, StatusCodeInt} "},
+ "Is used to force yaws to return a different status code than the "
" default 200 code."]}},
-
-
-
- {li,[],
+
+
+
+ {li,[],
{p,[],
[{tt, [], "ok"}, " Do nothing."]}},
-
-
- {li,[],
- {p,[],
+
+
+ {li,[],
+ {p,[],
[{tt, [], "{content, MimeType, Content} "},
"Sets the mime type, that is "
"the Content-Type: header to be ", {tt, [], "MimeType"},
@@ -147,17 +148,17 @@ out(A) ->
{p,[],
[{tt, [], "{redirect, URL} "}," a redirect is issued to the location in ",
{tt, [], " URL "}]}},
-
- {li,[],
+
+ {li,[],
{p,[],
[{tt, [], "{redirect_local, Path} "}," a redirect is issued to the local "
"server using the same method (http or https) as the incoming request "
" and the path part of the location header to the value in ", {tt, [], " Path "},"."]}},
-
+
{li,[],
{p,[],
- [{tt, [], "{'EXIT', normal}"}," which will make terminate the "
+ [{tt, [], "{'EXIT', normal}"}," which will terminate the "
" client connection in an uncontrolled way. "]}},
{li,[],
@@ -185,7 +186,7 @@ out(A) ->
"at the same time."},
{p,[],["All possible return values from the out/1 function are documented in "
"the man page for ",
- {a, [{href, "man.yaws?page=yaws_api"}],
+ {a, [{href, "yman.yaws?page=yaws_api"}],
["",
{tt, [], "yaws_api (5)"}]}]},
@@ -214,8 +215,17 @@ out(A) ->
ssi("ssi/dynamic.2"),
{p,[], "And some of the refered records are defined as:"},
- ssi("ssi/dynamic.3")]},
- {ssi, "END",[],[]}].
+ ssi("ssi/dynamic.3")]}]},
+ {ssi, "END",[],[]}].
</erl>
+
+
+</div>
+
+
+<erl>
+out(A) -> {ssi, "END2",[],[]}.
+</erl>
+
View
11 www/embed.yaws
@@ -1,8 +1,12 @@
<erl>
-out(A) -> yaws_api:ssi(A#arg.docroot, ["/HEAD", "/EXHEAD"]).
+out(A) ->
+ {ssi, "TAB.inc", [],[]}.
</erl>
+<div id="entry">
+
+
<h1>Running yaws embedded in another larger application</h1>
<p>
Yaws is ideal to embed inside another larger erlang application.
@@ -186,6 +190,9 @@ down to each .yaws web page.
+</div>
+
+
<erl>
-out(A) -> yaws_api:ssi(A#arg.docroot, ["/END"]).
+out(A) -> {ssi, "END2",[],[]}.
</erl>
View
21 www/form.yaws
@@ -1,12 +1,13 @@
+<erl>
-<html>
-<head>
-<title>This is a practice form.</title>
-</head>
+out(A) ->
+ {ssi, "TAB.inc", [],[]}.
+
+</erl>
-<body>
+<div id="entry">
<h2>POST example </h2>
<p>This is a simple example where we get to fill in
@@ -45,6 +46,12 @@ POSTed data.
<p><input TYPE=submit> <input TYPE=reset>
</form>
-</body>
-</html>
+
+</div>
+
+
+
+<erl>
+out(A) -> {ssi, "END2",[],[]}.
+</erl>
View
80 www/index.yaws
@@ -2,47 +2,47 @@
out(A) ->
- [{ssi, "HEAD",[],[]},
- {ssi, "TOPTAB", [],[]},
+ [{ssi, "TAB.inc",[],[]},
{ehtml,
- [{h2,[],"Yaws"},
- {p,[],"Yaws is a HTTP high perfomance 1.1 webserver."
- "Two separate modes of operations are supported."},
- {ul,[],
- [{li,[],
- {p,[],"Standalone mode where Yaws runs as a regular webserver "
- "daemon. This is the default mode."}},
- {li,[],
- {p,[], "Embedded mode where Yaws runs as an embedded webserver in "
- "another erlang application."}}
- ]},
- {p,[], ["Yaws is entirely written in ",
- {a, [{href, "http://www.erlang.org"}], "Erlang"},
- " furthermore it is a multithreaded webserver where one "
- "Erlang light weight process is used to handle each client."]},
- {p,[], "The main advantages of yaws compared to other Web technologies"
- " are performance and elegance. The performance comes from the "
- " underlying Erlang system and its ability to handle concurrent "
- " processes in an efficent way. Its elegance comes from Erlang as "
- "well. Web applications dont have to be written in ugly adhoc "
- "languages."},
-
- {h2,[], "yaws.hyber.org"},
-
- {p,[], ["The www page for Yaws is ",
- {a ,[{href,"http://yaws.hyber.org"}], "yaws.hyber.org"},
- " The documentation, examples as well as releases can be "
- "found there, and of course, ",
- {a ,[{href,"http://yaws.hyber.org"}],"yaws.hyber.org"},
- " is itself powered by Yaws."]},
-
- {p,[], ["A mailing list exists at: ",
- {a,[{href,"https://lists.sourceforge.net/lists/listinfo/""erlyaws-list"}],
- "https://lists.sourceforge.net/lists/listinfo/erlyaws-list"}]},
- {hr},
- gen_news(A),
- {ssi, "END",[],[]}
- ]}].
+ [{'div', [{id, "entry"}],
+ [{h1,[],"Yaws"},
+ {p,[],"Yaws is a HTTP high perfomance 1.1 webserver."
+ "Two separate modes of operations are supported."},
+ {ul,[],
+ [{li,[],
+ {p,[],"Standalone mode where Yaws runs as a regular webserver "
+ "daemon. This is the default mode."}},
+ {li,[],
+ {p,[], "Embedded mode where Yaws runs as an embedded webserver in "
+ "another erlang application."}}
+ ]},
+ {p,[], ["Yaws is entirely written in ",
+ {a, [{href, "http://www.erlang.org"}], "Erlang"},
+ " furthermore it is a multithreaded webserver where one "
+ "Erlang light weight process is used to handle each client."]},
+ {p,[], "The main advantages of yaws compared to other Web technologies"
+ " are performance and elegance. The performance comes from the "
+ " underlying Erlang system and its ability to handle concurrent "
+ " processes in an efficent way. Its elegance comes from Erlang as "
+ "well. Web applications dont have to be written in ugly adhoc "
+ "languages."},
+
+ {h2,[], "yaws.hyber.org"},
+
+ {p,[], ["The www page for Yaws is ",
+ {a ,[{href,"http://yaws.hyber.org"}], "yaws.hyber.org"},
+ " The documentation, examples as well as releases can be "
+ "found there, and of course, ",
+ {a ,[{href,"http://yaws.hyber.org"}],"yaws.hyber.org"},
+ " is itself powered by Yaws."]},
+
+ {p,[], ["A mailing list exists at: ",
+ {a,[{href,"https://lists.sourceforge.net/lists/listinfo/""erlyaws-list"}],
+ "https://lists.sourceforge.net/lists/listinfo/erlyaws-list"}]},
+ {h2, [], "News"},
+ gen_news(A)]}]},
+ {ssi, "END2",[],[]}].
+
gen_news(A) ->
View
13 www/man.yaws
@@ -2,8 +2,6 @@
<erl>
out(A) ->
- H = yaws_api:ssi(A#arg.docroot, ["/HEAD", "/TOPTAB"]),
-
L = case queryvar(A,"page") of
{ok, Page} ->
%% only allow regular chars in Page
@@ -26,11 +24,14 @@ out(A) ->
false ->
"illegal character detected in query arg"
end;
- false ->
+ undefined ->
"no man page found in query arg "
end,
- Man = yaws_api:pre_ssi_string(L,"man"),
- Trail = yaws_api:ssi(A#arg.docroot, ["/END"]),
- [H, Man, Trail].
+ {ehtml,
+ {html,[],
+ {'div',[{class,"man"}],
+ {pre,[], L}}}}.
+
+
</erl>
View
8 www/pcookie.yaws
@@ -1,8 +1,9 @@
<erl>
-out(A) -> yaws_api:ssi(A#arg.docroot, ["/HEAD", "/EXHEAD"]).
+out(A) -> {ssi, "TAB.inc", [],[]}.
</erl>
+<div id="entry">
<h1>Persistent Cookies</h1>
<p>
@@ -38,7 +39,10 @@ out(A) -> yaws_api:pre_ssi_files(A#arg.docroot, ["readpcookie.yaws"]).
</erl>
+</div>
-</html>
+<erl>
+out(A) -> {ssi, "END2",[],[]}.
+</erl>
View
9 www/post.yaws
@@ -14,12 +14,11 @@ fpostvar(A, Key) ->
out(A) ->
- [{ssi, "HEAD", [],[]},
- {ssi, "EXHEAD", [],[]},
+ [{ssi, "TAB.inc", [],[]},
{ehtml,
- [{h2, [],"post.yaws"},
+ {'div',[{id, "entry"}], [{h2, [],"post.yaws"},
{p,[],[ "This is the ", {tt, [], "post.yaws"}, " file ",
- "This yaws file gets invoked with client data. "
+ "This yaws file gets invoked with POSTed client data. "
"This is the data that is submitted from the forms page ",
{a, [{href, "form.yaws"}], " form.yaws "}]},
@@ -59,7 +58,7 @@ out(A) ->
undefined -> "None";
{ok, Val} -> Val
end]}}
- ]},
+ ]}},
{ssi, "END",[],[]}].
View
75 www/query.yaws
@@ -1,10 +1,12 @@
<erl>
out(A) ->
- yaws_api:ssi(A#arg.docroot, ["/HEAD", "/EXHEAD"]).
+ {ssi, "TAB.inc", [],[]}.
+
</erl>
+<div id="entry">
<h2>The query part of the url</h2>
@@ -21,46 +23,49 @@ In the above example, we have key=page and its value "cat".
The code in the page man.yaws, will read these key/value pairs
in the A#arg.querydata and display the man page.
+Assuming a predifined CSS class called box, defined as:
+
+<div class="box"
+<pre>
+div.box { border: solid; border-width: thin; width: 90%;
+ background: rgb(211, 211, 211) }
+</pre>
+</div>
+
+<p>
The following code:
+
<erl>
+
out(A) ->
-L="
- out(A) ->
- P = yaws_api:parse_query_data(A),
- L = case lists:keysearch(page, 1, P) of
- {value, {page, Page}} ->
- os:cmd(\"man \" ++ Page ++ \" | col -b\");
- false ->
- \"no man page found in query arg \"
- end,
- yaws_api:pre_ssi_string(L, \"man\").
-",
-yaws_api:pre_ssi_string(L).
+ {ehtml,ssi("man.yaws")}.
+
+ssi(File) ->
+ {'div',[{class,"box"}],
+ {pre,[], {ssi, File, [],[]}}}.
+
</erl>
+
<p> will display a man page if invoked with a proper key/value
pair in the query part of the URL.
-<p> This fairly awkward way of getting at the query (or POST)
-data in the Arg structure was only illustrated for the sake of
-explaining the Arg structure and its fields. It is much easier
-to access query data through the <tt>queryvar(ARG,Key)</tt> function.
-The above example again:
-
-
-<erl>
-out(A) ->
-L="
- out(A) ->
- {ok,Page} = queryvar(A,\"page\"),
- L = os:cmd(\"man \" ++ Page ++ \" | col -b\"),
- yaws_api:pre_ssi_string(L, \"man\").
-",
-yaws_api:pre_ssi_string(L).
+<p> This fairly convenient way of getting at the query (or POST)
+is equivalent of the code:
+<div class="box">
+<pre>
+P = yaws_api:parse_query_data(A),
+L = case lists:keysearch(page, 1, P) of
+ {value, {page, Page}} ->
+ .....
+</pre>
+</div>
-</erl>
+<p>The querypart of the URL is part as field in the Arg structure.
+The function <tt>parse_query/1</tt> parses the raw data into
+a key/value list.
<p>The <tt>queryvar(ARG,Key)</tt> function returns the value of the
@@ -69,4 +74,12 @@ or if the variable is unset, the <tt>queryvar(ARG,Key)</tt> function returns <tt
-</html>
+</div>
+
+
+<erl>
+out(A) -> {ssi, "END2",[],[]}.
+</erl>
+
+
+
View
5 www/readpcookie.yaws
@@ -38,7 +38,10 @@ The code is:
<erl>
out(A) ->
- yaws_api:pre_ssi_files(A#arg.docroot, ["readpcookie.yaws"]).
+ {ok, B} = file:read_file(A#arg.docroot ++ "/readpcookie.yaws"),
+ {ehtml,
+ {'div', [{class, "box"}],
+ {pre,[], B}}}.
</erl>
View
103 www/redirect.yaws
@@ -1,40 +1,101 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<HTML>
-<HEAD>
- <meta name="keywords" content="post">
+<erl>
-<TITLE>Redirect example</TITLE>
-
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+out(A) ->
+ {ssi, "TAB.inc",[],[]}.
-</HEAD>
-<BODY BGCOLOR="#C6C6B5" text="#333333">
+</erl>
+<div id="entry">
-<HTML>
+<h2>Redirects</H2>
-<H1> redirect.yaws </H1>
+<p> Redirs are a powerful tool in the webapp programmer toolbox. The
+Webserver returns a specific status code (302) and adds a "Location:" header
+to the responce headers to the Browser. The Browser then displays the new
+page as indicated in the "Location" header.
-<p> This a redirection example, the following <a href="redirect2.yaws">redirection url</a> contains the following code in its first erl group.
+<p> Yaws supports a number of different forms of redirect return values
+from the out/1 function.
+The code:
<erl>
+out(_A) ->
+ {ehtml,
+ {'div', [{class,"box"}],
+ {pre,[],
+ {ssi, "redirect2.yaws",[],[]}}}}.
+</erl>
+
+<p> Clickable <a href="redirect2.yaws"> On this link </a> executes the
+above redirect code.
-out(_) -> yaws_api:pre_ssi_string(
-"
- out(_) ->
- yaws_api:redirect(
- \"http://www.google.com/search?num=20&hl=en&lr=lang_en%7Clang_sv&q=yaws\").
-").
+<p> The code above redirects to an external URL. The HTTP RFC mandates
+that the Loaction header must contain complete URLs, including the
+the method, http, https etc. A very common case of redirection, is
+a to redirect to another file on the same server. The code
+in <a href="redirect3.yaws"> redirect3.yaws </a> shows an example of
+a yaws redirect relative to the "current" server.
+<erl>
+out(_A) ->
+ {ehtml,
+ {'div', [{class,"box"}],
+ {pre,[],
+ {ssi, "redirect3.yaws",[],[]}}}}.
</erl>
-<p>The redirection code in the yaws_api module returns a new status code
-as well as a Location header.
+<p> The code in <a href="redirect3.yaws"> redirect3.yaws </a> will
+do a relative redirect to the code in
+<a href="redirect2.yaws"> redirect2.yaws </a> which in its turn redirects, once again, to google. Double redirects.
+
+<p>While working with redirects, the tool <a href="http://curl.haxx.se/">
+curl </a> is an excellent way to troubleshoot the behaviour of your redirects.
+For example:
+
+<div class="box">
+<pre>
+# curl -I http://rubin.hyber.org:8000/redirect3.yaws
+HTTP/1.1 302 Found
+Server: Yaws/1.49 Yet Another Web Server
+Location: http://rubin.hyber.org:8000/redirect2.yaws
+Date: Tue, 16 Nov 2004 20:16:01 GMT
+Content-Type: text/html
+
+<pre>
+</div>
+
+<p>Where <tt> http://rubin.hyber.org:8000</tt> is where I am currently
+testing the <a href="redirect3.yaws"> redirect3.yaws </a> code.
+Learn and use the <a href="http://curl.haxx.se/"> curl </a>
+web client, it may not render pictures pretty, but it sure displays
+headers.
+<br>
-</HTML>
+<p> We show one additional version of redirect code. The code in
+<a href="redirect3.yaws"> redirect3.yaws </a> requires an absolute path.
+If we want to supply a path relative to the current url, we can use
+either the Redirect modifier <tt>rel_path</tt> or <tt>any_path</tt>
+as in :
+<erl>
+out(_A) ->
+ {ehtml,
+ {'div', [{class,"box"}],
+ {pre,[],
+ {ssi, "redirect4.yaws",[],[]}}}}.
+</erl>
+
+<p> <a href = "redirect4.yaws"> Clickable here </a>
+
+
+</div>
+
+
+<erl>
+out(A) -> {ssi, "END2",[],[]}.
+</erl>
View
8 www/redirect2.yaws
@@ -1,6 +1,8 @@
<erl>
-out(_) ->
- yaws_api:redirect(
- "http://www.google.com/search?num=20&hl=en&lr=lang_en%7Clang_sv&q=yaws").
+%% redirect2.yaws
+
+out(_Arg) ->
+ L="http://www.google.com/search?num=20&hl=en&lr=lang_en%7Clang_sv&q=yaws",
+ {redirect, L}.
</erl>
View
7 www/redirect3.yaws
@@ -0,0 +1,7 @@
+
+<erl>
+%% redirect 3 yaws
+
+out(_Arg) ->
+ {redirect_local, "/redirect2.yaws"}.
+</erl>
View
13 www/session.yaws
@@ -1,7 +1,9 @@
<erl>
-out(A) -> yaws_api:ssi(A#arg.docroot, ["/HEAD", "/EXHEAD"]).
+out(A) ->
+ {ssi, "TAB.inc", [],[]}.
</erl>
+<div id="entry">
<h1>The session server</h1>
@@ -14,11 +16,12 @@ The code in <a href="code.yaws?file=/session1.yaws">session1.yaws</a>
shows a minimalistic way to handle sessions.
To run it click <a href="session1.yaws">here</a>
+The actual session API is documented in the man page for yaws_api.
+</div>
-
-</html>
-
-
+<erl>
+out(A) -> {ssi, "END2",[],[]}.
+</erl>
View
15 www/setpcookie.yaws
@@ -63,10 +63,12 @@ out(A) ->
<erl>
-out(A) -> yaws_api:ssi(A#arg.docroot, ["/HEAD", "/EXHEAD"]).
+out(A) -> {ssi, "TAB.inc", [],[]}.
+</erl>
+
+<div id="entry">
-</erl>
@@ -77,7 +79,12 @@ the browser.
<a href="readpcookie.yaws">readpcookie.yaws</a> will
read the cookie and report persistent information.
-</html>
+
+</div>
+
+
+<erl>
+out(A) -> {ssi, "END2",[],[]}.
+</erl>
-
View
39 www/simple.yaws
@@ -1,11 +1,10 @@
<erl>
out(A) ->
- yaws_api:ssi(A#arg.docroot, ["/HEAD", "/EXHEAD"]).
-
+ {ssi, "TAB.inc", [],[]}.
</erl>
-
+<div id="entry">
<h2>Hello world</h2>
<p>
@@ -16,13 +15,13 @@ any embedded erlang code at all.
<p>
The file <a href="simple_ex1.yaws">simple_ex1.yaws</a> contains the following
HTML code.
-<br>
+
<erl>
out(A) -> yaws_api:pre_ssi_files(A#arg.docroot, ["/simple_ex1.yaws"]).
</erl>
-<br>
+
<p>
Since the file has the suffix <tt>.yaws</tt>, the file will be processed
by the Yaws dynamic compiler, but since no embeddded erlang code is found,
@@ -48,15 +47,29 @@ The file has one very simple function which just returns a tuple
The String will be substituted into the delivered HTML data instead of the
Erlang code.
+
+<h2> And yet again </h2>
+The file <a href="simple_ex2.yaws">simple_ex2.yaws</a> returns
+html embedded as a string. A tighter coupling to Erlang is
+provided by a construct known as "ehtml".
+As in <a href="simple_ex3.yaws">simple_ex3.yaws as ehtml</a>
+
+<erl>
+out(A) -> yaws_api:pre_ssi_files(A#arg.docroot, ["/simple_ex3.yaws"]).
+</erl>
+
+
+
+
<h2>Print the #arg record</h2>
<p> When writing yaws code, all classic erlang libraries are available,
however, the module <tt>yaws_api</tt> which is included in the load path
for yaws modules contains an number of usefule functions, here is a small
-example in <a href="simple_ex3.yaws">simple_ex3.yaws</a>
+example in <a href="simple_ex4.yaws">simple_ex4.yaws</a>
<erl>
-out(A) -> yaws_api:pre_ssi_files(A#arg.docroot, ["/simple_ex3.yaws"]).
+out(A) -> yaws_api:pre_ssi_files(A#arg.docroot, ["/simple_ex4.yaws"]).
</erl>
<p>The above code illustrates two points:
@@ -72,9 +85,17 @@ module. It's just a shortcut convenience to <tt>io_lib:format/2</tt>. The
<li>
<p>
The second point is a printout of the #arg record which is passed
-to the <tt>out/1</tt> function.
+to the <tt>out/1</tt> function. If you take the time to work with yaws,
+the Arg passed to the out/1 functions will become very familiar.
+It is the main mechanism which is used to pass data from the webserver to
+the application.
</ul>
+</div>
+
+
-</html>
+<erl>
+out(A) -> {ssi, "END2",[],[]}.
+</erl>
View
4 www/simple_ex3.yaws
@@ -1,10 +1,10 @@
<html>
-<h1> simple ex 3</h1>
+<h1> Yesssssss </h1>
<erl>
-out(Arg) -> {html, f("Printing the arg structure :~n<pre>~p~n</pre>~n", [Arg])}.
+out(Arg) -> {ehtml, [{h2, [{class, "foo"}], "Hello yet again"}]}.
</erl>
View
12 www/simple_ex4.yaws
@@ -0,0 +1,12 @@
+<html>
+
+
+<h1> simple ex 3</h1>
+
+<erl>
+out(Arg) -> {html, f("Printing the arg structure :"
+ "~n<pre>~p~n</pre>~n", [Arg])}.
+</erl>
+
+
+</html>
View
11 www/ssi.yaws
@@ -17,12 +17,13 @@ ssi(File) ->
out(A) ->
- [{ssi, "HEAD", [],[]},
- {ssi, "EXHEAD", [],[]},
+ [{ssi, "TAB.inc", [],[]},
{ehtml,
- [{h1, [], "Server side includes (with variable expansion)"},
+ {'div', [{id, "entry"}],
+ [
+ {h1, [], "Server side includes (with variable expansion)"},
- {p, [],
+ {p, [],
"This feature is useful when we are writing applications where "
"basically the entire page is dynamically generated but we also "
"want to include snippets of either html or, even more typically,"
@@ -94,7 +95,7 @@ out(A) ->
" out/1 function(s) "}
]
-
+ }
}
].
View
77 www/stil.css
@@ -1,52 +1,55 @@
<style TYPE="text/css">
- body {
- background: rgb(250,240,230);
- font-family: Verdana, Arial, Helvetica, sans-serif;
- color: black;
- }
-#menu {
- background: #B6B6A5;
-}
- div.links {
- background: green;
- }
+html {margin: 0; padding: 0;}
- div.box { border: solid; border-width: thin; width: 90%;
- margin : 4;
- background: rgb(211, 211, 211) }
+body {font: 12px Verdana, Arial, Helvetica, sans-serif;
+ margin: 0; padding: 0;
+ background: rgb(95%,95%,95%); color: black;}
+h1 {font-size: 200%; text-transform: lowercase; letter-spacing: 3px;
+ margin: 0.66em 0 0.33em 3%; padding: 0;}
+h3 {font-size: 133%; margin: 0; padding: 0;
+ border-bottom: 1px solid black;}
- div.man { border: solid; border-width: thin; width: 100%;
- font-size: 70%
- margin : 4;
- background: rgb(240, 230, 140) }
+h4 {font-size: 100%; margin: 0; padding: 0.33em 0 0;
+ border-bottom: 1px solid rgb(50%,50%,35%);
+ color: rgb(50%,50%,35%);}
+h5 {font-size: 100%; margin: 0; padding: 0.33em 0 0;
+ color: rgb(50%,50%,35%);}
- H1, H2, H4, H5 {
- text-decoration: none;
- font-family: Verdana, Arial, Helvetica, sans-serif;
- font-weight: bold;
- font-variant: small-caps
- }
- I { font-size : 9pt;
- font-family: Times, Verdana, Arial, Helvetica, sans-serif;}
- P { text-decoration: none;
- font-family: Verdana, Arial, Helvetica, sans-serif;
- font-weight: normal;
- }
+p {line-height: 1.66; margin: 0.5em 0 1em 3em;}
+
+div#entry {margin: 0 33% 1em 7%; padding: 0;}
+
+div#sidebar {position: absolute; top: 4em; right: 0; width: 20%; font-size: 11px;}
+
+div#sidebar a {display: block; padding: 8px 0 2px 10px; margin: 0;
+ border-left: 1px solid rgb(50%,50%,35%);}
- A { text-decoration: none;
- font-family: Verdana, Arial, Helvetica, sans-serif;
- font-weight: normal;
+div#sidebar a:hover {background: rgb(85%,85%,70%);}
+
+div.links {
+ background: green;
}
- A:visited { font-style: oblique; color: #600000;}
- A:link { color: #0000f0 } /* unvisited link */
- A:active { color: lime } /* active links */
- A:hover { background: rgb(189,183,107) }
+
+div.box { border: solid; border-width: thin; width: 90%;
+ background: rgb(211, 211, 211) }
+
+div.box pre {margin: 0.66em 0 0.33em 1%; padding: 0;}
+
+div.man { border: solid; border-width: thin; width: 100%;
+ font-size: 70%
+ margin : 4;
+ background: rgb(211,211,211) }
+
+
+
+I { font-size : 12px;
+ font-family: Times, Verdana, Arial, Helvetica, sans-serif;}
</style>
View
8 www/stream.yaws
@@ -17,9 +17,9 @@ ssi(File) ->
out(A) ->
- [{ssi, "HEAD", [],[]},
- {ssi, "EXHEAD", [],[]},
+ [{ssi, "TAB.inc", [],[]},
{ehtml,
+ {'div',[{id, "entry"}],
[{h1, [], "Streaming data to the client"},
{p, [],
@@ -50,7 +50,9 @@ out(A) ->
box("yaws_api:stream_chunk_deliver_blocking(YawsPid, Data)")
- ]}].
+ ]}},
+ {ssi, "END2",[],[]}
+ ].
</erl>
View
4 www/upload.yaws
@@ -2,7 +2,9 @@
<h2> File upload </h2>
-<p>This page shows how to upload a file to the webserver
+<p>This page shows how to upload a file to the webserver, nothing of cource
+does actually gets written to disc, but the upload code is
+<a href="code.yaws?file=/upload.yaws"> Here in file upload.yaws </a>
<erl>
View
29 www/upload0.yaws
@@ -1,19 +1,22 @@
<erl>
out(A) ->
- {ehtml,
+ [{ssi, "TAB.inc", [],[]},
+ {ehtml,
{html, [],
- [{h1, [], "Upload a file to the webserver"},
- {p, [], "The code that parses the multipart form data resides in"},
- {a, [{href, "code.yaws?file=/upload.yaws"}], "upload.yaws"},
- {br},
- {hr},
- {form, [{enctype, "multipart/form-data"},
- {method, post},
- {action, "/upload.yaws"}
- ],
- [{input, [{type, submit}, {value, "Upload"}]},
- {input, [{type,file}, {width, "50"}, {name, foo}]}
- ]}]}}.
+ {'div',[{id, "entry"}],
+ [{h1, [], "Upload a file to the webserver"},
+ {p, [], "The code that parses the multipart form data resides in"},
+ {a, [{href, "code.yaws?file=/upload.yaws"}], "upload.yaws"},
+ {br},
+ {hr},
+ {form, [{enctype, "multipart/form-data"},
+ {method, post},
+ {action, "/upload.yaws"}
+ ],
+ [{input, [{type, submit}, {value, "Upload"}]},
+ {input, [{type,file}, {width, "50"}, {name, foo}]}
+ ]}]}}},
+ {ssi, "END2",[],[]}].
</erl>
View
41 www/yman.yaws
@@ -0,0 +1,41 @@
+
+<erl>
+
+prebox(Str) ->
+ {'div',[{class,"man"}],
+ {pre,[], Str}}.
+
+
+out(A) ->
+ H = {ssi, "TAB.inc", [],[]},
+ L = case queryvar(A,"page") of
+ {ok, Page} ->
+ %% only allow regular chars in Page
+ case lists:all(fun(C) ->
+ if
+ $a =< C, C =< $z ->
+ true;
+ $A =< C, C =< $Z ->
+ true;
+ C == $_ ->
+ true;
+ C == $. ->
+ true;
+ true ->
+ false
+ end
+ end, Page) of
+ true ->
+ os:cmd("man " ++ Page ++ " | col -b -p -x");
+ false ->
+ "illegal character detected in query arg"
+ end;
+ undefined ->
+ "no man page found in query arg "
+ end,
+
+ Man = {ehtml, {'div', [{id, "entry"}], prebox(L)}},
+ Trail = {ssi, "END2",[],[]},
+ [H, Man, Trail].
+
+</erl>

0 comments on commit bea8261

Please sign in to comment.