0

Finally time to apply JavaScript to a particular web site, so I wrote some code that works fine in a test sub-directory, but when I went to deploy this to the web site I ran into problem(s). The problem(s) appears to be unique to when I'm trying to use a script file that's not in the directory or a sub-directory to where the page that's calling it is located. And this would be a show-stopper because the new functionality is needed site wide and the directory structure dynamically changes based on other mechanisms we don't need to get into here; the ability to call a top-level script is vital.

So, I stripped it all down to two lines of very simple JavaScript to help illuminate the issues; when it is contained in a file in the directory where the calling html resides, it works, or a subdirectory from there, OR if I refer to it in the same directory via a link to another location, that's fine too. But if I try and refer to the script file in any other way, it fails with:

[Thu Dec 08 12:08:26.643037 2016] [cgi:error] [pid 27403] [client xx.xx.xx.xx:46247] AH01215: (8)Exec format error: exec of '/usr/www/http/js/test.js' failed, referer: http://example.com/test/jstest.html [Thu Dec 08 12:08:26.643548 2016] [cgi:error] [pid 27403] [client xx.xx.xx.xx:46247] End of script output before headers: test.js, referer: http://example.com/test/jstest.html

Here, of course, xx.xx.xx.xx is the IP of the server, "example.com" is the domain in question, and the path '/usr/www/http' is the top level directory Apache serves this domain's web site from.

I've read a lot of materials on this and I know the Apache configuration files matter... I've tried setting a ScriptAlias and have a few questions about it I can't seem to find clarity on:

  1. Just how are scripts in the "ScriptAlias" directory refered to in the HTML code - start with a slash? Is there some special character to say "top of site?" And;
  2. Is there only one unique ScriptAlias directory permitted for the whole site, or can one have multiple directories that are searched - and if so, how do you specify them, multiple definitions of ScriptAlias, comma separated list, etc? And;
  3. Can we set one per VirtualHost? And do we do this by putting a ScriptAlias inside the Virtual Host definition?

To make testing a little easier I made multiple instances of almost the same code in files of the same name in various directories, and altered the contents slightly so I could easily determine which location had taken effect with what kind of a call, all the while looking at the Apache logs. Here's an example from one of these files:

var myHeading = document.querySelector('h2');
myHeading.textContent = 'website top level js dir';

This code takes the first tag and replaces whatever the content was with whatever textContent is provided in the second line. Obviously, I was changing the textContent to match what the location was.

In the HTML, any reference like any of these worked so long as the calling page was either in the same directory as test.js or in a parent directory or if there was a link to test.js that was either in the same directory or a subdirectory:

<script src="test.js"></script>
<script src="js/test.js"></script>
<script src="http://example.com/test/js/test.js"></script>

In the HTML, any reference like these always failed no matter what I tried so long as the calling html was not in the same directory or a parent directory:

<script src="/js/test.js"></script>
<script src="/usr/WWW/http/js/test.js></script>
<script src="http://example.com/test/js/test.js"></script>

The directories and files involved are all owned by my personal UID and GID (as they always have been), and their permissions are all 755.

There's a global ScriptAlias defined as (also tried variations on this):

ScriptAlias /js/ "/usr/www/js/"

There's another ScriptAlias entry in the Virtual Host definition - no idea if it does anything! No effect so far as I can yet see. ... And, there are Directory entries like this in the main config file for all the directories I tried:

<Directory /usr/www/http/js/>
   AllowOverride None
   Options ExecCGI
   Require all granted
</Directory>

UPDATE Fredi wanted a tree. Fine:

The tree starts at the Virtual host's document root - who cares where? From there:

├── index.html
├── js
│   └── test.js
└── test
    ├── js
    │   └── test.js
    └── testjs.html

3 directories, 4 files
Richard T
  • 1,206
  • 12
  • 29

2 Answers2

0

This is not what ScriptAlias is intended for. You can't put client-side JavaScript files in a directory that's also described in a ScriptAlias directive.

ScriptAlias is an Apache configuration directive telling it to attempt to execute files in that directory as programs and return the programs' output, instead of simply transmitting a static file to the user agent. This is very obviously not what you want. It's the browser that is supposed to run the JavaScript, not the server.

Richard T
  • 1,206
  • 12
  • 29
