Static files

1 view
Skip to first unread message

Dmitrii Dimandt

unread,
Jul 16, 2009, 8:28:08 AM7/16/09
to ew...@googlegroups.com
Old code for BeepBeep looked like this:

Provided that Req is a MochiWeb request:

case dispatch(Env, AppWebModule) of
  {ok, Status, ContentType, H, Content} ->
      Req:respond({Status, [{"Content-Type", ContentType}|Headers], Content});
  {redirect, Url} ->
   Req:respond({302,
                         [{"Location", Url},
                          {"Content-Type", "text/html; charset=UTF-8"}],
                         ""});
  {static, File} ->
      Req:serve_file(StaticFile, "path/to/file/dir")
end



This is, in part, trivially converted to ewgi.

case dispatch(C) of {ok, Status, ContentType, Headers, Content} -> {ewgi_context, Request, {ewgi_response, {Status, "OK"}, [{"content-type", ContentType} | Headers], Content, undefined}}; {redirect, Url} -> {ewgi_context, Request, {ewgi_response, {302, "Temporary redirect"}, [{"Location", Url}, {"Content-Type", "text/html; charset=UTF-8"}], "", undefined}}; {static, File} -> ??????????????????????????? end.


What do I do with files? :)


One answer is to get rid of {static, File} and let the webserver handle static content before it ever gets to the innards. However, there are cases when this may leak down to middleware or the framework (say, we cache output in static files).

Filippo Pacini

unread,
Jul 16, 2009, 9:31:46 AM7/16/09
to ew...@googlegroups.com
To serve files you in the body a callable/0.

In this case calls mochiweb's
Req:respond({Code, Headers, chunked})

and then invokes your allable to write chunks of the file.
The callable is written in a continuation passing style.
It returns a tuple {DataRead, callable}. When all the data is read the
callable must return an empty tuple {}

Take a look in ewgi_mochiweb.erl:
handle_result1 and handle_stream_result

cheers,
filippo

Dmitrii Dimandt

unread,
Jul 16, 2009, 9:53:09 AM7/16/09
to ew...@googlegroups.com
so, I would do something along the lines of

...
{static, File} ->
FileDesc = file:open(File, [read]),
{ewgi_context, Request, serve_file(FileDesc, 0, 100)}
...


where

serve_file(FileDesc, Location, Number) ->
F = fun() ->
case file:pread(FileDesc, Location, Number) of
{ok, Data} ->
{Data, serve_file(FileDesc, Location + Number,
Number)};
_ ->
file:close(FileDesc)
end,
F.



Am I correct?

Filippo Pacini

unread,
Jul 16, 2009, 10:08:47 AM7/16/09
to ew...@googlegroups.com
After you close the file return {}
Then it seems correct.

Hunter Morris

unread,
Jul 16, 2009, 10:10:48 AM7/16/09
to ew...@googlegroups.com
2009/7/16 Dmitrii Dimandt <dmit...@gmail.com>:

> so, I would do something along the lines of
>
> ...
> {static, File} ->
>     FileDesc = file:open(File, [read]),
>     {ewgi_context, Request, serve_file(FileDesc, 0, 100)}
> ...
>
>
> where
>
> serve_file(FileDesc, Location, Number) ->
>     F = fun() ->
>         case file:pread(FileDesc, Location, Number) of
>            {ok, Data} ->
>                 {Data, serve_file(FileDesc, Location + Number,
> Number)};
>             _ ->
>                 file:close(FileDesc)
>     end,
>     F.
>
>
>
> Am I correct?

The "stream" that you return is element 4 of the response tuple. It
also should conform to the stream format in the specification:

So, something like this:

fun() -> {<<"binary chunk 1">>, fun() -> {<<"binary chunk2">>, fun()
-> {} end} end} end.

You would produce it with your above example as in this gist:
http://gist.github.com/148423

Best,
Hunter

Hunter Morris

unread,
Jul 16, 2009, 10:13:48 AM7/16/09
to ew...@googlegroups.com
2009/7/16 Hunter Morris <hunter...@gmail.com>:

> You would produce it with your above example as in this gist:
> http://gist.github.com/148423

Also, please note that my examples are very "raw" in that they
directly manipulate the ewgi tuples. It's obviously best to use a
layer of abstraction to manipulate them (as in the ewgi_api module for
example).

Dmitrii Dimandt

unread,
Jul 16, 2009, 10:44:13 AM7/16/09
to ew...@googlegroups.com
It works! Thank you!

Now only the question of setting correct mimetypes remains, but that's
"easy-peasy" :)
Reply all
Reply to author
Forward
0 new messages