How does this HTTP request work? - php

To begin, this question deals primarily with HTTP requests, BackboneJS, some sort of RESTful API (such as Slim API), and how these things work with each other. Additionally, this question is coming from someone who doesn't have much experience on the server-side, other than just handling basic PHP/MySQL stuff.
I've been looking at Backbone, and I've seen some tutorials regarding the use of RESTful APIs on the back-end (including this one from 9bit).
I also read this answer to a StackOverflow question (Understand BackboneJS REST Calls).
If I open up a JS file, and type type in some code to send a POST request such as this:
(function() {
var http = new XMLHttpRequest();
var value = '{ "prop1": "value 1", "prop2": "value 2" }';
http.open('POST', 'dir', true);
http.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
http.setRequestHeader('Content-Length', value.length);
http.onreadystatechange = function () {
if (http.readyState == 4 && http.status == 200) {
alert(http.responseText);
}
}
http.send(value);
})();
I see in the console that it sent a POST request looking something like this:
Method: POST
Body: { "prop1": "value 1", "prop2": "value 2" }
Location: http://localhost/~myusername/Todo/dir/
And then, since it's just my local server, the server sends back a response with the basic HTML page that shows the files in that directory, etc.
I tried using a GET request to retrieve a similar JSON object as well, but obviously I couldn't get anything from that location, presumably because the object I was trying to request from some empty folder doesn't even exist anywhere.
My question is, when you use a BackboneJS method such as .save(), from what I understand, it might use, in that instance, a PUT method to send a request with a body of an object, perhaps parsed as a string, to a directory, such as 'article/id', with 'id' possibly being something like '43' (potentially the corresponding id of whatever model's properties you sent). So...
1) What does an API, such as Slim do with that request?
2) Where is it saving those object properties to (a MySQL database)?
3) Is there a file, such as 'index.php', sitting in the directory 'article', in which a script grabs the parameters in the body of the POST requests and uses though to communicate with the MySQL database? (I'm wondering why the location is simply a 'folder', such as '/article'. To put it in another context, whenever you type in a website like 'http://www.mywebsite.com', the server will automatically look for an 'index' page in that directory, such as 'index.html', and automatically open that file as the default file of that directory. Is that same type of thing happening in the context of using a location '/somefoldername' as the location of the HTTP request)?
Basically, it just looks strange to me that you would send an HTTP request to just some folder, and not a specific PHP file (for example) that would handle the request and communicate with a database. Using BackboneJS with a RESTful API, would our theoretical folder '/article' even exist, or is that just appended to the URL for some reason?
Thank you very much.

Since you asked your questions in the context of Slim, I'm going to answer them that way, although much of the information will generally apply to other web applications/frameworks.
What does an API, such as Slim do with that request?
Not to be to cheeky, but it does whatever you (or the API developer) wants it to do (more on that shortly).
Where is it saving those object properties to (a MySQL database)?
In general, those object properties are being used to create a resource (POST) or to updated a resource (PUT), and most likely the resource is being persisted in some sort of storage, be it an RDMS or a NoSQL solution.
Is there a file, such as 'index.php', sitting in the directory 'article', in which a script grabs the parameters in the body of the POST requests and uses though to communicate with the MySQL database?
Here's where things get interesting, IMHO. Considering the route article/id, here's what happens in a Slim application:
A request is received at example.com/article/22
The request is routed to a front controller script which, based on the request URI and HTTP method, makes a decision about what to do with the request.
If a PUT route for article exists, then the application code perhaps would take the request body and update the resource identified by the provided id.
With that in mind, in a Slim application, likely the only web accessible file is index.php. What appear to be directories are merely routes defined in the application's index.php that Slim used to make decisions about how to handle requests. With that in mind . . .
Using BackboneJS with a RESTful API, would our theoretical folder '/article' even exist, or is that just appended to the URL for some reason?
In the context of a Slim application, no, /article wouldn't exist as a directory, but rather a route.
Perhaps this won't help much, but this is what a portion of that index.php routing file might look like on the Slim side:
$app->post('/article', function () {
// Get data from post
// Create resource
});
$app->get('/article/:id', function ($id) {
// Return an article resource identified by $id
});
$app->put('/article/:id', function ($id) {
// Use $id to retrieve resource from storage
// Update resource with request data
});

Related

Objective-C: json response from jquery callback

I'm building and iOS application and
trying to get the json data from a url similar to:
example.com/ajax/u.php?callback=jQuery84054761566_1389381628746
Is anyone familiar with these types of callbacks?
Typical HTTP requests in obj-c return 200 status and a null response object with this url.
That's a JSONP callback used for...well, JSONP. JSONP is used on webpages to avoid the 'same origin' restriction. That is, a webpage loaded from a certain domain (say abc.com) cannot call/access resources on a separate domain (say xyz.com).
The way they (web front-end developers) get around this is by using the <script> tag which is exempt from this restriction. However the return of a <script> tag would just be parsed - to cause it to execute something, you tell it a function name that exists in your JavaScript code, in this case, jQuery84054761566_1389381628746.
So instead of returning a regular JavaScript object, say
{key : 'value'}
the server then returns a function invocation
jQuery84054761566_1389381628746({key : 'value'})
and you have, in your webpage JavaScript, the function definition for jQuery84054761566_1389381628746 that does something:
jQuery84054761566_1389381628746 = function(data){
alert(data.key);
};
iOS does not have this same-origin/cross-site restriction so you don't need JSONP - you can call whatever server you want.

In CakePHP, override AppController's redirect() to respond with a url via json during ajax requests

My controller methods serve dual purpose: To both handle traditional browser requests AND to interact via REST clients using mapped resources.
Case: This is convenient because I can keep all of my validation centralized in Cake models and still have nice ajax forms that I can validate by extracting Model::validationErrors and adding them to the json response. Where I don't care if a form is ajax, I can simply NOT apply my client-side javascript and the form and server communicate normally.
Problem: Many controller actions rely on Controller::redirect(). By overriding redirect(), trying beforeRedirect(), etc, I can find NO reliable way to convert the redirect into a JSON response during an ajax request that would indicate something like 'redirectUrl' => 'foo' so that my client (in the case of browser ajax) can forward the user to a new url using javascript location redirect.
I thought I had it working but realized that unauthorized users had access to run protected resources despite not seeing their output.
You can use json array with two keys like
$json['status'] => 'success',
$json['url'] => 'router::url ("/",array("controller" => "yourcontroller",
"action" => "youraction"))';
// url where you want redirect after some processing
return json_encode($json);
//In your Script from you was send ajax request:
if(json['status'] == 'success'){
window.location.href = json['url'];
}

