subdomain grouping misses slash in laravel - php

I am trying to write a simple REST API backend that resides on
http://api.stan.test/.
Got laravel/framework:v7.21.0 and PHP:7.2.30.
Can't get the route matched.
The problem:
when I am accessing the http://api.stan.test/api/t.json URL
With api.stan.test string as domain group, my route in \Illuminate\Routing\RouteCollection::match is compared to api.stan.testapi/user alias and route is not found obviously.
With api.stan.test/ string as domain group, my route in \Illuminate\Routing\RouteCollection::match is compared against api.stan.test/api/user alias, match is found but it fails domain validation in \Illuminate\Routing\Route::matches.
preg_match($hostRegex, $request->getHost()) fails because
preg_match("{^api\.stan\.test/$}sDiu", "api.stan.test") are the values.
This is my RouteServiceProvider
# \App\Providers\RouteServiceProvider::mapApiRoutes
Route::domain('api.stan.test')
->prefix('/api')
->middleware('api')
->namespace($this->namespace)
->group(base_path('routes/api.php'));
and here is included routes file
# routes/api.php
Route::get('t.json','TController#api');

In Laravel, route parameters matching uses Symfony's Route compiler. Actually route compiler was finding dot (.) as a segment separator. This is the reason why in your case it cannot find the route.
You can do something like this :
Route::get('t_json','TController#api');

Related

Optional parameter for prefix in Laravel

I'm trying to add an optional parameter in Laravel for group routes using prefix, but it doesn't work.
In the Laravel documentation I see:
Make sure to give the route's corresponding variable a default value
But how do I do it for prefixes? I see example only for a special route, but I need it for a group of routes.
I use Laravel 8.0.
There may or may not be space here, but it only works when there is space.
Route::middleware('api')
->prefix('v1/{space?}/')
->namespace($this->namespace)
->group(__DIR__ . '/../api.php');

Wildcard first pathame only in Lumen route

Is it possible to wildcard only the first pathname of a route in lumen / laravel? A type of wildcard like this would only work for routes that do not have a proceeding forward slash, for example:
The route path: /purple or /green would match the wildcard but if the route was prefixed, like /purple/green or proceeded with a forward slash, like /purple/ it would not match the wildcard route.
Currently I am using this wildcard which is matching all routes in the application and conflicting with prefixed and post routes:
$router->get('[{name}]', function () use ($router) {
return view('index');
});
From my understanding this can be achieved with Regular Expression matching in Lumen, but how I'm not sure.

Laravel route not matching pattern

In my Laravel routes/web.php file I have defined the following two routes:
Route::get('transaction/{id}', ['uses' => 'PaynlTransactionController#show'])->name('transaction.show');
Route::get('transaction/{txId}', ['uses' => 'PaynlTransactionController#showByTxId'])->name('transaction.showByTxId');
In my RouteServicesProvider I have defined the following two patterns:
Route::pattern('id', '[0-9]+');
Route::pattern('txId', '/^(TX(1[0-9]\d|[2-9]\d\d)-(1[0-9]\d\d\d\d|[2-9]\d\d\d\d\d))$/');
Whenever I go to transaction/<id> the routing works correctly, as long as id is an integer. However, when I go to transaction/TX874-152268, for example, it doesn't match any route and I receive the NotFoundHttpException in RouteCollection.php error.
I've validated the txId regex and it gives a full match: https://regex101.com/r/kDZR4L/1
My question: how come only my id pattern is working correctly, whereas my txId pattern isn't?
In the route
Route::pattern('txId', '/^(TX(1[0-9]\d|[2-9]\d\d)-(1[0-9]\d\d\d\d|[2-9]\d\d\d\d\d))$/');
I had included the forward slashes at the start and end of the string. This should not be included when passing a pattern to Route::pattern. Thus the following works:
Route::pattern('txId', '^(TX(1[0-9]\d|[2-9]\d\d)-(1[0-9]\d\d\d\d|[2-9]\d\d\d\d\d))$');
Because the urls are both /transaction/{value} it will get the last on.
If you change /transaction/{txId} to /transaction/tx/{txId} it will be clear for the routes.
Routes can only get one, so when you assign the prefix (at this time /transaction) to both of the urls it doesn't work.
You can also use /transaction/TX{txId}, in your controller you can past TX before the txId variable.
public function showByTxId($txId) {
$txid = "TX".$txid;
}
Edit:
Remove the / add the start.
Route::pattern('txId', '^(TX(1[0-9]\d|[2-9]\d\d)-(1[0-9]\d\d\d\d|[2-9]\d\d\d\d\d))$');
Hope this works!

