tl;dr My Yii 2 app, running as a micro-framework, works just fine when using standard ("not pretty") URLs. However when the urlManager application component is enabled in the configuration, the entire application breaks completely and every call to it ends with 404.
Following my other question, I am trying to run a minimalist version (micro framework) of Yii 2 app to act as an RESTful endpoint. I've followed the guide and everything seems to be working when I am calling a standard ("not pretty") URLs:
As suggested in the guide, I have enabled routing / pretty URLs in my application:
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => 'post'],
],
]
And suddenly my application stops working at all. It serves neither non-pretty:
nor pretty URLs:
It even fails to serve the default controller and action -- site/index.
What am I missing?
It seems that I have everything that I need. Following the guide I have:
Created the micro-framework application skeleton
Created default controller (site) and default action (index)
Configured db component, run migrations and created database
Created PostController
Enabled routing by adding Yii code to application configuration (see code example above) and by creating corresponding .httaccess file:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]
What else must I do in order to make the whole thing work or what am I missing here? Thanks!
Remove this line:
'enableStrictParsing' => true,
This question comes from an misunderstanding. I wasn't aware that when pretty URLs are enabled then yii\rest\UrlRule::$pluralize is set to true by default. Meaning that the request must be:
http://localhost/micro-app/posts
(plural controller name; notice "s" at the end)
Not:
http://localhost/micro-app/post
(singular controller name)
It is also completely normal that when pretty URLs are enabled then regular URLs doesn't work anymore. That's the reason for getting 404 File Not Found on http://localhost/micro-app/index.php?r=post URL when pretty URLs are enabled.
I am using Laravel sanctum in my project with angular as frontend. Getting unauthenticated from the second api request. Please let me know where am I going wrong
Frontend-> 127.0.0.1:4200
Backend-> localhost:8888
.env config
SESSION_DOMAIN=localhost
SANCTUM_STATEFUL_DOMAINS=127.0.0.1
Added middleware auth:sanctum to the routes group in api.php
Ref: https://prnt.sc/rm9ejy
For anyone having an Unauthenticated error, please ensure you follow these steps.
Send a GET request to /sanctum/csrf-cookie
Send a post request to web route /login to get authenticated
After this step, you will be successfully authenticated by auth:sanctum middleware in the WEB route or any resource route that needs CRSF token present.
[Why did this work]
Sending a GET request(empty request) to /sanctum/csrf-cookie enables laravel to send the fresh set cookies command to your browser to set a fresh CRSF token which can be found in your cookies. Axios and most library send this fresh token as part of headers X-CSRF-TOKEN by default, for regular ajax request, please include them explicitly in your headers or in form _token, else your SPA will still hit the 419(token expired) error
Other things to be aware of:
Ensure your SESSION_DOMAIN is set to localhost
SANCTUM_STATEFUL_DOMAIN is set to your sub domain/SPA with the port e.g localhost:8000
For the original question please ensure you maintain same domain. I mean use localhost for both. And set SANCTUM_STATEFUL_DOMAIN = localhost:4200
Edited
Also set SESSION_DRIVER
Add your domains, for example
my API is running on localhost:8000 my client is running on localhost:3000 so my env setting looks like below
SANCTUM_STATEFUL_DOMAINS=localhost:8000,localhost:3000
also, add your session domain
SESSION_DOMAIN=localhost
Have you checked your Kernel.php? app/Http/Kernel.php
Make sure you uncomment \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, coz by default it is being commented
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
Two days of pain and despair to arrive at this conclusion: the Bearer token was not attached to the request, and that was because of my .htaccess configuration.
If you, like me, are not able to authenticate via API token, try to add this line on your .htaccess file in the public directory in your Laravel project:
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
Right after RewriteEngine On directive.
CREDITS: Laravel not detecting auth token sent in the header and JWT package
From the screenshot you shared I see your domain is localhost and not 127.0.01, just do:
SANCTUM_STATEFUL_DOMAINS=localhost
For anyone using Laravel Homestead, use your actual domain.
SANCTUM_STATEFUL_DOMAINS=homestead.test
Which version are you running? Since V2.4.0 you need to specify the port:
SANCTUM_STATEFUL_DOMAINS=localhost:4200
See this issue for more info.
The sanctum stateful domains require the port number as well.
e.g. SANCTUM_STATEFUL_DOMAINS=127.0.0.1:4200
Although in your case your screenshot shows it should be SANCTUM_STATEFUL_DOMAINS=127.0.0.1:4201
Late in the game but just to help those that keep looking for this solution, most of the answers here have some truth, just have to put them together to make it work:
ENV file: SESSION_DOMAIN=localhost (or whatever your domains is)
in config->sanctum.php->stateful (if not already there): Sanctum::currentApplicationUrlWithPort()
in app/Http/Kernel.php API add as very first (this is important) : \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
in app/http/kernel API remove if there: \Illuminate\Session\Middleware\StartSession::class,
add to your api routes middleware: auth:sanctum
Also worth checking the guard settings under config->sanctum.php
that should do.
I had the same solution as Marco, adding the rewrite rule to my htaccess in public fixed it.
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
FYI I am hosting this on Auzre Web App Service (linux), if anyone else is doing that.
check if you had changed your guard in past. goto config/auth.php check if your provider model is same as your user model (or the model you using) for authentication.
in my case i was using different guard and provider.
In case you have problems when going into production and/or have more than one subdomains and also use https don't forget that the port is 443 instead of the usual 80.
E.g.:
SANCTUM_STATEFUL_DOMAINS=*.example.com:443
SESSION_DOMAIN=.example.com
Lost days trying to figure out why the laravel, the spa or the android app were taking turns to fail, but never working all at the same time, until found that solution.
This worked for me. The solution is adding this to .htaccess of root folder (not only inside the public folder)
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
I have a problem redirecting 404 errors to custom template.
My site structure is: project folder containing laravel and angularjs folders:
-> Project
-> AngularTheme
-> Laravel
In my .htaccess I have redirected the requests coming from / to /AngularTheme/index.php which is working fine.
RewriteRule ^(/)?$ ./AngularTheme/index.php [L]
Now, when anyone type in anything after the / i.e /foo it throws 404 not found error to which I am not being able to handle.
Inside laravel and Angular, there is not any problem redirecting to custome page.
Thanks for any help.
I would stick to what you know to do this.
here's a guide to do custom 404 handling in laravel
Though you can also play around in angular with routing to go to a specific page in certain cases.
I am trying to enable clean urls with Angular JS inside my Laravel 4 app. When I tried the required thing normally without laravel 4 refering to this url.
http://www.yearofmoo.com/2012/11/angularjs-and-seo.html, I was able to get the thing to work. Even ?_escaped_fragment_= was changed to snapshot/* folder and picked the content.
But I am not able to do the same in Laravel 4. I am not sure how to do this.
I am trying to define a route like ?_escaped_fragment_=/* and redirect it to some controller but that doesn't work.
Can anyone please help.
Escaped fragment is a query parameter, not a route, there for, in the root route Route::get('/', 'RootCtrl');, you can check for $_GET['_escaped_fragment'] presence, and if it is there, return an HTTP 302 redirect to the corresponding file in the snapshots dir.
While this will work, it is not the perfect solution, since some bots might index the path of the snapshots file instead of the original one, and since doing it using the Laravel framework is not correct in the first place.
The best choice of course, is to rewrite any request that contains an _escaped_fragment_
query parameter to it's corresponding path, in the nginx\apache configuration, prior to the configuration of your Laravel app, this way those requests won't event reach the Laravel router.
I have co-authored an Angular SEO plug-and-play solution, using PhantomJS & Mongoose integrated web server, to pre-render any Async JS code, and server it as raw HTML.
The server configuration aspects are also explained in the README.md file, please note that if you would like to use static snapshots, just change proxy-pass to rewrite(in order for the right URL to get indexed by the bots).
Hope that helps.
Example using simple rewrites with nginx:
if ($args ~* "^_escaped_fragment_=(.+)") {
set $path $1
set $args '';
rewrite ^.*$ /snapshots/$path last;
}
EDIT:
Apache, for your request (some words of advice: move to nginx).
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{QUERY_STRING} ^_escaped_fragment=(.+)$
RewriteRule ^.*$ /snapshots/%1 [QSA,L]
</IfModule>
I have a Slim application with following structure
project_root/
index.php
Slim
Client
index.html
scripts
styles
partials
I need to do the following:
Slim/PHP application should act as a rest server that responds in json for urls starting with /apis
Other urls should be redirected to Client and resources viz. styles,scripts should be served statically.
Client application is an independent application. (in this case an angular application)
index.php contents are like
$app = new \Slim\Slim();
$app->add(new \Slim\Middleware\ContentTypes());
// Routes
$app->get('/apis/register',function(){
echo "apis/register";
});
The following route renders index.html page. initial page of my angular application.
But styles and scripts are not getting served.
I get 404 Not Found for styles and scripts.
$app->get('/:route',function($route) use ($app) {
$app->config('templates.path', './Client/');
$app->render('index.html');
})->conditions(array("route" => "(index|style)"));
How can i host styles and scripts that are used by client application?
May be through some Slim route(preferred) or through apache configuration
In rails we can write following routes.
match "/styles" => redirect("/")
match "/partials" => redirect("/")
EDIT:
Looks like /* is not yet supported in Slim or its missed in documentation.
Like in node.js we do,
{
path: '/*',
httpMethod: 'GET',
middleware: [function(req, res) {
res.render('index');
}]
}
It seems that Slim has some kind of bug for redirecting to non-existing sub directory .htacess rewrites. I had a similar problem. I actually created the sub-directory and made the .htaccess to direct all API calls to specific sub directory and avoid App directory.
Have a look at this. It eventually solved my problem.
UPDATE: have a look at this at the Slim Help Thread. They had this issue indeed.
You can use these instructions (Apache Module mod_rewrite) in your .htaccess file to only send non-existing files to Slim.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]