Yii2 Functional test send ajax get request not working - yii2

I am trying to test an ajax request with a basic install of Yii2. I am just using the SiteController::actionAbout() method to try this out.
public function actionAbout()
{
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return [
'message' => 'hello world',
'code' => 100,
];
}
And in the test:
public function sendAjax(\FunctionalTester $I)
{
$I->sendAjaxGetRequest('site/about');
$r = $I->grabResponse();
die(var_dump($r));
}
The grab response method is one I wrote myself in a \Helper\Functional.php file:
public function grabResponse()
{
return $this->getModule('Yii2')->_getResponseContent();
}
When I dump out the response, I just see the html from the site/index page.
This happens for any route except the site default. If I try to do the same thing using site/index then it returns:
string(36) "{"message":"hello world","code":100}"
What am I missing / doing wrong?

Note the difference between a Yii route and the actual URL.
The argument to sendAjaxGetRequest() is the URL, not the route (at least if you pass it as a string, see below).
Dependent on your UrlManager config you might have URLs like /index.php?r=site/about, where the route is site/about. You can use the Url helper of Yii to create the URL:
$I->sendAjaxGetRequest(\yii\helpers\Url::to(['site/about']));
I am not sure about this but if you have the Codeception Yii2 module installed you should also be able to pass the route like this:
$I->sendAjaxGetRequest(['site/about']);

Related

CakePHP Routing json response

I am currently using RestApi plugin for CakePHP 3 and I want to be able to append the extension .json to URL, like so:
domain.com/api/search/abc.json
Following CakePHP's docs about creating RESTful routes I was able to use the extension without throwing an error.
I have this on my routes.php (edit to add the whole code)
use Cake\Core\Plugin;
use Cake\Routing\RouteBuilder;
use Cake\Routing\Router;
use Cake\Routing\Route\DashedRoute;
Router::defaultRouteClass(DashedRoute::class);
Router::scope('/', function (RouteBuilder $routes) {
$routes->connect('/', ['controller' => 'Pages', 'action' => 'display', 'home']);
$routes->connect('/pages/*', ['controller' => 'Pages', 'action' => 'display']);
$routes->fallbacks(DashedRoute::class);
});
Plugin::routes();
Router::scope('/', function ($routes) {
$routes->extensions(['json']);
});
In my controller, if I do this:
public function search($term=''){
$this->httpStatusCode = 200;
$this->apiResponse['term'] = $term;
}
The response is:
{
"status": "OK",
"result": {
"term": "abc.json" # Notice the .json
}
}
So, I get abc.json, when I want abc.
Am I doing something wrong? Or am I supposed to strip the .json from $term?
While reusing existing scopes will merge the connected routes to the same routes collection, calls to RouteBuilder::extensions() will generally not affect previously connected routes, and they also do not affect reused/reopened scopes.
Quote from the docs:
Future routes connected in through this builder will have the connected
extensions applied. However, setting extensions does not modify existing routes.
API > \Cake\Routing\RouteBuilder::extensions()
You should add the extensions() call in the existing routing scope, so that it affects the routes that are being connected in there after the extensions() call.
See also
Cookbook > Routing > Routing File Extensions

Laravel: return post request body from Postman in json

