I am attempting to implement an oembed provider using the Silverstripe framework but have come across an issue.
I have a controller routed from the url /omebed.json and it works fine if I call something like /omebed.json?mediaurl=mymovie.mp4.
However the Oembed standard states it should be /omebed.json?url=mymovie.mp4
But Silverstripe internally checks the $_GET['url'] variable and will attempt to route to that page/controller. So SilverStripe is trying to route to /mymovie.mp4 skipping my controller and hitting the ErrorPage_Controller creating a 404.
I'm thinking im going to have to extend the ErrorPage_Controller and rejig it if the url is oembed.json, but this seems a little hackish.
Any suggestions?
Cheers
Extending on @Stephen's answer, here is a way to get around that issue without duplicating main.php
and without modifying it directly.
What I did was create a _ss_environment.php
file which is added early on in the loading process of Silverstripe.
_ss_environment.php
global $url;
$url = $_GET['raw_url'];
if (isset($_GET['url']))
{
unset($_GET['url']);
}
// IIS includes get variables in url
$i = strpos($url, '?');
if($i !== false)
{
$url = substr($url, 0, $i);
}
.htaccess
RewriteCond %{REQUEST_URI} ^(.*)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !\.php$
RewriteRule .* framework/main.php?raw_url=%1 [QSA]
So here is what is happening:
.htaccess
is now using raw_url
instead of url
_ss_environment.php
is being called early in the loading process, setting the global $url
variable that main.php
normally sets. This is set with raw_url
rather than url
.main.php
to just override it again when it sees your url
query string parameter, it is unset (Silverstripe seems to reset this later as far as my test is concerned).main.php
would normally run if $_GET['url']
is set, copied as-is for apparent support in IIS. (If you don't use IIS, you likely won't need it.)This has a few benefits:
main.php
allows upgrading Silverstripe slightly easier in the futureThe one obvious drawback to any solution for changing away form the url
query string parameter is if anything looks at the parameter directly. With how Silverstripe works, it is more likely that code uses the $url
global variable or the Director
class rather than looking at the query string for the current URL.
I tested this on a 3.1 site by doing the changes I mentioned and:
TestController
In the init
function of the controller, I am running the following:
var_dump($_GET['url']);
var_dump($this->getRequest()->getVars());
/TestController?url=abc123
, saw the value of both dumps have "abc123" as the value for the URL parameter.Unfortunately, I haven't been able to find documentation for the order of inclusion in regards to _config.php
and _ss_environment.php
. However, after browsing through the code, I have worked out it is this:
main.php
runs, first main task is to require core/Constants.php
Constants.php
's first task is to search for _ss_environment.php
in the base folder and potential parent folders. If it finds it, it will be included.main.php
(and after the $_GET['url']
check is done in main.php
), it will start an ErrorControlChain
which it internally does another require for core/Core.php
Core.php
, it performs calls for the config manifestConfigManifest.php
exposes the functions to actually add _config.php
files and for them to be required.I could probably go on however I think this gives a pretty good picture of what is going on. I don't really see a way around not using the _ss_environment.php
file. Nothing else gets included early enough that you can hook into without modifying core code.
I had a quick play with this the other day. And looking at what main.php
does it might be best to hack away at it rather than ErrorPage_controller
.
For startes SS's default .htaccess
file does this:
<IfModule mod_rewrite.c>
SetEnv HTTP_MOD_REWRITE On
RewriteEngine On
# RewriteBase /silverstripe
RewriteCond %{REQUEST_URI} ^(.*)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* framework/main.php?url=%1&%{QUERY_STRING} [L]
</IfModule>
Note the ?url
changing that to something else and then changing main.php
's usage as well may/should help or will cause a heap of extra errors and sadness.
To avoid hacking the core/framework, you could change the .htaccess to target a copy of main.php in mysite
(with appropriate include changes).