Setting new absolute path of resources within Javascript depending on environment - php

I have an external javascript file that uses the getScript() function to run another JS file.
I have those all on static.mydomain.com. (I'm new to setting up CDNs)
getScript() doesn't seem to allow cross-domain requests because my HTML is on domain.com. But then I tried using relative paths according to this post: Dynamic URLs in CSS/JS
It works for CSS but does not work for JS (specifically within the getScript() function). What's going on here? What are some ways to mitigate this problem when dealing with CDNs?

The getScript method actually makes an ajax call, hence the reason it's not working. Unless you need access to things like 'was the script successfully found' and the like, it's better to just write up a quick method like...
function addScript(source, domain) {
$("head").append("<script src='"+ (domain ? domain + source : source) +"'></script>");
}
That will just add scripts to the head of the page, and let you add an optional domain to point to in case you want to change it up.

Related

Directory path calls, strange behaviour

I have an ajax request that I'm trying to call a specific file from which is located at:
ROOT/admin/functions/upload/filename.php
And the page making the request from is located at:
ROOT/admin/customers/123
Which is modified through htaccess from
ROOT/admin/customer.php?id=123
I have tried every combination of paths I could think of but I get some strange behaviours for example when I use
../functions/upload/filename.php
It looks for the file in
ROOT/functions/uploads/filename.php
And when I use
functions/upload/filename.php
It looks for the file in
ROOT/admin/customers/functions/uploads/filename.php
So I tried
../admin/functions/upload/filename.php
And it looks in
ROOT/admin/admin/functions/upload/filename.php
I'm pulling my hair out here, has anyone got any ideas as to what this might be?
Any help would be greatly appreciated.
Thanks, James.
Since the browser knows NOTHING about your server-side paths, and it only has the path you see in the address bar, e.g.
http://example.com/ROOT/admin/customers/123
then if your ajax code looks like
$.ajax('functions/foo/bar.php');
Then the ajax call will be requesting
http://example.com/ROOT/admin/customers/123/functions/foo/bar.php
Similarly, adding ../ just strips off levels of the source page's address:
$.ajax('../../functions/foo/bar.php');
results in
http://example.com/ROOT/admin/customers/123/../../functions/foo/bar.php
^-A-^
^-------B------^
http://example.com/ROOT/admin/functions/foo.bar.php
You probably want
$.ajax('/ROOT/functions/foo/bar.php');
With that leading /, the browser ignores ALL of the subdirectory stuff in the url and uses the entire path from the ajax call as the entirety of the path.
http://example.com/ + /ROOT/functions/foo.bar.php

API Component Separation

I'm new to the world of API programming, I just have a bit of a side project at work at the moment and I'm learning as I write, so bear with me.
I'm unsure as to the best way to implement an API for multiple different functions. At the moment I just have a test script I run and an apache redirect that redirects anything under /api to this script, call it TestAPI.php (so /api/anything will redirect). I pass the path variable of the API to the script (so in that example the path would be 'anything').
At the moment I'm just writing it for 1 purpose, to look up some data based on the path, and eventually be about to update and delete etc with PUT/DELETE etc (it's restISH not restFUL). This is fine at the moment where everything redirects to this script, but what about if I need 2 different functions? So I want to look up a different data set? So for example now /api/data1 would go to the 1st set and /api/data2 would go to the second. This is where I start to get unsure.
Do I simply have 1 mega script that grows and grows so that /api/data1 and /api/data2 redirect to the same place (and thus handle any errors like 404s there). Or do I have a script for /api/data1 and /api/data2 with separate redirects to each, then a generic catchall for 404s (I would always like to return JSON/XML rather than HTML for a 404, so I need at least logic to return based on the Accept header).
As a 3rd option, do I have some sort of frontline controller that catches everything, then calls off to the sub components? So 1 script that is redirects to for anything under /api, which then calls off to the required components or 404s if it's an invalid path. This seems like the best way to do it to me, but I have no idea how. Do I have some section of the site that only that script can call, or do I use cURL from the frontline controller to the back end API sections (as I'd need to pass POST/PUT data I assume I'd have to use cURL, is there any other way?). How is this best implemented in Apache?
Yes, you use a front controller. The front controller can use convention like first thing after /api processes the request
i.e.
/api/firstprocessor/method1
/api/firstprocessor/method2
/api/secondprocessor/method14
You can check out Zend_Framework for an example of this in action, or it can be something as simple as
$name = 'Script_' . $this->generateCommandName($request->getPathVariable(1));
$this->executeScript($name, $request);
public function executeScript($class, Request $request) {
if (file_exists("scripts/".$class.'.php')) {
//include the script
require_once "scripts/".$class.'.php';
//execute the script
$command = new $class;
$command->execute($request);
}
}
Then all your scripts just have an execute method that uses $request to get $_GET or $_POST variables

Allow PHP file to be requested by javascript but not directly from browser

