Slim Framework throws 405 Not Found Error on every request - slim-4

I am trying to build Slim Framework Version 4 api, for my angular application.
On every request i make, i get
Type: Slim\Exception\HttpMethodNotAllowedException
Code: 405
Message: Method not allowed. Must be one of: POST
File: G:\xampp\htdocs\slim\vendor\slim\slim\Slim\Middleware\RoutingMiddleware.php
Line: 96
Trace: #0 G:\xampp\htdocs\slim\vendor\slim\slim\Slim\Routing\RouteRunner.php(72): Slim\Middleware\RoutingMiddleware->performRouting(Object(Slim\Psr7\Request))
#1 G:\xampp\htdocs\slim\vendor\slim\slim\Slim\Middleware\ErrorMiddleware.php(98): Slim\Routing\RouteRunner->handle(Object(Slim\Psr7\Request))
#2 G:\xampp\htdocs\slim\vendor\slim\slim\Slim\MiddlewareDispatcher.php(140): Slim\Middleware\ErrorMiddleware->process(Object(Slim\Psr7\Request), Object(Slim\Routing\RouteRunner))
#3 G:\xampp\htdocs\slim\app\Middlewares\RequestUser.php(19): class#anonymous->handle(Object(Slim\Psr7\Request))
#4 G:\xampp\htdocs\slim\vendor\slim\slim\Slim\MiddlewareDispatcher.php(283): App\Middlewares\RequestUser->__invoke(Object(Slim\Psr7\Request), Object(class#anonymous))
#5 G:\xampp\htdocs\slim\vendor\slim\slim\Slim\MiddlewareDispatcher.php(81): class#anonymous->handle(Object(Slim\Psr7\Request))
#6 G:\xampp\htdocs\slim\vendor\slim\slim\Slim\App.php(211): Slim\MiddlewareDispatcher->handle(Object(Slim\Psr7\Request))
#7 G:\xampp\htdocs\slim\vendor\slim\slim\Slim\App.php(195): Slim\App->handle(Object(Slim\Psr7\Request))
#8 G:\xampp\htdocs\slim\public\index.php(42): Slim\App->run()
#9 {main}
[Tue Feb 18 11:38:13 2020] ::1:57190 [200]: /login
[Tue Feb 18 11:38:14 2020] ::1:57191 [200]: /login
The good part is my api is working fine as expected. But I get to see this error on every call.
How can i overcome this.
If i try a get call from my browser, then there is no error.
If i make an ajax call, the Network tab shows no error
But my command prompt throws this error
Edit 1
Adding route definitions
$app->get('/', '\App\Controllers\HomeController:home');
$app->post('/login', '\App\Controllers\UserController:login');
Edit 2
Adding angular code
login(data){
const url = environment.api+'login';
return this.http.post(url, data);
}
Answer
i need to add
$app->options('/{routes:.+}', function ($request, $response, $args) {
return $response;
});
in my index.php to accept all Options request
http://www.slimframework.com/docs/v4/cookbook/enable-cors.html

I had the same error for POST request ( not for GET ) caused by CORS.
I added route ( config/routes.php ):
// Post that cause an error
$app->post('/notes', NoteCreateAction::class);
// Allow preflight requests for /notes
$app->options('/notes', function (ServerRequestInterface $request, ResponseInterface $response): ResponseInterface {
return $response;
});
Solution was founded here: https://odan.github.io/2019/11/24/slim4-cors.html

There are two ways for deploy PHP-SLIM FRAMEWORK V4:
1. Run composer command:
>composer start
2. Deploy with apache server
a. In the file ‪C:\xampp\apache\conf\extra\httpd-vhosts.conf uncomment this config
NameVirtualHost *:80
b. In the file C:\xampp\apache\conf\extra\httpd-vhosts.conf put this config at finish
<VirtualHost *:80>
DocumentRoot C:\xampp\htdocs\myBackendServer
<Directory "C:\xampp\htdocs\myBackendServer">
Options FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
</Directory>
c. Finally, in the browser can you open:
http://localhost/

