Why does this relative file path work?

Why does this relative file path work?

Post by Steve Breche » Sun, 06 Jul 2003 07:02:34



On a shared Linux/Apache host, my directory structure is as follows:

home
    data
    HTML
        cgi
        topic
            downloads

topic contains page.html (and also the "downloads" directory).  page.html
contains a link to cgi/script.pl.  script.pl increments a count in a data
file and then redirects the client to download a file:

$k_counts_filepath = "../../data/hes_dl_counts.txt";
$k_target_dir_uri = "../../topic/downloads/";
# code to validate existence of download target and to increment counter
goes here
if ($ok) {
 print "Location: $k_target_dir_uri$targetname\n";
 print "Status: 302 Found\n\n"; }
else {
 print "Status: 404 Not found\n\n"; }

The double-up (../..) in the path to the file in the "data" directory seems
straightforward; it's relative to the cgi directory which contains the
script.

But notice the ../.. in the path to the "downloads" directory.  Wanting to
use a relative rather than absolute path I arrived at this by trial and
error, but I don't understand why it works.  What is the base directory that
the "../.." is being applied to?

--
For mail, please use my surname where indicated:

 
 
 

Why does this relative file path work?

Post by David Efflan » Mon, 07 Jul 2003 01:58:20



> On a shared Linux/Apache host, my directory structure is as follows:

> home
>     data
>     HTML
>         cgi
>         topic
>             downloads

> topic contains page.html (and also the "downloads" directory).  page.html
> contains a link to cgi/script.pl.  script.pl increments a count in a data
> file and then redirects the client to download a file:

> $k_counts_filepath = "../../data/hes_dl_counts.txt";
> $k_target_dir_uri = "../../topic/downloads/";
> # code to validate existence of download target and to increment counter
> goes here
> if ($ok) {
>  print "Location: $k_target_dir_uri$targetname\n";
>  print "Status: 302 Found\n\n"; }
> else {
>  print "Status: 404 Not found\n\n"; }

> The double-up (../..) in the path to the file in the "data" directory seems
> straightforward; it's relative to the cgi directory which contains the
> script.

> But notice the ../.. in the path to the "downloads" directory.  Wanting to
> use a relative rather than absolute path I arrived at this by trial and
> error, but I don't understand why it works.  What is the base directory that
> the "../.." is being applied to?

You do not need a Status: header for a redirect (apache does that
automatically for Location:).

You have one too many "../" in there.  If this was a /~user/ URL it would
not work.  But apparently you have a virtual host and a URI path cannot go
above the root of your website, so from cgi dir, the following should all
end up in the same place:

/topic/downloads/ (full URI path)
../topic/downloads/ (relative path, did this not work?)
../../topic/downloads/ (backtracking above URI root ignored)

I don't know whether apache or the browser generated the proper path for
the redirect.  But the browser needs to construct a full URL path for an
HTTP request and it cannot go above URI root.

If something did not work with the actual relative path, either you made a
typo or there is something unusual about your server config that we cannot
see here.

--
David Efflandt - All spam ignored  http://www.de-srv.com/
http://www.autox.chicago.il.us/  http://www.berniesfloral.net/
http://cgi-help.virtualave.net/  http://hammer.prohosting.com/~cgi-wiz/

 
 
 

Why does this relative file path work?

Post by Alan J. Flavel » Mon, 07 Jul 2003 02:38:20


On Fri, Jul 4, Steve Brecher inscribed on the eternal scroll:

Quote:> $k_target_dir_uri = "../../topic/downloads/";
> # code to validate existence of download target and to increment counter
> goes here
> if ($ok) {
>  print "Location: $k_target_dir_uri$targetname\n";
>  print "Status: 302 Found\n\n"; }

So: basically you are issuing a Location: CGI response with a
relative URL as its operand.

If you'd check the best-current-practice CGI draft, you'd notice that
this isn't one of the two forms of operand that are defined for a
CGI Location response.