I'm using a jquery script that uploads files with ajax and PHP. It sends a request to upload_a_file.php which then uploads files.
Is there a way that I can make sure upload_a_file.php is not loaded directly in a browser?
I tried putting upload_a_file.php above my public_html folder. But can't seem to get javascript to load upload_a_file.php.
Here is the url format I use in the javascript to request upload_a_file.php:
../upload_a_file.php
Is it even possible to access files above public_html with javascript?
JS cannot access anything on a server that you yourself as a user cannot. If a file is outside of the site's document root, it is NOT accessible by a user, or by JS. Imagine the fun place the web would be if JS could magically bypass access restrictions on a server and grab any more. "Aww, I was going to grab this bank's accounts list, but it's not in the document root. Good thing I've got Javascript, it can do everything!"
It'd be like every episode of 24, where "patching into the subnet" can magically bypass any firewall and get data from machines which aren't even online or (better yet) not even powered up. Amazing things, those subnets.
You can check the HTTP header X_REQUESTED_WITH is present and has a value of XMLHttpRequest. This is not non-standard header but most JavaScript frameworks, including jQuery, Prototype, and mootools follow this convention.
In PHP you can access it $_SERVER['HTTP_X_REQUESTED_WITH'];
for example:
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
{
// do something
}
The javascript is running in the browser. It makes its requests through the browser. So, No, there's no way to access a page through ajax but not directly from the browser.
No, not directly. You can call other script (PHP or whatever) that will either "call" your script with include or e.g. with fopen or curl.
Nothing can access files above public_html, because the web server will not serve them. Doing so would have obvious security vulnerabilities, like being able to view any file on your filesystem.
If you want to restrict the file to only being able to be loaded via your javascript, I would think you'd want to look at the $_SERVER['HTTP_REFERER'] variable in php. This should be set to the page the javascript is located on when it is being accessed properly. If it is anything else or empty, the user is accessing it in some other manner.
Using this method shouldn't be relied on for security however, because the referer can be spoofed with the right tools.
Since direct browser access to a page is a GET request by PHP, here is a very basic access control method to keep someone from inadvertently going directly to upload_a_file.php:
In your jquery script, use an ajax request with type "POST":
$.ajax({
url: "../upload_a_file.php",
dataType: "json",
type: "POST"
});
and use this in your upload_a_file.php:
if ($_SERVER['REQUEST_METHOD'] == "POST") {
// upload a file
} else {
header("Location: http://example.com/myPublicUploadPage.php");
die();
}

Clean links to PHP-generated JavaScript and CSS

Background: When generating HTML content with PHP or any such thing, it is possible to encapsulate links to JavaScript and CSS inside tags without actually having to include the CSS and JavaScript "in-line" with the rest of the content. All you have to do is create a link to the file.
Example:
{script type="text/javascript" src="./js/fooscript.js"}{/script}
Question: The above approach does not work, however, if your PHP needs to dynamically generate some or all of your JavaScript code. Is there a way to have a clean "one-line" link as above, but still use dynamically-generated JavaScript?
Obviously, one way to do it is to have PHP auto-generate the JavaScript and write that to a file; however that approach is undesirable for various reasons. I am wondering if there is an alternate trick to doing this that I have not thought of yet.
Put an .htaccess file in your /js/ folder and add the .js extension to PHP, like this:
AddHandler application/x-httpd-php .js
In other words, have PHP parse all .js files as PHP files. So your scripts would really be PHP files on the server-side that output JavaScript. Do the same for stylesheets, only use the .css extension, obviously.
Note: I've never tried doing this in a separate .htaccess file. If it doesn't work, just put it into your global Apache config.
From my experience, rarely do you need to (and rarely should you) generate an entire script dynamically. For example, in javascript you may need to dynamically get some piece of data (like user info or settings) into javascript, but the rest of the script (classes/functions/DOM manipulations) is static across all users.
Typically in this case you would just want to put the dynamic stuff "inline", output dynamically from PHP and then include the js (the 95% that doesn't need dynamically generated) as an external script. The most obvious reason for this is caching the js/css.
Consider how reddit.com does it by looking at their source code for getting user data into javascript.
var reddit = {
/* is the user logged in */ logged: 'username',
/* the subreddit's name (for posts) */ post_site: "",
/* are we in an iframe */ cnameframe: false,
/* this page's referer" */ referer: "",
/* the user's voting hash */ modhash: 'lzbcszj9nl521385b7e075e9750ee4339547befc6a47fa01e6',
/* current domain */ cur_domain: "reddit.com", ...
}
The rest of their js is found in external files.
You could just use mod_rewrite to make certain php files be seen as CSS/JS
e.g. /css/screen-style.css points to css.php?friendly_id=screen-style
You can use .php files in JavaScript and CSS calls. It's not pretty and anyone looking at your source knows it's a script, but it saves the hassle of configuration on the server. Also, if you're making dynamic JavaScript, I would suggest adding a timestamp on the end so the browser doesn't cache it.
Example.
<script src="myjavascript.php?a=20090611-021213"></script>

How to I make sure the path in jQuery autocomplete call to CakePHP controller/action resolves correctly?

I have the CakePHP stack in /var/www/site
from one view under controller A I do a jquery ajax call:
$("#searchstring").autocomplete("/items/getitemsforautocomplete", { ... more code
when the call is triggered I can see from firebug that cakephp wants to call:
http://localhost/items/getitemsforautocomplete?q=me
Note that 'site' is missing, resulting in a 404.
When I upload this to my site it works the way it should. How should I configure this correctly??
Doesn't '/' go to the root directory of the site? If your javascript file is in /var/www/site/script, you might want to do:
$("#searchstring").autocomplete("../items/getitemsforautocomplete", { ... more code }
Try using FULL_BASE_URL in your JS, like:
$("#searchstring").autocomplete("<?= FULL_BASE_URL ?>/items/getitemsforautocomplete", {
Not the most elegant way, but it solved some of my headaches in the past.
this is most likely due to the level of the call made from jquery. is the http://localhost/items/... the correct URL?
a not-used html tag that is really good is setting the base href. then all links and javascript calls are made from this.
<base href="http://localhost/site/">
then just remove the leading '/' from your script
$("#searchstring").autocomplete("items/getitemsforautocomplete", { ... more code

Categories