Creating jQuery AJAX requests to a PHP function

So far when creating AJAX requests I have been posting to a separate PHP file. Is it possible to create a jQuery AJAX request that calls a PHP function rather than posts to a separate page?
If you could send me any examples or documentation would be great.
I believe there's a fundamental misunderstanding of how the technology works here.
AJAX (Javascript), Flash, or any client-sided technology cannot directly call PHP functions (or other languages running on the server).
This is true for going the other way around as well (eg: PHP can't call JS functions).
Client and server codes reside on different machines, and they communicate through the HTTP protocol (or what have you). HTTP works roughly like this:
Client (eg: browser) sends a REQUEST -> Server processes request and sends a RESPONSE -> Client gets and displays and/or processes the response
You have to see these requests and responses as messages. Messages cannot call functions on a server-side language directly 1, but can furnish enough information for them to do so and get a meaningful message back from the server.
So you could have a handler that processes and dispatches these requests, like so:
// ajax_handler.php
switch ($_POST['action']) {
case 'post_comment':
post_comment($_POST['content']);
break;
case '....':
some_function();
break;
default:
output_error('invalid request');
break;
}
Then just have your client post requests to this centralized handler with the correct parameters. Then the handler decides what functions to call on the server side, and finally it sends a response back to the client.
1 Technically there are remote procedure calls (RPCs), but these can get messy.
AJAX requests call a URL (make a HTTP request), not a file, in most cases the URL is translated by the server to point at a file (or a php script in your case), but everything that happens from the HTTP request to the response that is received is up to you (on your server).
There are many PHP frameworks that map URL's to specific php functions, AJAX is just an asynchronous way to access a URL and receive a response.
Said URL CAN trigger the server to call a specific function and send back a response. But it is up to you to structure your URL's and server side code as such.
If you're asking whether you can call any arbitrary PHP function with AJAX the answer is no*, for obvious security reasons (in addition to the technical reasons). You could make a PHP script that does different things depending on what parameter it's given (for example, execute a single function) if you don't want to create multiple separate files.
*Although you could make a script that would execute any arbitrary PHP command coming from the client, but that would be very, very, very unwise.
Short answer is "no" but the real answer is that you can fake it. NullUserException's answer is good. You create a server that will take the function name and its parameters. Then the server executes the function, and returns the value.
This was done a while back via a protocol called XML-RPC. There was also an effort called JSON-RPC that used some JS techniques.
One things that's cool about JS is that you can do things like this:
var base64_decode = create_remote_call('base64_decode');
function create_remote_call(name) {
return function(x) {
jQuery.getJSON('url/server.php',
{func:name,arg:x},
function(d){return d;});
}
}
A call to base64_decode('sarefdsfsaes') will make a ajax request and return the value.
That code probably won't work because it hasn't been tested, but it's a function that produces a function that will call the server, and then return the value. Handling more than one argument requires more work.
All that said... in my experience, it's usually good to make all network communications explicit instead of disguising it as a regular function.
you may achieve the same result using a bridge, like my phery library http://phery-php-ajax.net you can call PHP functions directly from Javascript and deal with the value. The AJAX is bound to DOM elements, so you can manipulate the calling DOM or just use jQuery from the PHP side. An example would be:
Phery::instance()->set(array(
'phpfunction' => function(){
return PheryResponse::factory()->jquery('body')->addClass('whoops');
}
))->process();
and in the javascript side (or HTML)
phery.remote('phpfunction');
the equivalent to the https://stackoverflow.com/a/7016986/647380 from John Kawakami answer, using phery is:
function base64($data){
return !empty($data['encode']) ? base64_encode($data['content']) : base64_decode($data['content']);
}
Phery::instance()->set(array(
'base64' => 'base64'
))->process();
function base64(content, decode, output){
phery.remote('base64', {'content': content, 'encode': decode ? 1 : 0}, {'type':'text'}).done(output);
}
base64('asdf', false, function(data){
console.log(data); // or assign to some variable
});
since AJAX is asynchronous and you can't just return a value from the AJAX call, you need a callback, but this would suffice.

Cross domain JSON feed for jQuery FullCalendar plugin

I'm using PHP to pull the events from a FullCalendar as a JSON feed but I need to support multiple domains. I need a querystring variable to specify which calendar to pull events from... is this causing a problem? Here's the FullCalendar init code:
$('#full-calendar".$id."').fullCalendar({
editable: false,
events:'http://www.mydomain.com/resources/include/calendar-events.php?cal=".$id."',
loading: function(bool) {
if (bool) $('#loading').show();
else $('#loading').hide();
}
});
The documentation says "If you need to access a feed that is in a different domain, you can use JSONP with a ? in your URL (see the JSONP discussion in $.ajax)."
But I'm not exactly sure how to do that.
Thanks for your help in advance.
Well at a high level, JSONP lets you specify the name of a callback function that you want called when the AJAX request returns with data. HTTP GET operations can happen across different domains, (when you embed an image from a different host, you are creating an HTTP GET). POST (and PUT, DELETE etc) are limited to the same domain as the document (this is called the Same Origin Policy). JSONP, adds an extra parameter (usually 'callback') with the value of a JavaScript function in your document (the callback function). The sever sending the JSON needs to know to extract the value for that parameter. Your request might look like this:
GET http://ical.example.com/cal.json?callback=_calDraw
The cal.json servlet will return this
_calDraw({event:{date:'12/25/2010',title:'Jason\'s birthday'}});
Now this bit of JavaScript references the callback function you passed into it, but without a corresponding
function _calDraw(data) {
//render stuff
}
The returned data will just fail. It's important that you have some level of trust with any server you are making a JSONP call to, because you are giving them permission to execute JavaScript in your document (they don't have to return something valid).
Hope this helps!

