docroot, approot and very fishy behavior

7 views
Skip to first unread message

ke han

unread,
Nov 6, 2006, 2:44:59 PM11/6/06
to erlyweb
Using erlyweb 0.2.1 I create the music app tutorial.
It works as expected but there are "problems".
To be very clear, I will use exact paths to avoid confusion:
The directory structure on OS X is:

/Users/kehan/yaws_apps/ %% my root for yaws apps
/Users/kehan/yaws_apps/music
/Users/kehan/yaws_apps/music/www %% the yaws docroot as set in
yaws.conf
/Users/kehan/yaws_apps/music/ebin
/Users/kehan/yaws_apps/music/src

My yaws.conf contains:

<server www.erlymusic.com>
port = 8000
listen = 192.168.1.20
docroot = /Users/kehan/yaws_apps/music/www
appmods = <"/music", erlyweb>
<opaque>
appname = music
</opaque>
</server>

All works as expected.
Here are the problems:

The generated code has a file index.html which references style.css.
Both index.html and style.css are directly under my yaws docroot as
generated by erlyweb.
Line 3 of index.html references the stylesheet:

<link rel="stylesheet" href="/music/style.css">

This is the first clue that something fishy is going on. I can enter a
url of:
www.erlymusic.com:8000 _or_ www.erlymusic.com:8000/music and get
working results of the same welcome page. I would not expect this. I
should not be able to use _both_ urls unless I were to explicitely code
my app or yaws to handle both urls as the same.

My yaws docroot is /Users/kehan/yaws_apps/music/www. This is supposed
to mean that _all_ references in html files use this as the root. For
the stylesheet ref to work as it is coded, there should be a directory
under /Users/kehan/yaws_apps/music/www called music which of course
there is not.
So there is some trickery going on here that provides for surprises and
violates what I have set as my yaws docroot.

To demonstrate this trickery and show what kind of trouble it causes,
lets try these experiments.
Lets change the yaws config so the appmod is:
appmods = <"/", erlyweb>
This is perfectly legal and setting the root as an appmod was a bug
until very recently in yaws.
Now, I can still go to www.erlymusic.com:8000 and get my friendly
welcome view. But if try to go to www.erlymusic.com:8000/music, I get
an error:

The requested URL //music was not found on this server.

Notice the two slashes instead of one.

Of course if I try to go to www.erlymusic.com:8000/musician, which was
my goal, I get an error as well:

ERROR erlang code crashed:
File: appmod:0
Reason: {badarg,[{lists,split,[-1,"/musician"]},
{erlyweb_util,get_app_root,1},
{erlyweb,ewc,2},
{erlyweb,app_controller_hook,3},
{yaws_server,deliver_dyn_part,8},
{yaws_server,aloop,3},
{yaws_server,acceptor0,2},
{proc_lib,init_p,5}]}
Req: {http_request,'GET',{abs_path,"/musician"},{1,1}}

AHH but the fun doesn't stop there...remember I have set my appmod to
"/". I can still go to
www.erlymusic.com:8000/music/musician or
www.erlymusic.com:8000/music/musician/list/1 as if I had not changed
my appmod path at all!!!

I'm sure these things can be fixed...Yariv???

thanks, ke han

Yariv Sadan

unread,
Nov 6, 2006, 4:04:07 PM11/6/06
to erl...@googlegroups.com

This is a weird side effect of Yaw's appmod handling. If you go to

erlymusic.com:8000

the erlyweb appmod won't be invoked. Instead, Yaws will open
'index.html' in the docroot, i.e. music/www. OTOH, if you go to

erlymusic:com:8000/music

then the erlyweb appmod will pick up the request, check if it matches
the URL of a component, and since the component part is empty, it will
return to yaws the following tuple:

{page, "/index.html"}

(in ErlyWeb 0.2.2, which I will release later today, this will change
to {page, "/"}, which is more appropriate).

This again makes Yaws open music/www/index.html.

I think that the only way you can avoid this duplication is by setting
your appmod to "/".

>
> My yaws docroot is /Users/kehan/yaws_apps/music/www. This is supposed
> to mean that _all_ references in html files use this as the root. For
> the stylesheet ref to work as it is coded, there should be a directory
> under /Users/kehan/yaws_apps/music/www called music which of course
> there is not.
> So there is some trickery going on here that provides for surprises and
> violates what I have set as my yaws docroot.

The confusion again stems from the fact that if ErlyWeb receives a
request whose path doesn't match a component, it returns to yaws a
tuple such as {page, "/path"}. For instance, lets assume you open