Related

Whoops! There was an error. NotFoundHttpException

I can see that Laravel is not able to get resources when the resource name includes a plus sign (+)
Symfony \ Component \ HttpKernel \ Exception \ NotFoundHttpException
GET http://localhost:8000/vendor/store/store+json2.min.js 404 (Not Found)
GET http://localhost:8000/vendor/animo/animate+animo.css 404 (Not Found)
REQUEST_URI /vendor/store/store+json2.min.js
REQUEST_METHOD GET
SCRIPT_NAME /vendor/store/store json2.min.js
REQUEST_URI /vendor/animo/animate+animo.css
REQUEST_METHOD GET
SCRIPT_NAME /vendor/animo/animate animo.css
I can solve that by changing the filename with removing the plus sign. But is there any way to do that without changing filename?
I am using Laravel 4.*
Here is the contents in the route file:
Route::get('/', function()
{
return View::make('hello');
});
// Confide routes
Route::get('users/create', 'UsersController#create');
Route::get('users/create/{plan}', 'UsersController#create');
Route::post('users', 'UsersController#store');
Route::get('users/login', 'UsersController#login');
Route::post('users/login', 'UsersController#doLogin');
Route::get('users/confirm/{code}', 'UsersController#confirm');
Route::get('users/forgot_password', 'UsersController#forgotPassword');
Route::post('users/forgot_password', 'UsersController#doForgotPassword');
Route::get('users/reset_password/{token}', 'UsersController#resetPassword');
Route::post('users/reset_password', 'UsersController#doResetPassword');
Route::get('users/logout', 'UsersController#logout');
Route::resource('categories', 'CategoriesController');
Route::resource('forms', 'FormsController');
Route::resource('submissions', 'SubmissionsController');
The actual problem is that for some reason the two rewrite conditions:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
Are not working correctly with your requests. They should prevent that file requests are proxied off to Laravel. It also seems to be environment related. (On my local server it worked perfectly fine)
A workaround that apparently works is replacing + with the URL encoded value %2B.
Or just use urlencode():
urlencode('http://localhost:8000/vendor/store/store+json2.min.js')

Cross domain session with Sinatra and AngularJS

I am using Sinatra as a webservice and angularjs to make the calls
post '/loginUser' do
session[:cui]=user['cui']
end
get '/cui' do
return session[:cui].to_s
end
But it doesn't seem to work (the '/cui' call returns an empty string) any help would be greatly apreciated.
UPDATE:
setting this in sinatra headers['Access-Control-Allow-Credentials'] = 'true' allows me to send the session, but it seems like $http directive is not using the browsers cookies
on the sinatra app
before do
headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS'
headers['Access-Control-Allow-Origin'] = 'http://localhost:4567'
headers['Access-Control-Allow-Headers'] = 'accept, authorization, origin'
headers['Access-Control-Allow-Credentials'] = 'true'
end
angularjs app
host='http://127.0.0.1:5445/'
#viewController = ($scope,$http)->
$scope.getCui = ()->
$http.get(host+'cui',{ withCredentials: true}).success (data)->
$scope.cui=data
console.log data
Explanation:
AngularJS uses his own cookie system, so we need to specify that we can pass the cookies trough the $http.get call using the {withCredentials:true} configuration object. Sinatra needs to accept the cross domain cookies so we need the headers mentioned above.
Note: 'Access-Control-Allow-Origin' header cannot be wildcard.
One option around this would be to configure a http server with a proxy pass, so you could hit the same domain without incurring a cross origin error. That way you can continue to properly maintain your abstractions as 2 separate apps.
Here is a brief example with nginx:
upstream angular_app {
server localhost:3003;
}
upstream sinatra_app {
server localhost:3004;
}
server {
listen 80;
server_name local.angular_app.com;
root /Users/username/source/angular_app/;
location / {
proxy_set_header Host $http_host;
proxy_redirect off;
}
location ~ ^/api/(.*)$ {
proxy_set_header Host $http_host;
proxy_read_timeout 1200;
proxy_pass http://sinatra_app/;
}
}
By routing at the server level, you can successfully bypass domain restrictions AND you can keep the applications separate.

