Url Variables with %2f not handled by silex - php

I am very new to silex, but have experience with Java based MVC frameworks.
The problem I have seems to be how to accept certain special characters in URL arguments.
I have a controller defined as such:
$app->get('/editPage/{fileName}', function ($fileName) use ($app,$action) {
return $app['twig']->render('edit.twig.html',$action->editPage($fileName));
});
and this works great for urls like:
/myapp/editPage/file.html
/myapp/editPage/file-2.html
but if I pass an encodes "/" or %2F, the route is not picked up, and I get a 404.
1. /myapp/editPage/folder%2Ffile.html
The mod_rewrites rules should route any non-existent file paths to the index.php where silex is defined, so I am not sure what is happening.
I just need a way to capture values with "/" for this particular page. There are no conflicting childpages, so if there is a way to wildcard the path "/editPage/{.*|filename}/" or something obvious I am missing.

You can use assert to change the regex that is used to match the variable. If you want it to match anything, pass a very lenient regex.
eg.
$app = new \Silex\Application();
$app->get('/file/{filename}', function ($filename) {
die(var_dump($filename));
})->assert('filename', '.*');
$app->run();
These requests
GET /file/a%2fb%2fc.txt
GET /file/a/b/c.txt
both yield
string 'a/b/c.txt' (length=9)

It's not an issue with Silex but with Apache.
Apache rejects by design encoded slashes as part of the URI for security purposes. See this answer: https://stackoverflow.com/a/12993237/358813
As a workaround passing the value inside a query string is completely fine:
http://example.com/?file=%2Fpath%2Fto%2Ffile will work, provided you configure Silex accordingly.

In addition to #tacone answer's, here's how I configured Silex to make it work.
I guess it's not the prettiest solution however...
The URL called should be /get/?url=<url encoded>
$siController->get('/get/', function(Application $app, $url){
/** #var SocialIdentifier $si */
$si = $app['social_identifier.social_identifier'];
$result = $si->get($url);
return $app->json($result, 200);
})
->value('url', $_GET['url']);

Related

Difference between match parameter and RequestContext in Symfony Router UrlMatcher

I don't understand the semantics of the Symfony Routing Component's API.
From the first code example on the Routing Component documentation page:
$context = new RequestContext('/');
$matcher = new UrlMatcher($routes, $context);
$parameters = $matcher->match('/foo');
Why is the hostname and HTTP method passed in via $context and the path via a parameter to match()? Or is it? There is also a path parameter in the RequestContext constructor.
One gets the impression match() is supposed to be called multiple times with different paths within one request, which I can't imagine would ever happen.
After integrating the Routing Component into my application, I now have a hunch why
it was done like that.
Most of the properties of the RequestContext - method, request body, get parameters - can be used without modification, but depending on the desired path structure and server configuration (rewrite rules, etc.) there are multiple ways in which the path needs to be preprocessed.
This doesn't explain why the path is passed to the match() function and the request object is passed to the constructor, but it does explain why they are passed in separately.

Laravel 5 - calling $request->path() in middleware causing Laravel to ignore changes made to the request URI?

Using Laravel 5.2, and using a middleware, I need to remove a certain part from the URI of the request before it gets dispatched. More specifically, in a url like "http://somewebsite.com/en/company/about", I want to remove the "/en/" part from it.
This is the way I am doing it:
...
class LanguageMiddleware
{
public function handle($request, Closure $next)
{
//echo("ORIGINAL PATH: " . $request->path()); //notice this line
//duplicate the request
$dupRequest = $request->duplicate();
//get the language part
$lang = $dupRequest->segment(1);
//set the lang in the session
$_SESSION['lang'] = $lang;
//now remove the language part from the URI
$newpath = str_replace($lang, '', $dupRequest->path());
//set the new URI
$request->server->set('REQUEST_URI', $newpath);
echo("FINAL PATH: " . $request->path());
echo("LANGUAGE: " . $lang);
$response = $next($request);
return $response;
}//end function
}//end class
This code is working fine - when the original URI is "en/company/about", the resulting URI is indeed "company/about". My issue is this: notice that the line where I echo the ORIGINAL PATH is commented (line 8). This is done on purpose. If I uncomment this line, the code is not working; when the original URI is "en/company/about", the resulting URI is still "en/company/about".
I can only reach two conclusions from this: Either sending output before manipulating the request is somehow the culprit (tested - this is not the case), or calling the $request->path() method to get the URI has something to do with this. Although in production I will never need to echo the URI of course, and while this is only for debugging purposes, I still need to know why this is happening. I only want to get the URI of the request. What am I missing here?
Sidenote: The code originated from the first answer to this post:
https://laracasts.com/discuss/channels/general-discussion/l5-whats-the-proper-way-to-create-new-request-in-middleware?page=1
I don't think that line#8 is manipulating your output.
Here is the path() method from laravel's code:
public function path()
{
$pattern = trim($this->getPathInfo(), '/');
return $pattern == '' ? '/' : $pattern;
}
As you can see it is just extracting the pathInfo without editing the request itself.