Laravel 4 only root route works - other routes return 'Controller method not found'

I've got laravel set up on a domain on a linux host and I have a WAMP local host set up.
The only route that works is the root, when ever I try go to another route such as domain.com/account I get a "Controller method not found." error.
In my routes.php file I have:
Route::controller('','LoginController');
Route::controller('account', 'AccountController');
In my LoginController, I have just two methods. getIndex and postIndex.
After a couple of hours Googling with no results and playing around with the routes file amongst things, still nothing worked.
I tried adding the below route which didn't work either.
Route::any('hello', function(){
return 'hello!';
});
However, I then commented out my Route::controller('','LoginController'); line and the other routes started working!
I then changed it to Route::controller('login','LoginController'); and this and the other routes still worked. I then changed it to Route::any('','LoginController#getIndex'); and the root and other routes still worked. However, doing it this way, when I cliked the login button on my page nothing happened.
So my question really is, is there something wrong with doing Route::controller('','LoginController');? As everything else seems to 'work'
Laravel save an internal collection of registered routes in the $routes member of the Router class. When dispatching a request, a process of picking each element from this collection and test with current request will be executed to find out which route will be handle. This process is affected by the order of your route registering statements.
When testing each route with the current request, the picked route will be compiled and have a regex pattern. This pattern will be use to check with the current URI by the preg_match function as you can see at this line in Laravel source.
When using Route::controller a special route will be add to your routes collection. If your input is Route::controller($uri, $controller) then this special routes will have a regex pattern as ^/$uri/?P<_missing>(.*)$ and it tells Laravel that this request belong to a missing method of the $controller controller class.
In your case, you have set the value of $uri to an empty string which cause the regex of the special route to be ^/?P<_missing>(.*)$ (setting $uri with the string / cause the same effect). Well, this regex will match every URI. So, the internal route looking up process will abort when look to this special route. This is the reason while the exception has been thrown.
You should not use an empty string or the/ string when register with the Route::controller method like the way you did. Instead, use Route::resource or explicit calls (Route::get, Route::post, ...) to handle your top level routes.
I have not tried that, but maybe you could add a "/":
Route::controller('/','LoginController');
Edit
I was able to reproduce the issue and I solved by changing the order of your route lines:
Route::controller('accounts', 'AccountController');
Route::controller('','LoginController');

Phalcon routing behaviour - redundant routes?

I'm working with the following routing example:
https://github.com/phalcon/mvc/blob/master/simple-subcontrollers/app/config/routes.php
Can anyone explain to me why on line 12 there is this:
$router->add('/:controller', array(...
Haven't we already defined the route on line 5 as:
$router->add('/:controller/:action/:params', array(
"/:controller" is a subset of '/:controller/:action/:params'.
If you remove "/:controller" route, URLs ending with controller name will not be matched.
Why isn't router falling back to default action name that I can indicate as:
$router->setDefaultAction('index');
Is this a bug or a feature?
Thanks!
This route
$router->add('/:controller/:action/:params', array(
Will only execute if it gets all parts to make the route valid for example
myapp/users/logout/dave
The above will match what that route is looking for and cause the route to execute.
myapp/users
The above however wouldn't match due to missing actions and params also a url with a / and without aren't the same url.
Since you can add many routes as you need using add(), the order in which routes are added indicate their relevance, lastest routes added have more relevance than first added. Internally, all defined routes are traversed in reverse order until Phalcon\Mvc\Router finds the one that matches the given URI and processes it, while ignoring the rest.
Hope this helps.

Categories