I am trying to make a test work. I use a REST client, "Postman" to send a POST request with an object to Laravel. The idea is to get back the request as an object. But I don't think I am getting the right result.
In Postman, I specify the adress to send to, choose "POST", and then send this:
{
"url": "http://testingtesting.com"
}
In Laravel I have a Route to the adress:
Route::post('api/test', 'TestController#index');
and the controller should return the json object. If I do this:
class TestController extends BaseController{
public function index(){
$input = Input::json()->all();
var_dump($input);
}
}
I get back an array in POSTman:
array (size=1)
'url' => string 'http://testingtesting.com' (length=18)
That's when I look at "preview". If I switch to "Pretty" it shows like this:
<pre class='xdebug-var-dump' dir='ltr'>
<b>array</b>
<i>(size=1)</i>
'url'
<font color='#888a85'>=></font>
<small>string</small>
<font color='#cc0000'>'http://testing.com'</font>
<i>(length=18)</i>
</pre>
but I'm supposed to get an object(stdClass), not an array. What do I need to do?
I got some info here (laracasts forum)get-raw-post-data.
It seems to work with:
class TestController extends BaseController{
public function index(){
$data = json_decode(file_get_contents("php://input"));
var_dump($data);
In Postman, that results in:
object(stdClass)[144]
public 'url' => string 'http://testingtesting.com' (length=18)
But not sure if this is a recommended way, or why/how it works. I guess I have to read more about it. But if anyone wants to add any more info, or solutions, feel free!

Play 2.0 routes file for different configurations

I have a Play 2.0 application with 3 different configurations (application.conf, test.conf and prod.conf)
Now I have a robots.txt file that should be delivered for only test.conf and for the rest environments it should give a 404 if someone tries to access it.
How can I configure my routes file to check if my application is using test.conf? Can I set some variable in test.conf that I can check in the routes file?
Something like this? (pseudo code)
#{if environment = "test"}
GET /robots.txt controllers.Assets.at(path="/public", file="robots.txt")
#{/if}
#{else}
GET /robots.txt controllers.Application.notFoundResult()
#{/else}
You can't add logic in the routes file.
I'd write a controller to serve the robots.txt file. Something like this:
In the routes file:
GET /robots.txt controllers.Application.robots
Then, in the controller, I'll test if I'm in a testing environment :
def robots = Action {
if (environment == "test") { // customize with your method
Redirect(routes.Assets.at("robots.txt"))
} else {
NotFound("")
}
}
I'm using Scala, but it can be easily translated to Java.
Edit - java sample
You can check if application is in one of three states: prod, dev or test, ie, simple method returning current state:
private static String getCurrentMode() {
if (play.Play.isTest()) return "test";
if (play.Play.isDev()) return "dev";
if (play.Play.isProd()) return "prod";
return "unknown";
}
you can use as:
play.Logger.debug("Current mode: "+ getCurrentMode());
of course in your case that's enough to use these condition directly:
public static Result robots() {
return (play.Play.isProd())
? notFound()
: ok("User-agent: *\nDisallow: /");
}

Why am I unable to access the json data POST'd to my codeigniter application?

I'm working on a RESTful application using CodeIgniter and I'm unable to access my POST'd json data in my controller.
I'm posting the json via cURL on my local machine, while the app is being developed on a remote server.
Here is the controller code in question:
class Products extends CI_Controller
{
public function __construct()
{
$this->load->model(products_model);
}
public function index($id = FALSE)
{
if($_SERVER['REQUEST_METHOD'] == 'GET')
{
// fetch product data
$product_data = $this->products_model->get_products($id)
// set appropriate header, output json
$this->output
->set_content_type(application/json)
->set_output(json_encode($product_data));
}
elseif($_SERVER['REQUEST_METHOD'] == 'POST')
{
// debugging for now, just dump the post data
var_dump($this->input->post());
}
}
}
The GET action is working well enough, and returning the appropriate data when requested from a browser, or via a cURL request. However, when attempting to POST json data via cURL I consistently get bool(FALSE) returned from the POST section of the index function. Here is the cURL request I'm making:
curl -X POST -d #product.json mydomain.com/restfulservice/products
Also, here is the contents of the product.json file:
{"id":"240",
"name":"4 x 6 Print",
"cost":"1.5900",
"minResolution":401,
"unitOfMeasure":"in",
"dimX":0,
"dimY":0,
"height":4,
"width":6}
I've made another POST via cURL, excluding the json data and passing something like this:
curl -X POST -d '&this=that' mydomain.com/restfulservice/products
Which returns
array(1) {
["this"]=>
string(4) "that"
}
What gives? Something with the json? It's valid. I've turned off the global CSRF and XSS in application/config/config.php as I understand they require use of CI's form_open() and won't work properly without it. It's my understanding that excluding parameters from $this->input->post() will return ALL the post items yet I continue to get none. I've also tried going around CI's input library and accessing the data via PHP's $_POST variable, it has made no difference.
Your post data is not in query string format so you should skip dealing with $_POST and go straight to the raw post data.
try
var_dump($HTTP_RAW_POST_DATA);
or even better
var_dump(file_get_contents("php://input"));
in codeigniter 2.X, you can override Input class and add necessary functionality.
https://ellislab.com/codeigniter/user-guide/general/core_classes.html
add file MY_Input.php to application/core
add code inside this file:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Input extends CI_Input {
public function raw_post() {
return file_get_contents('php://input');
}
public function post($index = NULL, $xss_clean = FALSE) {
$content_type = $this->get_request_header('Content-type');
if (stripos($content_type, 'application/json') !== FALSE
&& ($postdata = $this->raw_post())
&& in_array($postdata[0], array('{', '['))) {
$decoded_postdata = json_decode($postdata, true);
if ((json_last_error() == JSON_ERROR_NONE))
$_POST = $decoded_postdata;
}
return parent::post($index, $xss_clean);
}
}
that's it..
use it like normal post..

set content-type to json in symfony

I am using symfony 1.4, to create my project with propel as ORM. i want to get the response in JSON format, when i call a url. I have set the headers to "application/json" but it is not working, i am getting the response back in HTML format..which i am not able to decode. How can we set content-type in symfony??
example code:
Action-
public function executeIndex(sfWebRequest $request)
{
$data_array=array("name" => "harry", "mobile" => "9876543210");
$data_json=json_encode($data_array);
$this->output=$data_json;
}
View-
<?php
header('Content-type: application/json');
echo $output;
?>
ok i got where i was going wrong..yhe code should have been..
Action-
public function executeIndex(sfWebRequest $request)
{
$this->getResponse()->setContentType('application/json');
$data_array=array("name" => "harry", "mobile" => "9876543210");
$data_json=json_encode($data_array);
return $this->renderText($data_json);
}
this code has worked for me, please post if any better solution you have got..
You can also define this in the view.yml (apps/{app_name}/modules/{module_name}/config/view.yml) file for the module.
indexSuccess:
has_layout: false
http_metas:
content-type: application/json
Oh ! As an alternative, I'd just say I have been using the routing system, which provides a pretty neat way to get it done:
-> In your routing.yml
json_test:
url: /test
class: sfRequestRoute
param: { module: test, action: index, sf_format: json }
Then, the frameworks will automatically pick up you view index.json.php, which you have to create. As mentioned above, you can generate the content in the action with json_encode, though there are arguments to put it in the view.
Now... Ok, if you are interested in picking some more about this, have a look at the "Practical symfony" tutorial: Day 15: Web Services
There's some good stuff down there !
In a REST style, just add .format to the URI, create the relative template and Symfony Routing system does the rest of the work for us.