Match last URL param including slashes in Koa router - koa

I use koa-router, and would like to match part of the URL (potentially) including slashes. For instance, everything that matches /foo/xxx, /foo/yyy, /foo/dir/xxx, and /foo/a/b/c/d.
Something like the following, if *path meant the same as ":path but including slashes":
router.get('/foo/*path', async (ctx) => {
console.log(`PATH: ${ctx.params.path}`);
});
Being able to say "catch everything starting with /foo/" would work as well.
I am stuck here, I don't find any way for koa-router to allow me to do this.

I found the answer in one of koa's github issue. You need to simply create your router as follows:
router.get('/foo/:splat*', async (ctx) => {
// do what you want
});

Related

Laravel Catch Any Route with Prefix?

So currently in my Laravel app I've got the route;
Route::get('/{any}', 'SinglePageController#index')->where('any', '.*');
And in this state, it works. However I want to add a prefix to it such as /app/{any} and for it to be inclusive of app as well. So /app would still go to SinglePageController.
I've tried doing something like that and it works for everything except the /app route itself.
Hopefully someone can provide some suggestions.
Try this:
Route::group(["prefix" => "app"], function(){
Route::get('/{any?}', 'SinglePageController#index');
}
I converted the any parameter to optional, so it can go to SinglePageController#index when it's not given too.
Also you may define the parameter of the index method as optional too. Like:
public function index($any = null){

How to config Laravel Router some route rule work on different path?

I deployed my Laravel 5 project on A.com, I also want put it under B.com/a. For some reason, the /a path I should handle it in router.
So in router I write:
Route::get('post','PostController#index');
Route::get('a/post','PostController#index');
It's not a good way because there is redundancy, especially there are a lot of other route rules.
In the doc, there is only {xx}? to handle optional param, but in my project, it's not param instead of a static string.
It's there any better way to combine two lines?
I'd use a route prefix within a foreach loop. That'd allow you to quickly and easily manage the prefixes on your routes while keeping them all in one place.
foreach([null, 'a'] as $prefix) {
Route::group(['prefix' => $prefix], function () {
// Your routes here
});
}
The routes not prefixed will take precedence as their routes would be generated first in this case. You could just as easily swap the array around if necessary.
If you really wanted to do it in a single route definition you could do it using a regular expression to match the route.
Route::get('{route}', function () {
dd('Browsing ' . app('request')->path());
})->where('route', '(a/)?post');
But it's clearly not very clean/readable so probably not recommended.
You can do this:
RealRoutes.php:
Route::get('post','PostController#index');
// ... include all of your other routes here
routes.php:
include('RealRoutes.php');
Route::group(['prefix' => 'a/'], function () {
include('RealRoutes.php');
});
There's probably a better way to solve this using a lambda function or similar but the above should work as a quick solution.

Laravel passing all routes for a particular domain to a controller

Working on a Laravel 4.2 project. What I am trying to accomplish is pass every URI pattern to a controller that I can then go to the database and see if I need to redirect this URL (I know I can do this simple in PHP and do not need to go through Laravel, but just trying to use this as a learning experience.)
So what I have at the moment is this:
Route::group(array('domain' => 'sub.domain.com'), function()
{
Route::get('?', 'RedirectController#index');
});
I am routing any subdomain which I deem as a "redirect subdomain" ... The ? is where I am having the problem. From what I have read you should be able to use "*" for anything but that does not seem to be working. Anyone have a clue how to pass any URL to a controller?
And on top of that I would ideally like to pass the FULL URL so i can easily just check the DB and redirect so:
$url = URL::full();
Try this:
Route::group(array('domain' => 'sub.domain.com'), function()
{
Route::get('{path}', 'RedirectController#index')
->where('path', '.*');
});
And your controller will reseive the path as first argument
public function index($path){
// ...
}
In case you're wondering, the where is needed because without it {path} will only match the path until the first /. This way all characters, even /, are allowed as route parameter

Laravel routing & filters

I want to build fancy url in my site with these url patterns:
http://domain.com/specialization/eye
http://domain.com/clinic-dr-house
http://domain.com/faq
The first url has a simple route pattern:
Route::get('/specialization/{slug}', 'FrontController#specialization');
The second and the third url refers to two different controller actions:
SiteController#clinic
SiteController#page
I try with this filter:
Route::filter('/{slug}',function()
{
if(Clinic::where('slug',$slug)->count() == 1)
Route::get('/{slug}','FrontController#clinic');
if(Page::where('slug',$slug)->count() == 1)
Route::get('/{slug}','FrontController#page');
});
And I have an Exception... there is a less painful method?
To declare a filter you should use a filter a static name, for example:
Route::filter('filtername',function()
{
// ...
});
Then you may use this filter in your routes like this way:
Route::get('/specialization/{slug}', array('before' => 'filtername', 'uses' => 'FrontController#specialization'));
So, whenever you use http://domain.com/specialization/eye the filter attached to this route will be executed before the route is dispatched. Read more on documentation.
Update: For second and third routes you may check the route parameter in thew filter and do different things depending on the parameter. Also, you may use one method for both urls, technically both urls are identical to one route so use one route and depending on the param, do different things, for example you have following urls:
http://domain.com/clinic-dr-house
http://domain.com/faq
Use a single route for both url, for example, use:
Route::get('/{param}', 'FrontController#common');
Create common method in your FrontController like this:
public function common($param)
{
// Check the param, if param is clinic-dr-house
// the do something or do something else for faq
// or you may use redirect as well
}

How to Remove/Register Suffix on Laravel Route?

EDIT: See below for my current problem. The top portion is a previous issue that I've solved but is somewhat related
I need to modify the input values passed to my controller before it actually gets there. I am building a web app that I want to be able to support multiple request input types (JSON and XML initially). I want to be able to catch the input BEFORE it goes to my restful controller, and modify it into an appropriate StdClass object.
I can't, for the life of me, figure out how to intercept and modify that input. Help?
For example, I'd like to be able to have filters like this:
Route::filter('json', function()
{
//modify input here into common PHP object format
});
Route::filter('xml', function()
{
//modify input here into common PHP object format
});
Route::filter('other', function()
{
//modify input here into common PHP object format
});
Route::when('*.json', 'json'); //Any route with '.json' appended uses json filter
Route::when('*.xml', 'xml'); //Any route with '.json' appended uses json filter
Route::when('*.other', 'other'); //Any route with '.json' appended uses json filter
Right now I'm simply doing a Input::isJson() check in my controller function, followed by the code below - note that this is a bit of a simplification of my code.
$data = Input::all();
$objs = array();
foreach($data as $key => $content)
{
$objs[$key] = json_decode($content);
}
EDIT: I've actually solved this, but have another issue now. Here's how I solved it:
Route::filter('json', function()
{
$new_input = array();
if (Input::isJson())
{
foreach(Input::all() as $key => $content)
{
//Do any input modification needed here
//Save it in $new_input
}
Input::replace($new_input);
}
else
{
return "Input provided was not JSON";
}
});
Route::when('*.json', 'json'); //Any route with '.json' appended uses json filter
The issue I have now is this: The path that the Router attempts to go to after the filter, contains .json from the input URI. The only option I've seen for solving this is to replace Input::replace($new_input) with
$new_path = str_replace('.json', '', Request::path());
Redirect::to($new_path)->withInput($new_input);
This however leads to 2 issues. Firstly I can't get it to redirect with a POST request - it's always a GET request. Second, the data being passed in is being flashed to the session - I'd rather have it available via the Input class as it would be with Input::replace().
Any suggestions on how to solve this?
I managed to solve the second issue as well - but it involved a lot of extra work and poking around... I'm not sure if it's the best solution, but it allows for suffixing routes similar to how you would prefix them.
Here's the github commit for how I solved it:
https://github.com/pcockwell/AuToDo/commit/dd269e756156f1e316825f4da3bfdd6930bd2e85
In particular, you should be looking at:
app/config/app.php
app/lib/autodo/src/Autodo/Routing/RouteCompiler.php
app/lib/autodo/src/Autodo/Routing/Router.php
app/lib/autodo/src/Autodo/Routing/RoutingServiceProvider.php
app/routes.php
composer.json
After making these modifications, I needed to run composer dumpautoload and php artisan optimize. The rest of those files are just validation for my data models and the result of running those 2 commands.
I didn't split the commit up because I'd been working on it for several hours and just wanted it in.
I'm going to hopefully look to extend the suffix tool to allow an array of suffixes so that any match will proceed. For example,
Route::group(array('suffix' => array('.json', '.xml', 'some_other_url_suffix')), function()
{
// Controller for base API function.
Route::controller('api', 'ApiController');
});
And this would ideally accept any call matching
{base_url}/api/{method}{/{v1?}/{v2?}/{v3?}/{v4?}/{v5?}?}{suffix}`
Where:
base_url is the domain base url
method is a function defined in ApiController
{/{v1?}/{v2?}/{v3?}/{v4?}/{v5?}?} is a series of up to 5 optional variables as are added when registering a controller with Route::controller()
suffix is one of the values in the suffix array passed to Route::group()
This example in particular should accept all of the following (assuming localhost is the base url, and the methods available are getMethod1($str1 = null, $str2 = null) and postMethod2()):
GET request to localhost/api/method1.json
GET request to localhost/api/method1.xml
GET request to localhost/api/method1some_other_url_suffix
POST request to localhost/api/method2.json
POST request to localhost/api/method2.xml
POST request to localhost/api/method2some_other_url_suffix
GET request to localhost/api/method1/hello/world.json
GET request to localhost/api/method1/hello/world.xml
GET request to localhost/api/method1/hello/worldsome_other_url_suffix
The last three requests would pass $str1 = 'hello' and $str2 = 'world' to getMethod1 as parameters.
EDIT: The changes to allow multiple suffixes was fairly easy. Commit located below (please make sure you get BOTH commit changes to get this working):
https://github.com/pcockwell/AuToDo/commit/864187981a436b60868aa420f7d212aaff1d3dfe
Eventually, I'm also hoping to submit this to the laravel/framework project.

Resources