http://erlymusic.com/music/style.css

if 'style.css' isn't the name of a component, ErlyWeb will return to Yaws

{page, "/style.css"}

This yields the same result as navigating to

http://erlymusic.com/style.css

(assuming style.css is in the docroot, i.e. music/www/).

Assuming your appmod is set to be <"/music", erlyweb>, then the only
way to load the

>
> To demonstrate this trickery and show what kind of trouble it causes,
> lets try these experiments.
> Lets change the yaws config so the appmod is:
> appmods = <"/", erlyweb>
> This is perfectly legal and setting the root as an appmod was a bug
> until very recently in yaws.
> Now, I can still go to www.erlymusic.com:8000 and get my friendly
> welcome view. But if try to go to www.erlymusic.com:8000/music, I get
> an error:
>
> The requested URL //music was not found on this server.
>
> Notice the two slashes instead of one.

The two slashes looks like a bug. I'll fix it.

>
> Of course if I try to go to www.erlymusic.com:8000/musician, which was
> my goal, I get an error as well:
>
> ERROR erlang code crashed:
> File: appmod:0
> Reason: {badarg,[{lists,split,[-1,"/musician"]},
> {erlyweb_util,get_app_root,1},
> {erlyweb,ewc,2},
> {erlyweb,app_controller_hook,3},
> {yaws_server,deliver_dyn_part,8},
> {yaws_server,aloop,3},
> {yaws_server,acceptor0,2},
> {proc_lib,init_p,5}]}
> Req: {http_request,'GET',{abs_path,"/musician"},{1,1}}

That's a bug. I'll fix it.

>
> AHH but the fun doesn't stop there...remember I have set my appmod to
> "/". I can still go to
> www.erlymusic.com:8000/music/musician or
> www.erlymusic.com:8000/music/musician/list/1 as if I had not changed
> my appmod path at all!!!
>

That's because of the weird way Yaws handles appmods. As long as a
substring of the path component matches the appmod directive in
yaws.conf, Yaws forwards the request to the appmod (the substring
doesn't have to start from index 0). Check out this page for more info
(it's the 'prepath' string):http://yaws.hyber.org/appmods.yaws. I
should probably add a check in ErlyWeb to make sure the prepath length
is 0 because this behavior is too weird.

> I'm sure these things can be fixed...Yariv???

Will do :)

Cheers,
Yariv

Yariv Sadan

unread,
Nov 6, 2006, 4:18:37 PM11/6/06
to erl...@googlegroups.com
> > AHH but the fun doesn't stop there...remember I have set my appmod to
> > "/". I can still go to
> > www.erlymusic.com:8000/music/musician or
> > www.erlymusic.com:8000/music/musician/list/1 as if I had not changed
> > my appmod path at all!!!
> >
>
> That's because of the weird way Yaws handles appmods. As long as a
> substring of the path component matches the appmod directive in
> yaws.conf, Yaws forwards the request to the appmod (the substring
> doesn't have to start from index 0). Check out this page for more info
> (it's the 'prepath' string):http://yaws.hyber.org/appmods.yaws. I
> should probably add a check in ErlyWeb to make sure the prepath length
> is 0 because this behavior is too weird.

Actually, this isn't even a prepath issue. It looks like a bug in
Yaws, where Yaws forwards requests such as

http://foo.com/music/musician

to ErlyWeb, passing it an appmoddata of "/musician" even when the
appmod directive in yaws.conf is

appmods = <"/", erlyweb>

Yariv

Yariv Sadan

unread,
Nov 6, 2006, 4:41:31 PM11/6/06
to erl...@googlegroups.com
> >
> > The requested URL //music was not found on this server.
> >
> > Notice the two slashes instead of one.
>
> The two slashes looks like a bug. I'll fix it.

Correction: This is a byproduct of what looks like a Yaws bug. When
you set your appmods directive in yaws.conf to

appmods = <"/music", erlyweb>

and then you navigate to http://localhost:8000/music/music, you get
the error message "The requested URL /music was not found on this
server." (Note the single slash, which is correct.)

However, when you set your appmods directive to

appmods = <"/", erlyweb>

and then you navigate to http://localhost:8000/music, you get the
error message, "The requested URL //music was not found on this
server." Now you get the double slash.

I will add a workaround to this bug in ErlyWeb by checking for a
leading slash, but this should still be fixed in Yaws because it is
causing other problems.

Yariv

Reply all
Reply to author
Forward
0 new messages