Cross Domain Ajax Request with JQuery/PHP

Help, if you can-
The situation:
http://foobar.com includes a remotely hosted javacript file (http://boobar.com/stuff.js).
The goal is to just get an alert from the remotely hosted php script on foobar.com
I have tried the following code in stuff.js:
$.ajax({
type: "GET",
url: "http://www.boobar.com/script.php?callback=?",
dataType: 'jsonp',
success: function(result) { alert(result); }
});
No luck.
$.getJSON("http://www.boobar.com/script.php?jsonp=?",
function(data) { alert(data); }
);
Also no luck.
On the php side I have tried both the following:
return json_encode(array(0 => 'test'));
echo json_encode(array(0 => 'test'));
In Firefox I get a security error. I understand that it thinks I'm violating the security model. However, according to the jquery documentation, I should be able to accomplish this.
The error seems to be a security feature of the Same Origin Policy: to simplify, you can only make AJAX requests for stuff on the originating server (http://foobar.com). One way around this is to make a simple facade on the originating server, e.g.:
<?php
// this file resides at http://foobar.com/getstuff.php
echo file_get_contents('http://www.boobar.com/script.php?callback=?'
. $possibly_some_other_GET_parameters );
?>
Then, from foobar.com, you can make an AJAX request for http://foobar.com/getstuff.php (which in turn makes a HTTP GET request from your web server to boobar.com and sends it back to the browser).
To the browser, the request goes to the origin server, and is allowed (the browser has no way of knowing that the response comes from somewhere else behind the scene).
Caveats:
the PHP config at foobar.com must have allow_url_fopen set to "1". Although this is the default setting, some servers have it disabled.
the request to www.boobar.com is made from foobar.com server, not from the browser. That means no cookies or user authentication data are sent to www.boobar.com, just whatever you put into the request URL ("$possibly_some_other_GET_parameters").
You can get data from another server asynchronously using script tags and json:
<script type="text/javascript" src="http://somesite.com/path/to/page/"></script>
You can use this to dynamically load a remote javascript (by created a new script element and setting the src attribute, then loading into the DOM), which could set a variable. However, you need to really trust the remote site, because the JS will be evaluated without any precondition.
There is a method called window.name transport or window.name method which uses a general browser bug(not sure if this is a bug actually). You make the request through an iFrame and the loaded page puts the information you need to the "name" property of the JavaScript window object of itself.
This method uses a "blank.htm" since it first navigates to the target page and then goes back to the blank.htm page to overcome the "same origin policy" restriction.
Dojo have implemented this and you can find a more detailed explanation here.
Also I have implemented a cross-domain XMLHttpRequest object based on this method in the library I have written which can be found here.
You may not be able to use the library since it will need 1 or 2 additional libraries which can be found here.
If you need further help in implementing it in your style, I'll try to do my best.
So what I ended up doing, since it was just a GET - no data need to be retrieved - I used JQuery to create a hidden iframe with the URL including the variables I wanted to pass set as the source. Worked like a charm. To all who provded feedback - Thanks!
How about this !! Using a php proxy.
Cross-Domain AJAX calls using PHP
http://www.phpfour.com/blog/2008/03/cross-domain-ajax-using-php/
jQuery .ajax also has a setting 'crossDomain'.
http://api.jquery.com/jQuery.ajax/
crossDomain (default: false for same-domain requests, true for cross-domain requests)
Type: Boolean
If you wish to force a crossDomain request (such as JSONP) on the same domain, set the value of crossDomain to true. This allows, for example, server-side redirection to another domain. (version added: 1.5)

Categories