1. Trang chủ
  2. » Công Nghệ Thông Tin

Tạo mạng xã hội với PHP - part 38 pps

10 253 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 3,71 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

The way RESTful APIs rely on descriptive URIs for providing access to data makes them very easy for consumers to utilize, as the URIs provide information on what the request does, and wh

Trang 1

Let's go with REST

REST is now a very popular API architecture, with most social networks providing

REST-based APIs The way RESTful APIs rely on descriptive URIs for providing access

to data makes them very easy for consumers to utilize, as the URIs provide information

on what the request does, and what data it will return Some implementations, such

as the Twitter API even make it possible to change the format of the data returned,

simply by changing a part of the URI

Requests

Requests to a RESTful API use HTTP verbs to describe what the consumer is trying

to do The API requests are made to specific URIs, which define the resource that the

consumer is trying to perform the action (determined by the verbs) upon

HTTP verbs

The HTTP verbs and their usage are described as follows:

GET Retrieve information POST Create records PUT Update records DELETE Delete records

Resources

RESTful APIs relate URIs to resources Below are some examples:

• http://ourdomain.com/profiles: To list or create profiles

• http://ourdomain.com/profiles/1: A specific user's profile

Our RESTful API will be based within an API controller, thus prefixing all URLs with api/, which goes slightly against the REST concept of a resource

Trang 2

Resources and verbs—the requests

Let's look at how resources and verbs combined result in API requests

API operation HTTP verb Resource

Creating a user POST http://ourdomain.com/api/profiles

Listing users GET http://ourdomain.com/api/profiles

Viewing a user's profile GET http://ourdomain.com/api/profiles/1

Updating a profile PUT http://ourdomain.com/api/profiles/1

Deleting a profile DELETE http://ourdomain.com/api/profiles/1

In the above resources, the number 1 represents the

ID of a user's profile

Responses

The response to an API request is generally made up of two parts The first part

of the response is the HTTP header containing an appropriate status code Some

examples of HTTP status codes are below:

HTTP status code Meaning

400 Bad request

Within PHP, HTTP status codes are set as follows:

header("HTTP/1.0 404 Not Found");

The second part of the response is the data itself; for instance, if the API request was

for a list of users, the response would be the list of users Commonly, response data

is sent as XML or JSON Some APIs allow the consumer to request the format of the

response by supplying the format to the API We are going to use JSON If we have

an array of data that we want to return as JSON, we simply do the following:

Trang 3

Further reading

There are numerous resources available regarding web services and REST

Following are the resources you may find particularly useful

RESTful PHP Web Services

Packt has a book dedicated to creating RESTful APIs in PHP—RESTful PHP Web

Services, by Samisa Abeysinghe,

https://www.packtpub.com/restful-php-web-services/book This book details the concepts of a REST architecture, how

to make use of existing RESTful APIs in your framework, how to create a RESTful

API for other applications to interact with, as well as debugging information and

case studies

Conference talks