As far as I recall the original CGI specification sketched out at
NCSA, it also had no examples of using relative URLs, though its
specification was a bit vague compared with what's in the RFC draft.

I would recommend therefore that you not use relative URLs in
Location: responses.

If you want a 302 redirection, then you should supply a full URL
(there's then no need to specify a Status - you would use Status if
you wanted a 30x value other than 302, such as 301 or 307).

If, on the other hand, you supply an absolute URLpath, the server is
required to provide the other kind of Location: response, namely an
internal redirection, resulting in the specified contents being
returned with a 200 status.

The specification isn't very clear about what's supposed to happen if
you provide incompatible headers, such as an absolute URLpath +and+
a status 30x.  You might find it doing what you wanted on one server,
and something different on another.

So I'd say you best follow the best-practice draft.

References

http://CGI-Spec.Golux.Com/
http://hoohoo.ncsa.uiuc.edu/cgi/
Perl FAQ part 9 e.g http://www.perldoc.com/perl5.8.0/pod/perlfaq9.html

Quote:> But notice the ../.. in the path to the "downloads" directory.  Wanting to
> use a relative rather than absolute path I arrived at this by trial and
> error, but I don't understand why it works.  What is the base directory that
> the "../.." is being applied to?

In both cases the reference is to a _URL_ and NOT to a filepath as
such.  Sometimes (quite often, indeed) the URL hierarchy is based on
some part of the server's file directory hierarchy, but this is by no
means inevitable, and at various points such a simple-minded model
will break down (due to symlinks, aliases etc.).  You absolutely
_must_ resolve relative URLs *as* URLs, and _only then_ map them to
actual server resources, if you are to be sure of getting the right
answer.

good luck

--
     "The operator has a long-standing problem with short formations" -
     news report about a train service - translation: the operator
     provides a short train, and the travellers get a long stand.

 
 
 

Why does this relative file path work?

Post by Steve Breche » Mon, 07 Jul 2003 07:53:30




> > On a shared Linux/Apache host, my directory structure is as follows:

> > home
> >     data
> >     HTML
> >         cgi
> >         topic
> >             downloads

> > topic contains page.html (and also the "downloads" directory).
page.html
> > contains a link to cgi/script.pl.  script.pl increments a count in a
data
> > file and then redirects the client to download a file:

> > $k_counts_filepath = "../../data/hes_dl_counts.txt";
> > $k_target_dir_uri = "../../topic/downloads/";
> > # code to validate existence of download target and to increment counter
> > goes here
> > if ($ok) {
> >  print "Location: $k_target_dir_uri$targetname\n";
> >  print "Status: 302 Found\n\n"; }
> > else {
> >  print "Status: 404 Not found\n\n"; }

> > The double-up (../..) in the path to the file in the "data" directory
seems
> > straightforward; it's relative to the cgi directory which contains the
> > script.

> > But notice the ../.. in the path to the "downloads" directory.  Wanting
to
> > use a relative rather than absolute path I arrived at this by trial and
> > error, but I don't understand why it works.  What is the base directory
that
> > the "../.." is being applied to?

> You do not need a Status: header for a redirect (apache does that
> automatically for Location:).

Noted.

Quote:> You have one too many "../" in there.  If this was a /~user/ URL it would
> not work.  But apparently you have a virtual host and a URI path cannot go
> above the root of your website, so from cgi dir, the following should all
> end up in the same place:

> /topic/downloads/ (full URI path)
> ../topic/downloads/ (relative path, did this not work?)

(This is now irrelevant because I am persuaded that what is needed to comply
with CGI best practice is either an entire URL or a complete path; however,
for the record...)

It didn't work; the server reported that the URL
               /~myaccount/cgi/topic/downloads/target.file
was not found on the server.

Quote:> ../../topic/downloads/ (backtracking above URI root ignored)

As noted originally, this worked.

--
For mail, please use my surname where indicated: