Page 1 of 1

API tutorial.

Posted: Sun Jun 19, 2011 8:19 am
by Torniquet
I have followed your youtube tutorial for the developers API.

I am getting a slightly disturbing issue. Data is not always being fed back to me.

it can take 5-6 refreshes of my page before any information is displayed. Now for what i need this API for, this is an issue i need resolved.

Here are my 3 scripts used for the API.

api_interface
class taptin
{
	const API_URL = 'http://www.website.net/api/api.php';
	
	// internal function for sending post data
	private static function send_post_data($data)
	{
		$url = parse_url(self::API_URL);
		$boundary = md5(microtime(true));
		
		$post = '';
		
		foreach($data as $name => $value)
		{
			$post .= "--{$boundary}\r\n";
			$post .= "Content-Disposition: form-data; name=\"{$name}\"\r\n\r\n";
			$post .= "{$value}\r\n";
		}
		
		$post .= "--{$boundary}--\r\n";
		
		if(isset($url['query']))
		{
			$head = "POST {$url['path']}?{$url['query']} HTTP/1.1\r\n";
		}
		else
		{
			$head = "POST {$url['path']} HTTP/1.1\r\n";
		}
		
		$head .= "Host: {$url['host']}\r\n";
		$head .= "Content-Type: multipart/form-data; boundary=\"{$boundary}\"\r\n";
		$head .= "Content-Length: " . strlen($post) . "\r\n";
		$head .= "Connection: close \r\n\r\n";
				
		$socket = fsockopen($url['host'], ((isset($url['port'])) ? $url['port'] : 80));
		
		fwrite($socket, "{$head}{$post}");
		
		return (end(explode("\r\n\r\n", stream_get_contents($socket))));
	}
	
	// Gets the user_id for the reference id given
	public static function user_by_ref($ref)
	{
		return json_decode(self::send_post_data(array('log_user' => $ref)), true);
	}
}
api.php
include ("api.inc.php");

header('Content-Type: application/json');

if(isset($_POST['log_user']))
{
	$errors = array();
		
	$user = (empty($errors)) ? get_user_ref($_POST['log_user']) : false;
	
	echo json_encode(array(
		'user_id' 	=>	$user['user_id'],
		'username'	=>	$user['username'],
		'gender'	=>	$user['gender'],
		'errors'	=>	$errors,
	));
	
}
else
{
	echo json_encode(array(
		'get_user_info'	=>	'returns the basic information of a specified user.',
		'log_user'		=>	'returns the user id of a user logging onto your game.',
	));
}	
log_api_request($_SERVER['REMOTE_ADDR']);
and api.inc.php

$db_host = "xxxxxxx";
$db_user = "xxxxxxxxx";
$db_pass = "xxxxxxxx";
$db_name = "xxxxxxxx";

$dba = new mysqli($db_host, $db_user, $db_pass, $db_name);

// Logs a new request received from the given IP address
function log_api_request($ip)
{
	global $dba;
	$ip = $dba->real_escape_string($ip);
	$query = "INSERT INTO `api_log` (`ip`, `date`, `requests`) VALUES (INET_ATON('{$ip}'), NOW(), 0)
				ON DUPLICATE KEY UPDATE `requests` = `requests` + 1";
				
	$dba->query($query);
}


// Gets the total number of requests made for today
function get_day_request($ip)
{
	$ip = mysqli_real_escape_string($ip);
	$query = "SELECT `requests` FROM `api_log` WHERE `ip` = INET_ATON('{$ip}') AND `date` = DATE(NOW())";
	
	$sql = $dba->query($query);
	
	return ($sql->num_rows == 1) ? $sql->fetch_row(0) : 0;
}

function get_user_ref($ref)
{
	global $dba;
	$ref = preg_replace('#[^A-Za-z0-9]#', '', $ref);
	$query = "SELECT user_id, username, gender FROM table WHERE porting_ref='$ref' LIMIT 1";
	$sql = $dba->query($query);
	
	if($sql->num_rows > 0)
		return $sql->fetch_assoc();
}

am i missing something? or is this just a risk using this kind of API?

it manages to log every hit, just doesnt return data all the time.

Re: API tutorial.

Posted: Sun Jun 19, 2011 11:27 am
by jacek
Can you try changing this line
return (end(explode("\r\n\r\n", stream_get_contents($socket))));
to this.
var_dump(stream_get_contents($socket));
Which should tell you what you are getting back from the server. It will break the following code and you will get some warnings but don't worry about that for now, we just need to know what you are getting back from the server when it does fail.

The other possible cause I can think of is that you are testing this via the internet from a server that has a very slow connection or is overloaded, making it not able to respond in time.

Re: API tutorial.

Posted: Sun Jun 19, 2011 11:43 am
by Torniquet
i have a feeling that its my host being slow... and its not asthough i am requesting a ton of data either ¬¬

i will try the vardump and get back to you.

Re: API tutorial.

Posted: Sun Jun 19, 2011 11:49 am
by jacek
you can try increasing the socket time out too
$socket = fsockopen($url['host'], ((isset($url['port'])) ? $url['port'] : 80), $errno, $errstr, 60.0);
I think is right.

Re: API tutorial.

Posted: Sun Jun 19, 2011 12:12 pm
by Torniquet
increasing the timeout didnt work, still had the same effect even @ 1000.0

This is what vardump is returning, each and everytime...

string(357) "HTTP/1.1 200 OK Date: Sun, 19 Jun 2011 12:05:01 GMT Server: Apache mod_fcgid/2.3.6 mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635 X-Powered-By: PHP/5.2.15 Connection: close Transfer-Encoding: chunked Content-Type: application/json X-Pad: avoid browser bug 3f {"user_id":"1","username":"Torniquet","gender":"1","errors":[]} 0 "

obviously the time changes, but it seems to be getting the right data all the time, so why isnt it packing it out with the return :s

Re: API tutorial.

Posted: Sun Jun 19, 2011 12:34 pm
by jacek
Encoding: chunked
The method used relies on having all of the data in one go, so it will not work with chunked encoding. I have no idea of the correct way to not accept chunked encoding but you can force the server not to use it by using HTTP/1.0

Try changing
$head = "POST {$url['path']}?{$url['query']} HTTP/1.1\r\n";
to
$head = "POST {$url['path']}?{$url['query']} HTTP/1.0\r\n";
And the same for the other similar line.

Re: API tutorial.

Posted: Sun Jun 19, 2011 4:18 pm
by Torniquet
jacek, i could kiss you right about now!

It seems to have done the trick :) full steam ahead for my API we go. I will look into the http1.1 issue another time, and if i find it i will post the solution

Re: API tutorial.

Posted: Sun Jun 19, 2011 4:44 pm
by jacek
One alternative is to actually check for, and then process the chunked encoding whcih would not be that hard.

But good that you got it working :D

Re: API tutorial.

Posted: Sat Jun 25, 2011 11:26 am
by Torniquet
A question regarding the API, can host IPs be blocked from using the API by banning the ip? One thing I am slightly concerned about is using an API to make a ton of requests in attempt to DDOS my site (if enough info is sent & requested to make an impact that is)?

Re: API tutorial.

Posted: Sun Jun 26, 2011 12:02 am
by jacek
Torniquet wrote:A question regarding the API, can host IPs be blocked from using the API by banning the ip?
That will be most effectively done with a firewall not by php, so iptables if you are on Linux.
Torniquet wrote:One thing I am slightly concerned about is using an API to make a ton of requests in attempt to DDOS my site (if enough info is sent & requested to make an impact that is)?
It's defiantly somethign to be worried about, but your actual page would be more effective at creating a DOS I think.