Perl Dancer Testing: No route_exists for ajax routes? - ajax

I use the use Dancer::Plugin::Ajax to define some ajax routes in perl Dancer.
get '/' => sub {
template 'index' => $data;
};
ajax '/api/foo' => sub {
...
};
ajax '/api/bar' => sub {
...
};
In my test I would like to test if all the routes do exist:
route_exists [GET => '/'], 'a route handler is defined for /';
route_exists [AJAX => '/api/foo'], 'an ajax route handler is defined for /api/foo';
route_exists [AJAX => '/api/bar'], 'an ajax route handler is defined for /api/bar';
But unfortunately that does not work. I also tried
route_exists [GET => '/api/foo'], 'an ajax route handler is defined for /api/foo';
route_exists [GET => '/api/bar'], 'an ajax route handler is defined for /api/bar';
without succes.
Did I miss the right statement in the documentation?
Update after the first answer from #simbabque:
It nearly works now.
Unfortunatly find_route in Dancer::App uses
next if $r->has_options && (not $r->validate_options($request));
if it would use
next if $r->has_options && (not $r->check_options($request));
everything would work fine.
Background is: validate_options in Dancer::Route only checks the $_options_aliases, but the
required option is 'ajax' and that is only mentioned in $_supported_options.
Ideas how to work around this limitation?
(I will add my solution if this is fixed.)

This is not a complete answer, just a collection of stuff that will help you figure it out.
First, look at https://metacpan.org/source/YANICK/Dancer-1.3121/lib/Dancer/Request.pm#L341. The is_ajax method checks if the request has $self->{x_requested_with} eq "XMLHttpRequest".
If you look at https://metacpan.org/source/YANICK/Dancer-1.3121/t/15_plugins/07_ajax_plack_builder.t, which is the test for the Ajax plugin, it will create a fresh HTTP::Request.
My guess is you will need to do that too, in some way. Look at https://metacpan.org/source/YANICK/Dancer-1.3121/lib/Dancer/Test.pm#L107 for route_exists and hack your own version of that for ajax requests.
Update:
I hacked a little but did not test this at all:
*Dancer::Test::ajax_route_exists = sub {
my ($req, $test_name) = #_;
my $tb = Test::Builder->new;
my ($method, $path) = expand_req($req);
$test_name ||= "a route exists for $method $path";
$req = Dancer::Request->new_for_request($method => $path, undef, undef, HTTP::Headers->new( 'X-Requested-With' => 'XMLHttpRequest'));
return $tb->ok(defined(Dancer::App->find_route_through_apps($req)), $test_name);
}
Might be this works afterwards:
Dancer::Test::ajax_route_exists [GET => '/api/foo'], 'an ajax route handler is defined for /api/foo';

Related

Laravel routing with or without parameter in a group

For my application I am trying to create a few routes entries.
One entry to initialise the application and another for AJAX requests.
So my application should hit the initialise function if I type https.test.com/app/drive but also if I want to type some additional parameters at the end something like this: https:test.com/app/drive/specificTabA or https:test.com/app/drive/specificTabB
The problem is that when ever I type https.test.com/drive/specificTabNameA this clashes with the fetchData get route used by my AJAX call.
How can I access the initialise function when hitting this URl https.test.com/app/drive or also hitting something like this: https:test.com/app/drive/specificTabA or https:test.com/app/drive/specificTabB?
Route::group(['prefix' => 'drive'], function () {
Route::get('', 'CustomController#initialise');
Route::get('fetchData', 'CustomController#fetchData');
});
I've done some tests, and came with the following conclusion/solution:
Route::group(['prefix' => 'drive'], function () {
Route::get('fetchData', 'CustomController#fetchData');
Route::get('{param?}', 'CustomController#initialise');
});
CustomerController:
function initialise($param = null)
{
...
}
Note that by changing the order of the routes you will actually load the correct route.
When you visit /drive/fetchData it will load fetchData route
When you visit /drive/ it will load initialise route without arguments
When you visit /drive/xyz it will load initialise route with $param being xyz
Hope it helps :)
My friend I want to get your attention to Laravel docs https://laravel.com/docs/5.0/routing#route-parameters especially this one Route Parameters. You can tell router that this route can have parameter but also can not have it. Look at this example
Route::get('/{specific?}')
Now you can get this specific parameter in your Controller function after request
public function initialize (Request $request, $specific = null)
Set it default to null as this param can both be past and not, so it should have some default value.
Good luck ;)
The following should work for you:
Route::group(['prefix' => 'drive'], function () {
Route::get('fetchData', 'CustomController#fetchData');
Route::get('{path?}', 'CustomController#initialise')->where(['path' => '.*']);
});
This will allow the following path:
/drive => initialise
/drive/1 => initalize
/drive/1/2/3 => initalize
/drive/fetchData => fetchData
Adding ->where(['path' => '.*']) will route any path to initalize, e.g. /1, /1/2, /1/2/3.
If you only want to allow the path to be one level deep you can remove the where:
Route::get('{path?}', 'CustomController#initialise');