Passing "\" and "/" in variable via Laravel Route

First off, apologies if this is a bad question/practice. I'm very new to Laravel, so I'm still getting to grips with it.
I'm attempting to pass a variable that contains forward slashes (/) and backwards slashes () in a Laravel 5 route and I'm having some difficulties.
I'm using the following: api.dev/api/v1/service/DfDte\/uM5fy582WtmkFLJg==.
Attempt 1:
My first attempt used the following code and naturally resulted in a 404.
Route:
Route::group(array('prefix' => 'api/v1'), function() {
Route::resource('service', 'ServiceController');
});
Controller:
public function show($service) {
return $service;
}
Result:
404
Attempt 2:
I did a bit of searching on StackOverflow and ended up using the following code, which almost works, however, it appears to be converting \ to /.
Route:
Route::group(array('prefix' => 'api/v1'), function() {
Route::get('service/{slashData}', 'ServiceController#getData')
->where('slashData', '(.*)');
});
Controller:
public function getData($slashData = null) {
if($slashData) {
return $slashData;
}
}
Result:
DfDte//uM5fy582WtmkFLJg==
As you can see, it's passing the var but appears to be converting the \ to /.
I'm attempting to create an API and unfortunately the variable I'm passing is out of my control (e.g. I can't simply not use \ or /).
Does anyone have any advice or could point me in the right direction?
Thanks.
As you can see from the comments on the original question, the variable I was trying to pass in the URL was the result of a prior API call which I was using json_encode on. json_encode will automatically try and escape forward slashes, hence the additional \ being added to the variable. I added a JSON_UNESCAPED_SLASHES flag to the original call and voila, everything is working as expected.
You should not do that. Laravel will think it is a new parameter, because of the "/". Instead, use htmlentitites and html_entity_decode in your parameter, or use POST.

Route parameters are URL-encoded

I'm trying out Lumen and I've written my first route:
$app->get('hello/{name}', function ($name) {
return "Hello, $name!";
});
The documentation I've read so far doesn't say a word about how the framework approaches HTML-injection so I made a quick test:
http://example.com/hello/<u>café
... which showed up like this:
Hello, %3Cu%3Ecaf%C3%A9!
In other words, route parameters are not URL-decoded when they reach my function. Other frameworks I've tried decode everything for you, just as if you were reading from $_GET.
Is there an issue with my set-up (Apache/2.4, mod_php and mod_rewrite with the default .htaccess bundled with the framework) or that's the expected input?
It's an intentional bug/feature (see Route parameters are URL-encoded #238 for reference). No idea about the rationale behind the design decision.

Symfony2 cache and parameters

I have an odd app set up, multiple sub domains all pointing to the same Symfony2 install.
The subdomain simply changes a single parameter within the application so that different content is loaded.
This parameter is being cached however, so visiting a.site.com and then b.site.com makes A's content appear rather than B's.
Is there another approach I can use?
Is there a way I can add this parameter the cache's hash or something similar so that when the parameter changes within the app the content can change.
I am using this method to pass the constant from the sub domain into the Symfony2 application
How to pass a PHP constant as service argument in Symfony 2?
You can use Symfony's Request Object to get the URL and parse that for the subdomain. Use that to create your configuration parameter because it won't be cached.
Like this:
echo $request->getUri();
Symfony's API can be a great resource, but a bit hard to read. http://api.symfony.com/2.6/Symfony/Component/HttpFoundation/Request.html
I ended up writing a service to parse the host name, that service was then available within my Controllers.
class GameSystem {
public function getGameSystemName()
{
$ar = explode(".", $_SERVER['HTTP_HOST']);
$first = reset($ar);
$game_system_short_name = strtolower($first);
return $game_system_short_name;
}
}
Initially I had tried to use the constant value set in each subdomain's index file. But this was failing and having some really odd effects.

Categories