What is the most efficient way to process AJAX requests? - php

For example let's say I have a controller called News. Methods of News include Create, Edit, Delete, etc. So let's say for users with javascript enabled, we can use AJAX to deal with these things and use the controllers if not. For example, going to /news we can create news, edit, or delete without leaving this page...with AJAX. Without javascript, we would have to go to /news/create, /news/edit/1, /news/delete/1, etc.
So then what way is more efficient to deal with AJAX requests? On each controller should I just have a conditional to check whether the request was sent with AJAX, something like:
if(isset($_POST['ajax'])) {
// serve ajax request
} else {
// serve regular request
}
Or should I create additional methods such as ajaxCreate, ajaxEdit, ajaxDelete, etc?

Shouldn't your AJAX requests be almost the same as your regular requests, except the regular requests have an additional layer (rendering a page) on top?
Your conditional check should simply regulate whether you respond with something like a JSON response, or a full page - in effect, what view you invoke (assuming an MVC-style setup).

Never use /news/delete/1 to delete news!
use POST /news/delete and pass a news id
With that said, both ajax request and regular requests should be made to the same URL. the difference is that regular requests will return an html response and an ajax request will return xml/json/etc
Page: /news/create/
// create new news item code goes here
// most newer javascript libraries set this header so you know the page
// was requested via ajax
if ( isset( $_SERVER['X-Requested-With'] && $_SERVER['X-Requested-With'] == 'XMLHttpRequest' ) {
//output status code or new news item
exit;
}
// not an ajax request load a view
require( 'views/news_create.php' );

I prefer to pull this functionality into an API. For example, I can have a folder structure like the following:
web
- api
- 1.0
- news
create.php
news.php
Then your page is accessible at the 'news.php' URL. Inside this file you consume your own api. The AJAX would also directly access the API at the 'api/1.0/news/create.php' URL for instance.
This leads to less API code in the controllers/views.
Bob

Related

Handling users that visit a PHP process page without POST

This question addresses the security / user end side of things.
Suppose I have a script that is called via ajax which will add something to a database.
The script checks for the request method. If it is from 'POST' then the script will carry out this function.
I do not want users accessing my pages and either getting an error or a blank page.
What is the 'ideal' way to deal with this?
My current plan is as follows: If it is not a POST method, redirect them to an error page in the same way as a 404 handler and then provide some links for elsewhere.
Returning a 400 Bad Request is a pretty standard way to indicate that the user got there without the proper data that's needed.
if(!isset($_POST)){
header("HTTP/1.0 400 Bad Request");
}
On top of that, you should spend some time investigating doing some cross site request forgery protection (CSRF) if you want to make sure only your UI posts to that page.
Try this, i use it in all my pages called via ajax:
if ($_POST['ajax'] == "ajax") { // You need to set this is your post ajax variables sent to this php file.
// all your code here
} else {
// Not needed for a blank page, or whatever you want for another page ie
header ("location: 404.php");
}

API Component Separation

I'm new to the world of API programming, I just have a bit of a side project at work at the moment and I'm learning as I write, so bear with me.
I'm unsure as to the best way to implement an API for multiple different functions. At the moment I just have a test script I run and an apache redirect that redirects anything under /api to this script, call it TestAPI.php (so /api/anything will redirect). I pass the path variable of the API to the script (so in that example the path would be 'anything').
At the moment I'm just writing it for 1 purpose, to look up some data based on the path, and eventually be about to update and delete etc with PUT/DELETE etc (it's restISH not restFUL). This is fine at the moment where everything redirects to this script, but what about if I need 2 different functions? So I want to look up a different data set? So for example now /api/data1 would go to the 1st set and /api/data2 would go to the second. This is where I start to get unsure.
Do I simply have 1 mega script that grows and grows so that /api/data1 and /api/data2 redirect to the same place (and thus handle any errors like 404s there). Or do I have a script for /api/data1 and /api/data2 with separate redirects to each, then a generic catchall for 404s (I would always like to return JSON/XML rather than HTML for a 404, so I need at least logic to return based on the Accept header).
As a 3rd option, do I have some sort of frontline controller that catches everything, then calls off to the sub components? So 1 script that is redirects to for anything under /api, which then calls off to the required components or 404s if it's an invalid path. This seems like the best way to do it to me, but I have no idea how. Do I have some section of the site that only that script can call, or do I use cURL from the frontline controller to the back end API sections (as I'd need to pass POST/PUT data I assume I'd have to use cURL, is there any other way?). How is this best implemented in Apache?
Yes, you use a front controller. The front controller can use convention like first thing after /api processes the request
i.e.
/api/firstprocessor/method1
/api/firstprocessor/method2
/api/secondprocessor/method14
You can check out Zend_Framework for an example of this in action, or it can be something as simple as
$name = 'Script_' . $this->generateCommandName($request->getPathVariable(1));
$this->executeScript($name, $request);
public function executeScript($class, Request $request) {
if (file_exists("scripts/".$class.'.php')) {
//include the script
require_once "scripts/".$class.'.php';
//execute the script
$command = new $class;
$command->execute($request);
}
}
Then all your scripts just have an execute method that uses $request to get $_GET or $_POST variables