Http request and response in codeigniter

I am currently working in codeigniter and I am new to this.
I was wondering how to retrieve the JSON values using API call .
Can anyone suggest me where should I start.
Many Thanks in advance
Pass your array of row to json_encode();example for method of controller is below
public function getUserList() {
header('Content-Type: application/json');
$query = $this->db->get('mytable');
if(count($query) > 0) {
$message = array('status' => 'true' , 'message' => 'Record get successfully' , 'data' => $return );
}else{
$message = array('status' => 'false' , 'message' => 'Record not found.' );
}
echo json_encode($message);
}
Codeigniter does not have an inbuilt HTTP method so you need to use other things in php to achieve this.
There are 2 ways, you can use cURL, but honestly... it's convoluted... but read this: http://php.net/manual/en/book.curl.php
Another method is using stream_context_create() http://php.net/manual/en/function.stream-context-create.php
I strongly suggest using this 2nd one as its much easier to work with (in context with curl..
Much of how you setup your request depends on the API you are referencing with and the kind of requests it allows: GET, POST ... and what kind of header information it requires you to send over as well do they require oAuth header?
There is no 1 bunch of code fits all, I had to create a full custom library to integrate codeigniter into Magento, it took many hours.

method not allowed, when using onlyajax in controller action

Background:
I'm attempting to make good RESTful APIs in cakephp, and delegate front end work to a front end templating language Handlebars. As elicited here (http://www.dereuromark.de/2014/01/09/ajax-and-cakephp/) , using the JsonView and making an extensionful api is a good approach.
Problem:
Allowing only ajax by using $this->request->onlyAllow('ajax'); is returning method not allowed. I want to enforce this so my APIs are not directly called from the browser.
Could you (the community) validate my approach to building such APIs.
Code:
//At the controller
public function joinWithCode() {
//$this->request->onlyAllow('ajax'); //returns 405 method not allowed
//$this->request->onlyAllow('post'); //works and does not allow access from browser
$this->response->type('json');
$data = array(
'content' => 'something',
'error' => 'something else',
);
$this->set(compact('data'));
$this->set('_serialize', 'data');
}
//routes.php
Router::parseExtensions('json');
Router::connect('/Classrooms/join', array('controller' => 'classrooms', 'action' => 'joinWithCode'));
The post attempt from the postman extension:

Is there a way to set a default url parameter for the Route class in Laravel 4?

I'm trying to set up sub-domain based routing in Laravel 4 and I've hit a bit of an annoyance...
My route group looks like this:
Route::group(array('domain' => '{company}.domain.com'), function() {
// ...
});
Which seems to work fine, however, I need to specify the company parameter for every route/url I generate. I.e:
{{ HTML::linkRoute('logout', 'Logout', ['company' => Input::get('company')]) }}
Is there any way to specify the company parameter as static/global, so it is automatically added to any links I specify, unless otherwise overwritten/removed?
Unfortunately, no (I haven't seen any evidence in the router or HTMLBuilder that you can). You could, however, make an HTML macro... Example:
HTML::macro('lr', function($link, $title) {
$company = !empty(Input::get('company')) ? Input::get('company') : "";
return HTML::linkRoute($link, $title, ['company' => $company]);
});
Then call it - instead of HTML::linkRoute, use HTML::lr('logout', 'Logout')
Just an idea.

Symfony Routing: Can call route but not forward to

I have a route for just the locale without any other information (the startpage that is):
homepage:
pattern: /{_locale}/
defaults: { _controller: OurStartBundle:Default:index }
If I call the route directly it works (i.e.: localhost/de_DE/) but if I forward it throws the Error:
Unable to parse the controller name "/app_dev.php/de_DE/".
I forward using the Controller Method like this:
$locale = \Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
return $this->forward($this->generateUrl('homepage', array('_locale' => $locale)));
Anyone jave any idea why this doesn't work?
You are trying to forward the request to a URI, rather than a bundle string.
For example, your forward call should be...
$response = $this->forward('OurStartBundle:Default:index', array(
'_locale' => 'de_DE'
));
The Problem was that i used $this->forward() where i wanted a redirect and should have used $this->redirect().
Solution is:
$locale = \Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
return $this->redirect($this->generateUrl('OurStartBundle_homepage', array('_locale' => $locale)));

Resources