Lorna Jane Mitchell (http://www.lornajane.net), a widely-respected developer

and conference speaker on PHP-related topics, has recently spoken at a number

of conferences on the subject of web service design Slides from related talks are

available online:

http://www.slideshare.net/lornajane/best-practices-in-web-service-design,

http://www.slideshare.net/lornajane/php-and-web-services-perfect-partners

Implementation

Now that we know what sort of API we are going to develop, we can move onto the

implementation In this chapter we will only implement a small sub-set of the API's

functionality Feel free to extend this to match the entire functionality of Dino Space,

if you wish

Data format

Most commonly, RESTful APIs either return their data in XML format or as JSON

Some APIs allow the consumer to specify the return type by adding xml or json

to the end of the URL For the purposes of our implementation, let's stick to JSON,

as it is simpler to convert data to JSON (simply by passing the data to the

json_encode function)

Trang 4

API controller

Our API controller itself won't do very much; instead it will pass control to

delegate controllers, which contain logic specific to the various sections of

the site

<?php

/**

* API Controller

*/

class Apicontroller{

To indicate which files are available for control to be delegated to, we should

maintain an array of allowable API controllers For our work in this chapter,

we will create the profiles delegate

/**

* Allowable API Controllers, for control to be delegated to

*/

private $allowableAPIControllers = array( 'profiles' );

/**

* Request data

*/

private $requestData = array();

The object's constructor simply sets the registry object, gets the value of the API

delegate that should be used, and calls the delegator method (delegateControl)

/**

* API Controller Constructor

* @param Registry $registry the registry

* @param boolean $directCall

* @return void

*/

public function construct( Registry $registry, $directCall=true )

{

$this->registry = $registry;

$apiController = $registry->getObject('url')->getURLBit(1);

Trang 5

The delegateControl method checks that the delegate controller is within the

allowed delegates If it is, then it includes the appropriate controller, instantiates

it, and passes the registry and the API controller object to it There are a number of

methods that will be common to all API delegates These methods are stored in this

object, and called by the delegate referencing this object If the requested controller

is not allowable, then we generate an appropriate HTTP status code; in this case:

404 Not Found

/**

* Pass control to a delegate

* @param String $apiController the delegate

* @return void

*/

private function delegateControl( $apiController )

{

if( $apiController != '' && in_array( $apiController,

$this->allowableAPIControllers ) )

{

require_once( FRAMEWORK_PATH 'controllers/api/'

$apiController '.php' );

$api = new APIDelegate( $this->registry, $this );

}

else

{

header('HTTP/1.0 404 Not Found');

exit();

}

}

A shared method is required by our delegates This is called if a delegate requires the

API user to be an authenticated user on the site It generates a basic authentication

prompt (this is presented to users viewing the site in their browsers, but for API

users the username and password are passed as part of the HTTP request)

Trang 6

Alternatives to basic authentication

Basic authentication isn't the best option in terms of security, especially

if many websites begin offering services utilizing our API Our users'

passwords could be stored (with their permission) within these websites,

putting reliance on the integrity and security of those sites and their

owners An alternative is OAuth, where the API provider deals with the

authentication, and provides consumers with an API key for their users If

a user then wishes to stop a third-party service utilizing their account via

the API, they can simply revoke access We will discuss this option more

in the security section of this chapter

If the authentication fails, then the 401 Unauthorized status code is issued

/**

* Request authentication for access to API methods, called by

delegates

* @return void

*/

public function requireAuthentication()

{

if( !isset( $_SERVER['PHP_AUTH_USER'] ) )

{

header('WWW-Authenticate: Basic realm="DinoSpace API Login"');

header('HTTP/1.0 401 Unauthorized');

exit();

}

else

{

$user = $_SERVER['PHP_AUTH_USER'];

$password = $_SERVER['PHP_AUTH_PW'];

$this->registry->getObject('authenticate')->postAuthenticate(

$user, $password, false );

if( ! $this->registry->getObject('authenticate')-

>isLoggedIn() )

{

header('HTTP/1.0 401 Unauthorized');

exit();

Trang 7

PUT and DELETE data (technically, there should never be DELETE data sent on a

DELETE request) cannot be accessed through super globals as POST and GET data

can ($_POST and $_GET), so we need a mechanism to get the request data, regardless

of the type of request

/**

* Get the type of request

* @return array

*/

public function getRequestData()

{

if( $_SERVER['REQUEST_METHOD'] == 'GET' )

{

$this->requestData = $_GET;

}

elseif( $_SERVER['REQUEST_METHOD'] == 'POST' )

{

$this->requestData = $_POST;

}

elseif( $_SERVER['REQUEST_METHOD'] == 'PUT' )

{

parse_str(file_get_contents('php://input'),

$this->requestData );

}

elseif( $_SERVER['REQUEST_METHOD'] == 'DELETE' )

{

parse_str(file_get_contents('php://input'),

$this->requestData );

}

return $this->requestData;

}

}

?>

php://input

php://input is an input stream wrapper in PHP, which allows us to

read raw request data More detailed information is available on the PHP

website: http://php.net/manual/en/wrappers.php.php/

Trang 8

Wait—no models?

That's right; we don't need to create any models for our API All of the functionality

our API needs to provide already exists through the various models we have created

So instead of creating API-specific models, we will create some additional API

controllers, which work with the pre-existing models to get the data and present

it to the consumer

Authentication

Keeping with the RESTful way of leveraging HTTP, we can make use of HTTP

authentication to authenticate the user This is where authentication details are

passed as part of the HTTP request from our API consumer You will have seen

examples of this if you have ever visited a web page, and your browser has opened

a pop up prompting for authentication details before loading the page In this case,

your browser reads the server's request for authentication, and then requests login

details before sending the authentication request to the server

More information

You can read more about HTTP authentication with PHP here:

http://php.net/manual/en/features.http-auth.php

Sessions lead to unREST!

REST is a stateless architecture, which means all of the information required for a

particular operation or request should be included within that request It shouldn't

rely on information from a previous request or other information such as sessions

and cookies To that end, we should amend our authenticate registry object and

our index.php file

Amending the authenticate registry object

We need to amend the authenticate registry class (registry/authenticate

class.php) to only set $_SESSION data if that is required, so that we can indicate,

from our API controller, that we don't want $_SESSION data to be created

Trang 9

We should add an optional parameter to the postAuthenticate method to indicate

if $_SESSION data should be set, with a default value of true so it doesn't impact on

other aspects of our site, which we have already implemented

public function postAuthenticate( $u, $p, $sessions=true )

{

$this->justProcessed = true;

require_once(FRAMEWORK_PATH.'registry/user.class.php');

$this->user = new User( $this->registry, 0, $u, $p );

if( $this->user->isValid() )

{

if( $this->user->isActive() == false )

{

$this->loggedIn = false;

$this->loginFailureReason = 'inactive';

}

elseif( $this->user->isBanned() == true )

{

$this->loggedIn = false;

$this->loginFailureReason = 'banned';

}

else

{

$this->loggedIn = true;

If the sessions parameter for this method has been set to true, then we set the

appropriate session If it has been set to false (for example, by our API controller),

then it is not set

if( $sessions == true )

{

$_SESSION['sn_auth_session_uid'] = $this->user->getUserID();

}

}

}

else

{

$this->loggedIn = false;

$this->loginFailureReason = 'invalidcredentials';

}

}

Trang 10

Amending index.php

Our index.php file by default checks for SESSION data for authentication

See Chapter 2, or take a look at the index.php file to refresh your memory

<?php

session_start();

DEFINE("FRAMEWORK_PATH", dirname( FILE ) "/" );

require('registry/registry.class.php');

$registry = new Registry();

// setup our core registry objects

$registry->createAndStoreObject( 'template', 'template' );

$registry->createAndStoreObject( 'mysqldb', 'db' );

$registry->createAndStoreObject( 'authenticate', 'authenticate' );

$registry->createAndStoreObject( 'urlprocessor', 'url' );

$registry->getObject('url')->getURLData();

// database settings

include(FRAMEWORK_PATH 'config.php');

// create a database connection

$registry->getObject('db')->newConnection( $configs['db_host_sn'],

$configs['db_user_sn'], $configs['db_pass_sn'],

$configs['db_name_sn']);

Firstly, we need to move the line that sets the controller variable to just before

authentication is checked We then wrap the authentication check line in an IF

statement, so that it is only executed if the controller being requested isn't the

API controller

$controller = $registry->getObject('url')->getURLBit(0);

if( $controller != 'api' )

{

$registry->getObject('authenticate')->checkForAuthentication();

}

Ngày đăng: 04/07/2014, 22:20

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

  • Đang cập nhật ...

TÀI LIỆU LIÊN QUAN