ajax- if I send an ajax request on a url, can i check in the php page if it is a request or the page has been opened?

For security purposes, I want to stop the users from being able to view or send anything to the php pages I am going to use for ajax purposes.
So is there any way by which I can check whether a page has been called because of an ajax request or the page has been opened?
Does self=top consider ajax request or not?
/* AJAX check */
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
/* special for ajax here */
}
else
{
//its a page request
}
this will only work when using JS frameworks that send this header :-by Bergi
No, you will need an other security model.
Of course you could set custom http headers (like X-Requested-With) or such when you are doing Ajax requests (many libraries do that automatically), and tell them apart from normal "view" requests. But everything can be faked, so there can be no security through determining that.
Even if you do stop people not using a ajax request, what's stopping people from changing the ajax request in the first place?
This would add little to none added security in my opinion especially with the ease this can be done with firebug for example.

PHP - Only allow access via AJAX

In my CMS, I have a page which loads lots of mini-interfaces into a panel using AJAX. Those interfaces come from various PHP files in a /ajax directory.
Would it be possible somehow to only allow access to those files using ajax, and not just by browsing to them?
My concern is, of course, that someone finds out about the /ajax directory, and gets access to the core functionality of the CMS without even having to login. Of course I could import my user class and authenticate each of the AJAX files individually, but would it be possible to only allow access through AJAX?
Would it be possible somehow to only allow access to those files using ajax, and not just by browsing to them?
No.
You could add extra HTTP headers, or modify existing ones (such as Accept) when you make the request from JavaScript … but since you are trying to do this for security reasons, that would be insufficient.
Of course I could import my user class and authenticate each of the AJAX files individually
Do that. Ajax requests are not special. They are just HTTP requests. End points created for Ajax should be secured with authentication/authorization just like any other HTTP request end point.
No. A hacker could just fake Ajax requests, anyway. You need to authenticate everywhere or you'll get screwed.
From outside a browser, it's possible for anybody to initiate HTTP requests to any public URL on your site. There's nothing special about AJAX requests other than headers, and those can be spoofed easily.
Now what can't be easily spoofed is a secure session mechanism. If you're requiring people to log in, then you should be doing that anyway.
Simple answer, "no".
Your ajax files should also validate the user is logged in the same way as the front end of your system does.
AJAX is almost same request as Standart request you can check header but this is not secure way. So short you can't do this. Authetificate on server side what you have proposed.
Authenticate your AJAX files. If there are lots of them, create a class and extend it in each individual AJAX file.
/ajax/abstract.php:
<?php
abstract class AjaxHandler {
public function __construct() {
// import authentication handler
if ($authenticated) {
$this->display();
}
else {
header('HTTP/1.1 401 Unauthorized');
exit;
}
}
}
Then in each file, i.e. /ajax/get_user_profile.php:
<?php
class GetUserProfile extends AjaxHandler {
public function display() {
// do your routine
}
}
Well, an alternative option you could have is to use post method to get the content from the php, and in your php you should set a key for the post method. And then system wide remove cross origin access. :)

Different classes and config for AJAX and non-AJAX actions

I have a website where people can place bids on products. So the first thing I have done is created a normal HTML-PHP version of the website which works great.
I have created some basic PHP functions that look at the url -> route you to the controller -> perform the action -> take the POST object etc.
Now I have implemented an AJAX version for this action but I want to know if I am doing the correct thing.
I made a new folder called ajax, and there I made a new controller for the ajax request. Now when somebody clicks on 'bid' then the request is hijacked by Javascript and sent to the AJAX controller. Now in the AJAX controller I strip down the link and then load the controller and model, and the work is done by the class.
Now the response the class has to send back is different for the AJAX version and for the HTML version. Now in the code of the class I have something like this
if(ajax version){
give ajax response
}else{
give html response
}
Now there are more things in the classes that are different.
Now my question is is it ok to use the same classes and config files for the ajax and non ajax function, or do they have to be seperate.
Or is there a more elegant manner of tackling this problem, maybe using interfaces.
If you follow the MVC pattern correctly, which it looks like from your description you are, then you should have a different action per request.
The flow should be
a different URL and action to receive the AJAX request
perform the business logic in your model
the action should then format the response in the style required (AJAX)
By having a switch (the if statement) in a shared controller, you run the risk of adding logic into the controller, which reduces the re-usability of your code.
So, put simply. Have a different PHP page for the different actions.
An easy way to do this is set a GET or POST parameter in the request when using AJAX, such as ajax=1 then check for this in the PHP:
if (isset($_GET['ajax'])){
give ajax response
} else {
give html response
}
AJAX requests have a header HTTP_X_REQUESTED_WITH with a value XMLHttpRequest
For example:
if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'){
// Ajax
} else {
// Normal request
}
As a rule of thumb, it is usually better to keep the same Model and Controller and, based on data in the request (such as a value in the query string, or a custom header such as X-Requested-By), switch Views (probably between an HTML Template View and a JSON View).

Categories