Enable Debug Component in Symfony 2.3

Before opening a ticket in the symfony repository, I just wanted to check if I have missed something obvious.
I want to enable the debug component (for having these nice exception screens, etc..).
I just installed symfony using
composer create-project symfony/framework-standard-edition symfony 2.3.1
For testing purposes I added an exception to the WelcomeController:
class WelcomeController extends Controller
{
public function indexAction()
{
throw new \Exception("test");
/*
* The action's view can be rendered using render() method
* or #Template annotation as demonstrated in DemoController.
*
*/
return $this->render('AcmeDemoBundle:Welcome:index.html.twig');
}
}
Instead of showing me the (old) exception screen, I am just getting a 502 Bad Gateway from nginx.
app_dev.php:
//$loader = require_once __DIR__.'/../app/bootstrap.php.cache';
$loader = require_once __DIR__.'/../app/autoload.php';
Debug::enable(-1);
require_once __DIR__.'/../app/AppKernel.php';
$kernel = new AppKernel('dev', true);
//$kernel->loadClassCache();
Request::enableHttpMethodParameterOverride();
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);
Update:
Handling PHP errors does work however:
IDoNotExist();
produces the gray symfony error screen.
Ok, the problem was an error in the nginx config.
The error log of nginx revealed the following:
2013/07/03 14:33:05 [error] 22792#0: *15 upstream sent too big header while reading response header from upstream, client: 127.0.0.1, server: localhost, request: "GET /test/symfony_2.3.1/web/app_dev.php HTTP/1.1", upstream: "fastcgi://127.0.0.1:9111", host: "localhost"
I fixed it with adding
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
for the server {} in the nginx config (for reference http://forum.nginx.org/read.php?2,188352).
This first occured with 2.3.0, 2.2.3 works without this fix.
Ticket related to this issue: https://github.com/symfony/symfony/issues/8413

Google URL Shortening API using PHP

Now I know this is a common topic that has been over the Internet especially StackOverflow. But what I do not have (or haven't yet seen) is a straight solution for the token being maintained over a session.
I'm using the Google APIs Client Library for PHP .
My Query:
I have one index.php where I fetch the user data (such as name) using the Google_Oauth2Service from the PHP client lib. The user is authenticated successfully and all goes well. Now I'd like to use the URL Shortening service and therefore I have a shorten.php where I have the code to try fetch the short URL. Some how this doesn't work.
index.php
//include google api files
require_once 'src/Google_Client.php';
require_once 'src/contrib/Google_Oauth2Service.php';
require_once 'src/contrib/Google_UrlshortenerService.php';
//start session
session_start();
$gClient = new Google_Client();
$gClient->setApplicationName('Test App');
$gClient->setClientId($google_client_id);
$gClient->setClientSecret($google_client_secret);
$gClient->setRedirectUri($google_redirect_url);
$gClient->setDeveloperKey($google_developer_key);
$google_oauthV2 = new Google_Oauth2Service($gClient);
....
....
Here I have started the session and made an object of the Google_Client. I have declared the client id, secret and all other details.
Then I get the access token on successful authentication and store it in the Session variable so that when I try to fetch the short url (using jQuery ajax) from shorten.php, I can use the existing token.
$_SESSION['token'] = $gClient->getAccessToken();
....
Now in shorten.php
session_start();
require_once 'src/Google_Client.php';
require_once 'src/contrib/Google_Oauth2Service.php';
require_once 'src/contrib/Google_UrlshortenerService.php';
$gClient = new Google_Client();
$gClient->setApplicationName('Test App');
$gClient->setClientId($google_client_id);
$gClient->setClientSecret($google_client_secret);
$gClient->setRedirectUri($google_redirect_url);
$gClient->setDeveloperKey($google_developer_key);
....
if (isset($_SESSION['token']) && $_SESSION['token']) {
// Set the access token from the session
$gClient->setAccessToken($_SESSION['token']);
$url_service = new Google_UrlshortenerService($gClient);
// Check if a URL has been passed
if (isset($_GET['url'])) {
$url = new Google_Url();
$url->longUrl = $_GET['url'];
$shortURL = $url_service->url->insert($url);
....
This is the exact line where the code breaks $shortURL = $url_service->url->insert($url); I was successful in getting the token using the Session variable and created a successful URL Service object. But just when I call the insert method, that's when it fails.
From the apache error logs :
husain#innovate:~/myprojects/web$ tail -1 /var/log/apache2/error.log | sed -e 's/\\n/\n/g'
[Thu Mar 28 00:42:35 2013] [error] [client 127.0.0.1] PHP Fatal error: Uncaught exception 'Google_ServiceException' with message 'Error calling POST https://www.googleapis.com/urlshortener/v1/url?key=AIzaSyCxfXP-xS-QYJw-7mM4SNG3EW9ryj_Oiv4: (401) Invalid Credentials' in /home/husain/myprojects/web/apps/src/io/Google_REST.php:66
Stack trace:
#0 /home/husain/myprojects/web/apps/src/io/Google_REST.php(36): Google_REST::decodeHttpResponse(Object(Google_HttpRequest))
#1 /home/husain/myprojects/web/apps/src/service/Google_ServiceResource.php(177): Google_REST::execute(Object(Google_HttpRequest))
#2 /home/husain/myprojects/web/apps/src/contrib/Google_UrlshortenerService.php(38): Google_ServiceResource->__call('insert', Array)
#3 /home/husain/myprojects/web/apps/shorten.php(44): Google_UrlServiceResource->insert(Object(Google_Url))
#4 {main}
thrown in /home/husain/myprojects/web/apps/src/io/Google_REST.php on line 66
When I dump the Google_Client variables on the index.php and shorten.php files, this is what I get.
index.php
Google_Client Object
(
[scopes:protected] => Array
(
)
[useObjects:protected] =>
[services:protected] => Array
(
[oauth2] => Array
(
[scope] => Array
(
[0] => https://www.googleapis.com/auth/userinfo.profile
[1] => https://www.googleapis.com/auth/userinfo.email
)
)
)
[authenticated:Google_Client:private] =>
)
shorten.php
object(Google_Client)#1 (4) {
["scopes":protected]=>
array(0) {
}
["useObjects":protected]=>
bool(false)
["services":protected]=>
array(1) {
["urlshortener"]=>
array(1) {
["scope"]=>
string(44) "https://www.googleapis.com/auth/urlshortener"
}
}
["authenticated":"Google_Client":private]=>
bool(false)
}
and both aint the same so I'm assuming that there is something not right here. Help or direction please.
You're not requesting the UrlShortener scope when authenticating, that's why it's failing.
To get the scope added, you can create an UrlshortenerService before authenticating in index.php, passing the same instance of the client, as in:
//start session
session_start();
$gClient = new Google_Client();
$gClient->setApplicationName('Test App');
$gClient->setClientId($google_client_id);
$gClient->setClientSecret($google_client_secret);
$gClient->setRedirectUri($google_redirect_url);
$gClient->setDeveloperKey($google_developer_key);
$google_oauthV2 = new Google_Oauth2Service($gClient);
$url_service = new Google_UrlshortenerService($gClient);
Alternatively, you can use setScopes to override the automatically generated scope

sammy.js : camel case urls

How can I force sammy.js to recognize a url /Brief to be the same as /brief?
this.get('/brief', function(context) {
console.log("BRIEF");
});
I have my CMS setup to generate lower case urls, however if a user types in a url with a camel case format I get the error:
Tue Mar 19 2013 15:39:31 GMT+1100 (AUS Eastern Daylight Time)] body 404 Not Found get /Brief Error {message: "404 Not Found get /Brief "}
The page still loads fine, but Sammy.js won't activate the module for that route.
You can use a case insensitive regex expression to match any case of alpha characters:
this.get(/\/brief/i, function(context) {
console.log("BRIEF");
});

Resources