Michael Hampton
  • 244,070
  • 43
  • 506
  • 972
  • Thanks for the reply but it doesn't help; that's where I started - no ScriptAlias. From my qs above: is there a special way to say "from the top of this site's directory tree" as it appears instead to always think it's in the same dir or a subdir to the file containing the html that's calling it. It also doesn't take if I give the full URL unless it's from the same dir or a subdir of the html file. – Richard T Dec 09 '16 at 17:31
  • It won't help if you leave `ScriptAlias` in. It is clearly causing at least part of your problem. – Michael Hampton Dec 09 '16 at 17:32
  • OK, interesting... Yes, I tested it thoroughly now, and it's true; if the dir is listed in a ServerAlias directory, it cannot be used for client-side .js files! Damn, that's obscure! Sure would be nice if you could put ALL your scripts in one place, but OK, them's the rules! Thanks. Works now. – Richard T Dec 09 '16 at 17:54
0

First some things that I noticed from your question:

  • ScriptAlias has nothing to do with client side scripting, it's for server side scripting / CGI
  • Filesystem execution flags do not matter on client side scripts

  • In this snippet:

<script src="/usr/WWW/http/js/test.js></script>

Seems to me you've put in there the full filesystem path, you should use URI paths instead, beware of the difference. Read as a URI path, it supposes the script can be downloaded from:

http(s)://example.com/usr/WWW/http/js/test.js

Actually what is happening from what i see from your logs is that Apache is trying to pass the javascript to a CGI process and failing at it, indeed it's a client side script:

[Thu Dec 08 12:08:26.643037 2016] [cgi:error] [pid 27403] [client xx.xx.xx.xx:46247] AH01215: (8)Exec format error: exec of '/usr/www/http/js/test.js' failed, referer: http://example.com/test/jstest.html [Thu Dec 08 12:08:26.643548 2016] [cgi:error] [pid 27403] [client xx.xx.xx.xx:46247] End of script output before headers: test.js, referer: http://example.com/test/jstest.html

So, start by getting your javascripts outside the ScriptAlias paths. And while we are at it, can you run a tree on yor document root, you can omit files, just leave the html file from where you're including your javascripts and the javascripts themselves so we can have a better picture.

Update after tree output

Assuming the html page that is loading the javascript it's the index.html in the document root, the correct way to load the first javascript, the one under $DOC_ROOT/js/test.js is:

<script src="/js/test.js"></script>

If you want to load the second one, the one under the "test" tree:

<script src="/test/js/test.js"></script>

That is, the filesystem path $DOCUMENT_ROOT is translated to the _URI path '/', or http(s)://example.com/

If things don't work check your logs. If you get the AH01215 error as above, check again your ScriptAlias settings though (I know you did that but that error is related to this)

Fredi
  • 2,257
  • 10
  • 13
  • Hmmm... All I want is for the server to pass to the client - the browser - the appropriate .js file from a subdirectory at the top of the web site when it's asked for by the browser. OK, so ScriptAlias is not involved; how then am I supposed to tell the browser where to get the js file? The ONLY strategies I can think of are: full path or full domain because apparently it assumes the directory the calling html file came from... I ask the questions discretely above! – Richard T Dec 09 '16 at 17:25
  • @RichardT, as in my reply (and Michael's one) can you first put your javascript out of the ServerAlias dirs? And post the output of `tree` (or similar) output of the related files in your documentroot? – Fredi Dec 09 '16 at 17:29
  • Sorry, I thought it was abundantly clear I had STARTED with that. Doesn't help, thanks. Ignore the ScriptAlias; not used now. – Richard T Dec 09 '16 at 17:33
  • The tree output? It's the third time I'm asking BTW – Fredi Dec 09 '16 at 17:41
  • ...Already added it over 10 minutes ago, I think! – Richard T Dec 09 '16 at 17:51
  • Updated as for your info – Fredi Dec 09 '16 at 17:53
  • Thanks for your comment that is much more simply stated as: "The Virtual Host's DocumentRoot effectively becomes / for purposes of referring to files in the tree." However, you completely missed the whole exercise: NO, the html in question was NOT coming from /index.html but from /test/testjs.html. Nothing ever done from index.html ever failed, at least not before I added the ScriptAlias entry. The key here is very simply: You cannot specify client-side scripts in any directory described in a ScriptAlias directive. Simple. Clear. Concise. – Richard T Dec 09 '16 at 18:03
  • That was the first point of my answer. But whatever, glad you got it working – Fredi Dec 09 '16 at 18:06