I have spent the past few days integrating Slim API to handle some PHP web services. The first few services utilized GET which was straight forward and had no problems. However, when trying to integrate some POST methods, I am receiving no response from the service. I have tried even just a simple echo to see if the service is being called. In every case, there is no return. Code below, some of the methods have been removed for clarity.
Any reason the POST method is unresponsive? Thanks! viv
$app->get('/login/:un/:pw/:type','login');
$app->get('/browseMO/:prm1/:prm2', 'browseMedia');
$app->get('/usersReviews/:userID','usersReviews');
$app->get('/pubsReviews/:userID','pubsReviews');
$app->get('/productReviews/:productID','getProductReviews');
$app->get('/productAvg/:productID','averageReviewsByOProduct');
$app->post('/userUpd','updateUserInfo');
$app->run();
function averageReviewsByOProduct($productID){
reviews::getAvgReviewByProduct($productID);
}
function browseMedia($param1, $param2){
browseMediaObjects::getMedia($param1, $param2);
}
function updateUserInfo(){
// $request = Slim::getInstance()->request();
// $body = $request->getBody();
echo "UPDATE CALLED"; // never reached
}
Try creating an anonymous function in the slim post declaration and see if the function gets call. If it doesn't, it's something with slim. If it does, it's something with your code.
$app->post('/userUpd',function() use ($app) {
echo 'Test';
});
If that doesn't work, make sure you are returning your data correctly. For instance the above returns data correctly for an AJAX call that expects a text string response.
Related
I'm using the Laravel Swoole Coroutine go function to do a HTTP request in order to achieve better performance. When I get the response from the external service, a new entry is created in the database with the data from the external service.
I want to be able to return a response from the controller with that new DB record. However, it appears that anything outside the go does not have access to anything that got assigned in the go function. I understand that that happens in a separate thread, but is there a way to implement this so that I can have access to the results inside the go function?
Please note that I have coroutine enabled globally and I only to use function as shown below:
public function store(User $user, Request $request) {
go(function () {
// get data from external API using Laravel HTTP Client
...
$user = User:create($data);
return response($user, 201)->send();
});
}
I have tried using the WaitGroup(), but it complains that the event loop has already been started if I wrap it with the Co\run function.
I'm using CakePHP 3.5 and two of the methods I want to use are deprecated and I can't find an alternative.
The methods are:
$this->response->send();
$this->response->stop();
I want to redirect to a different page and stop the execution of the current method. I've tried calling die() after my redirect and it doesn't work.
According to the migration guide the methods have been made obsolete.
Any thoughts?
Edit:
I'm trying to redirect users without access to certain pages. This is in the initialize() method in the controllers.
if ($allowedAccess) {
$this->Flash->error("Insufficient rights to access that location");
$this->redirect($this->referer());
// FIXME - find alternative to deprecated methods
return $this->response;
$this->response->send();
$this->response->stop();
}
Are you trying this in a controller? Simply return the response object from your controllers method:
public function index() {
// Some code
return $this->response;
}
send() was just a wrapper around phps exit(). Use exit() if you need to somewhere.
What happens when you return the response is that the ActionDispatcher processes the return value and if it's a Response object. See the __invoke() method.
The response will go through the middleware layer and will be finally send by the ResponseEmitter which is used by the Server. Check your webroot/index.php to see it:
// Bind your application to the server.
$server = new Server(new Application(dirname(__DIR__) . '/config'));
// Run the request/response through the application
// and emit the response.
$server->emit($server->run());
I have a controller, that when request is Post, it gets the request, and from there I get REMOTE_ADDR, and REQUEST_TIME. The code works just fine, I get that information that I need.
However, I am writing an integration test for the entire flow of my web app, and when I send the request, I get Call to undefined method Zend\Http\Request::getServer() when it gets to that point of my action in the controller.
$server = $this->getRequest()->getServer();
$remoteAddr = $server['REMOTE_ADDR'];
$timestamp = $server['REQUEST_TIME'];
When I do
$request = $this->getRequest();
and look at $request, it has method, uri, queryParams, postParams, fileParams, version, headers, metadata and content.
postData has everything I'm sending via my test, but it crashes when it gets to the point of getting the server.
Any ideas?
Thank you.
The request class your application is using is Zend\Http\PhpEnvironment\Request, which extends Zend\Http\Request with some PHP-specific stuff like getServer(). Change your test to use that and it should work fine.
In my CakePHP app I return JSON and exit for certain requests. An example of this would be trying to access the API for a login as a GET request:
header('Content-Type: application/json');
echo json_encode(array('message'=>'GET request not allowed!'));
exit;
However I am having to prefix the echo with the content type in order for it to be sent as JSON. Otherwise my code at the other end interprets it different.
Any ideas on how to get around this? Or at least improve it.
Update: Cake version 2.3.0
You can leverage the new 2.x response object:
public function youraction() {
// no view to render
$this->autoRender = false;
$this->response->type('json');
$json = json_encode(array('message'=>'GET request not allowed!'));
$this->response->body($json);
}
See http://book.cakephp.org/2.0/en/controllers/request-response.html#cakeresponse
Also you could use the powerful rest features and RequestHandlerComponent to achieve this automatically as documented: http://book.cakephp.org/2.0/en/views/json-and-xml-views.html
You just need to allow the extension json and call your action as /controller/action.json.
Then cake will automatically use the JsonView and you can just pass your array in. It will be made to JSON and a valid response by the view class.
Both ways are cleaner than your "exit" solution - try to unit-test code that contains die()/exit(). This will end miserably. So better never use it in your code in the first place.
Im currently building a controller from my Zend MVC application which would only be used as json service to populate the page. I want to restrict the users to use only GET method to access this end point(for some security reasons).
I followed this post _forward() in Zend does not work? but could not get working.
I am using the preDispatch to detect the non-get requests and would like to forward to errorAction in the same controller. My code looks likes this,
public function preDispatch(){
$this->_helper->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender();
//Restrict this Controller access to Http GET method
if(!($this->getRequest()->isGet())){
return $this->_forward('error');
}
}
public function errorAction(){
$this->getResponse()->setHttpResponseCode(501);
echo "Requested Method is not Implemented";
}
When I test the page with a post request, it throws
PHP Fatal error: Maximum execution time of 30 seconds exceeded
I got it working with
$this->_redirect("service/error");
Wondering if it is the only/best way to handle this situation.
Any help would be really appreciated. Thanks in advance.
The reason that calling _forward doesn't work is because the request method doesn't change so you end up in an infinite loop trying to forward to the error action since the request is always POST.
_forward works by modifying the module, controller, and action that will be called when the request is dispatched, _redirect actually returns a 302 redirect and results in an additional HTTP request by the browser.
Either method is okay, but I'd prefer to go with _forward since it won't require an additional HTTP request (but you still guarantee the POST request is denied).
This code should work for you:
if(!($this->getRequest()->isGet())){
// change the request method - this only changes internally
$_SERVER['REQUEST_METHOD'] = 'GET';
// forward the request to the error action - preDispatch is called again
$this->_forward('error');
// This is an alternate to using _forward, but is virtually the same
// You still need to override $_SERVER['REQUEST_METHOD'] to do this
$this->getRequest()
->setActionName('error')
->setDispatched(false);
}