Giter VIP home page Giter VIP logo

restserver's Introduction

Jacwright RESTServer v1.2.0

A PHP REST server for providing a very light-weight REST API. Very easy to set up and get going. Independent from other libraries and frameworks. Supports HTTP authentication.

Simple REST server in PHP

After building a couple of RESTful services using the Zend Framework, I decided to create a dead simple REST server that allowed me to skip all the features I didn’t need as well as a tons of classes that came with Zend Framework MVC. There are still useful features to add (XML support for example), but overall I’m quite happy with what I’ve come up with.

My solution, RestServer, is a JSON REST server, so far. It should be trivial to add support for XML or other formats, but there would have to be assumptions on what your object would look like in XML (XML-RPC style, your own custom XML format, etc). First we’ll look at the classes that you write to handle the requests, then we’ll look at how to tie it together in your index.php file.

REST Controllers

The RestServer class assumes you are using URL rewriting and looks at the URL from the request to map to the necessary actions. The map that gets a request from URL to class method is all in the doc-comments of the classes. Here is an example of a class that would handle some user actions:

class TestController
{
    /**
     * Returns a JSON string object to the browser when hitting the root of the domain
     *
     * @url GET /
     */
    public function test()
    {
        return "Hello World";
    }

    /**
     * Logs in a user with the given username and password POSTed. Though true
     * REST doesn't believe in sessions, it is often desirable for an AJAX server.
     *
     * @url POST /login
     */
    public function login()
    {
        $username = $_POST['username'];
        $password = $_POST['password'];
        // validate input and log the user in
    }

    /**
     * Gets the user by id or current user
     *
     * @url GET /users/$id
     * @url GET /users/current
     */
    public function getUser($id = null)
    {
        if ($id) {
            $user = User::load($id); // possible user loading method
        } else {
            $user = $_SESSION['user'];
        }

        return $user; // serializes object into JSON
    }

    /**
     * Saves a user to the database
     *
     * @url POST /users
     * @url PUT /users/$id
     */
    public function saveUser($id = null, $data)
    {
        // ... validate $data properties such as $data->username, $data->firstName, etc.
        $data->id = $id;
        $user = User::saveUser($data); // saving the user to the database
        return $user; // returning the updated or newly created user object
    }

    /**
     * Gets user list
     *
     * @url GET /users
     */
    public function listUsers($query)
    {
        $users = array('Andra Combes', 'Valerie Shirkey', 'Manda Douse', 'Nobuko Fisch', 'Roger Hevey');
        if (isset($query['search'])) {
          $users = preg_grep("/$query[search]/i", $users);
        }
        return $users; // serializes object into JSON
    }
}

Let’s walk through the above TestController class to talk about the features demonstrated. First we’ll look at the test method. You’ll notice there is a new kind of doc-comment tag in the docblock. @url maps a URL to the method below it and is in the form:

@url <REQUEST_METHOD> <URL>

In this particular example, when someone does a GET on http://www.example.com/ (assuming example.com is where our service is located) it will print out:

"Hello World"

which is a valid representation of a string in JSON.

Moving on to the next method, login, we see the @url maps any POSTs to http://www.example.com/login to the login method. Getting data from a regular web-type POST is the same as any PHP application, allowing you to use your own validation or other framework in conjunction with this REST server. Sessions can also be kept if desired. Though keeping sessions isn’t true REST style, often all we want a REST server for is to serve up data to our ajax application, and it can be easier to just use sessions than something more RESTful.

Next we have our getUser method (you’ll notice that it doesn’t really matter what I name my methods because our @url directives define what URLs map to the method). You can see a couple of things here. First, we have multiple @url mappings for this method. And second, there is an odd /$id in that first URL mapping. RestServer treats any :keyword placeholders as wildcards in the URL and will take that section of the URL and pass it into the parameter with the same name in the method. In this example, when hitting http://www.example.com/users/1234, $id will equal 1234. When hitting http://www.example.com/users/current, $id will equal null. It doesn’t matter what order your parameters are in, so long as they have the same name as the placeholder (:id and $id, :username and $username). You’ll also want to be sure to make your parameters optional ($id = null) when you have several URL mappings that don’t all require a parameter. Otherwise you’ll have an error thrown telling you that you didn’t pass in a required parameter.

One last thing to note in getUser is that this method simply returns a User object. This gets serialized into JSON (or potentially XML) and printed out for consumption by the application.

Next we have to saveUser. You see here we have multiple URL mappings again. This time they also have different HTTP methods (POST and PUT) for creating and updating a user. The new thing here is the $data variable. This is a special keyword parameter that will contain the value of whatever was POSTed or PUT to the server. This is different than your regular web POST in that it doesn’t need to only be name-value pairs, but can be as robust as JSON, sending complex objects. For example, the body of a regular web POST, let’s say the login request, might look like this:

username=bob&password=supersecretpassw0rd

but POSTing a new user object for our saveUser method could look like this:

{ "username": "bob", "password": "supersecretpassword", "firstName": "Bob", "lastName": "Smith" }

So you’re able to allow POSTing JSON in addition to regular web style POSTs.

Finally we get to listUsers method. It is simple as test method. but $query parameter is the new. This special parameter can be used to read query string. and hold query string parameters as associated array. for example if client request this API with url /users?search=Manda then $query parameter will hold [search => Manada].

I call these classes that handle the requests Controllers. And they can be completely self-contained with their URL mappings, database configs, etc. so that you could drop them into other RestServer services without any hassle.

REST index.php

In order to get the whole server kicked off, you’ll want to create an index.php file, have your URL rewriting direct requests to it (another topic which you can learn about elsewhere), and create the RestServer and add controller classes to it for handling. RestServer will cache the URL mappings between requests using APC or a file to speed up requests. You won’t have to load every controller file on every request if you use autoload and this cache, only the one needed for the request. The cache only runs in production mode. Here is an example index.php file:

spl_autoload_register(); // don't load our classes unless we use them

$mode = 'debug'; // 'debug' or 'production'
$server = new RestServer($mode);
// $server->refreshCache(); // uncomment momentarily to clear the cache if classes change in production mode

$server->addClass('TestController');
$server->addClass('ProductsController', '/products'); // adds this as a base to all the URLs in this class

$server->handle();

That’s it. You can add as many classes as you like. If there are conflicts, classes added later will overwrite duplicate URL mappings that were added earlier. And the second parameter in addClass can be a base URL which will be prepended to URL mappings in the given class, allowing you to be more modular.

You can view the RestServer class, copy it and use it for your own purposes. It is under the MIT license. Features to be added include XML support and HTTP Authentication support. If you make this class better please share your updates with everyone by leaving a comment. I will try and keep this class updated with new features as they are shared. I hope you enjoy!

Good luck and let me know if you end up using it!

Update: I am including an example .htaccess file for anyone who might need it. It will only rewrite requests to files that don’t exist, so you can have images, css, or other PHP files in your webroot and they will still work. Anything that would give a 404 will redirect to your index.php file.

DirectoryIndex index.php
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule ^$ index.php [QSA,L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php [QSA,L]
</IfModule>

Authentication

Authentication is unique for each application. But tying your authentication mechanisms into RestServer is easy. By simply adding a method named authorize to your Controller all requests will call that method first. If authorize() returns false, the server will issue a 401 Unauthorized response. If authorize() returns true, the request continues on to call the correct controller action. All actions will run the authorization first unless you add @noAuth in the action's docs (I usually put it above the @url mappings).

Inside your authentication method you can use PHP's getallheaders function or $_COOKIE depending on how you want to authorize your users. This is where you would load the user object from your database, and set it to $this->user = getUserFromDatabase() so that your action will have access to it later when it gets called.

RestServer is meant to be a simple mechanism to map your application into a REST API. The rest of the details are up to you.

Cross-origin resource sharing

For security reasons, browsers restrict cross-origin HTTP or REST requests initiated from within scripts. So, a web application using REST APIs from browsers, could only make API requests to its own domain. To override this restriction RestServer can be configured to allow cros-orign requests, by including following code in REST index.php file.

    /**
     *
     * include following lines after $server = new RestServer($mode); 
     */
     $server->useCors = true;
     $server->allowedOrigin = 'http://example.com';
     // or use array of multiple origins
     $server->allowedOrigin = array('http://example.com', 'https://example.com');
     // or a wildcard
     $server->allowedOrigin = '*';

Throwing and Handling Errors

You may provide errors to your API users easily by throwing an excetion with the class RestException. Example:

    /**
     * Gets the user by id or current user
     *
     * @url GET /users/$id
     * @url GET /users/current
     */
    public function getUser($id = null)
    {
        if ($id) {
            $user = User::load($id); // possible user loading method

            if (!$user) {
                throw new RestException(404, 'User not found');
            }

        } else {
            $user = $_SESSION['user'];
        }

        return $user; // serializes object into JSON
    }

You have control over how your REST service handles errors. You can add an error controller using $server->addErrorClass('ErrorController');. This controller can define methods named handle401 or handle404 to add your own custom error handling logic.

Installation

By Hand

cd <your project>
mkdir -p vendor/jacwright/RestServer
cd vendor/jacwright/RestServer
git clone https://github.com/jacwright/RestServer .
composer install
cd <your project>
composer require 'jacwright/restserver:dev-master'

restserver's People

Contributors

33mhz avatar akasparas avatar carcabot avatar chialunwu avatar guitarneck avatar jacwright avatar jk avatar luciancd avatar mprtenjak avatar nasirbest avatar ossarotte avatar scimon avatar shades3002 avatar stevleibelt avatar tyzoid avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

restserver's Issues

Usability on Microsoft IIS

On IIS on Window there seems to be an issue with the definition of the root path.

I've aded this simple line after line 68 of RestServer.php

// Set the root
$dir = dirname(str_replace($_SERVER['DOCUMENT_ROOT'], '', $_SERVER['SCRIPT_FILENAME']));
$dir =  str_replace('\\', '/', $dir);

I'm new to github so not sure how to push this.

Great project by the way!

adding a directory of classes

I added this to code, I have and autoloader included in my framework so it works well

// this is to use with magic autoinclude.
public function get_dir_classes($lib_dir,$subdir,$seperator="_",$recurse=true,$follow_symlic=false){
    $classes=array();

    $full_dir = $lib_dir.DIRECTORY_SEPARATOR.$subdir;

    //using the opendir function
    $dir_handle = @opendir($full_dir) or die("Unable to open $full_dir");
    //running the while loop
    while ($file = readdir($dir_handle)){
        if($file!="." && $file!=".."){
            if(strpos($file,'.php')>0){
                //echo "<a href='$file'>$file</a><br/>";
                $classes[] = str_replace(DIRECTORY_SEPARATOR,$seperator,$subdir).$seperator.str_replace('.php','',$file);
            } elseif($recurse && is_dir($full_dir.DIRECTORY_SEPARATOR.$file) && ($follow_symlic || !is_link($full_dir.DIRECTORY_SEPARATOR.$file)) && $file<>'.svn') {
                $more_files = $this->get_dir_classes($lib_dir,$subdir.DIRECTORY_SEPARATOR.$file,$seperator,$recurse,$follow_symlic);
                $classes = array_merge($classes,$more_files);
            }
        }
    }
    //closing the directory
    closedir($dir_handle);
    return $classes;
}

public function add_dir($libdir,$subdir='rest',$basePath = '',$seperator="_",$recurse=true,$follow_symlic=false){
    $list = $this->get_dir_classes($libdir,$subdir,$seperator,$recurse,$follow_symlic);
    foreach($list as $class){
        // function get_dir_classes adds the prefix and seperator to class name for autoloading
        $this->addClass($class,$basePath);
    }
}

oauth example

Hello,

Does anybody have any working example for authentication with oauth ?

Thanks.

Relations many to many using REST API

According to the Publisher-Book-Author design model, the Many-to-Many relationship appears between Book and Author. One book may have no or many authors books, one author may authored no or many books.
How to treat it?

Entry point not on the root

Hello,

I'm trying to install RestServer on my dev environment, my entry point is not on the root of the server but in a "api" directory : http://dev.com/my_username/api/index.php

But URLs/Path are different, I added a var_dump() line 254 (between the 2 if) and I had 👍

string(20) "my_username/api/client"
string(22) "/my_username/api/client"

So, it failed for the next condition ($url == $this->url), and I had a 404.

My temporary fix was to comment the following code in addClass method :

if (substr($basePath, 0, 1) == '/') {
    $basePath = substr($basePath, 1);
}

The / is not removed, and it works like a charm now...

Did I miss something in the config?

Thanks.

Composer Package

i've used your framework and must admit it is pretty easy and cool for micro-small projects. i'm hoping You/ We can look at packaging it with probably Idiorm & Paris to offer a nice project framework start up.

handleError not verbose in production

Hello,

Sometimes, datas from the client are bad and I need to send a 400 error with an explicit error message. But in production mode, we don't have messages:
$message = $this->codes[$statusCode] . ($errorMessage && $this->mode == 'debug' ? ': ' . $errorMessage : '');

I really need to send error messages in production, maybe only on 4xx errors?

json data with POST or PUT

Hi everyone!

I'm just using this class for a while when Cappuccino 0.9.5 came out. My Cappucino web application uses this RestServer on the backend side pushing raw json data via PUT or POST. But, it seems that RestServer doesn't accept my json data. Here is the code on the client side:

    var content = "{login:"+ [loginTextField objectValue] +", password:"+ [passwordTextField objectValue] +"}";
    var contentLength = [[CPString alloc] initWithFormat:@"%d", [content length]];

    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:content];
    [request setValue:contentLength forHTTPHeaderField:@"Content-Length"];
    [request setValue:"application/json" forHTTPHeaderField:@"Content-Type"];

The backend side code is this one:

    /**
     *
     * @url POST    /login
     */
    public function login( $data )
    {
        $query = "
            SELECT  *
            FROM    users
            WHERE   login = '".$data->login."'
            AND     password = '".$data->password."'";
        return $this->db->query($query, true);
    }

My log on the backend side says me that all given parameters ('logon' and 'password' here) are never passed through.
What I'm doing wrong here? Is my HTTP header correct?

"Thank you for your co-operation" ™

Callback support for JSONP

Absolutely love this. Fantastic for playing around and sketching out APIs.

JSONP support is baked into jQuery and a few other libraries and seems fairly standardised around the notion that if you provide a callback parameter, the server should respond by wrapping the JSON response in that callback function e.g:

/api/mydata/?callback=myfunc

Returns

myfunc(jsondata);

With a text/javascript header rather than application/json

To me it looks like a pretty simple addition but just wondering if it had been considered and rejected for any reason?

DocumentRoot with trailing slash causes incorrect root.

On localhost, my DocumentRoot is "/Applications/MAMP/htdocs".
On my development environment, my DocumentRoot is "/var/www/html/".

On line 74, dirname('/index.php') returns '/' on localhost, but on development, dirname('index.php') returns '.' to the $dir variable.

On line 75, there's a nested ternary operator that is supposed to assign the root variable, but it is not assigning correctly on my development environment, which causes the routes to mismatch.

For example:

$restServer->addClass('FeedController', '/feed');

This causes the urls to mismatch on line 243. On localhost, it correctly matches $url and $this->url as 'feed/endpoint'. But on development, it incorrectly matches $url to 'feed/endpoint' and $this->url to '/feed/endpoint'.

I suspect that the ternary on line 75 was to account for DocumentRoot trailing slashes, but because it is nested or because the logic is faulty, it is causes the routes to mismatch like it is doing above.

As a quick fix, I've made $this->root = '/' which is working on both my localhost and development environment.

Any help is appreciated!

Parse error

I just copied over the example to my server and am getting this error in RestServer.php:

Parse error: syntax error, unexpected '[' in /home/content/46/12363346/html/gomedina/REST/RestServer-master/RestServer-master/source/Jacwright/RestServer/RestServer.php on line 260

permission denied in destructor

Hello again,

Thank you for fixing issue #20 so quickly. Now I have encountered a different problem.

As before, everything works fine when the RestServer is started in "debug" mode. This happens when I switch it to "production" mode:

$server = new RestServer('production');

When I visit the link, the following text is displayed, slightly modified for a public bug report:

[{"A":"1","B":"5"}]<br />
<b>Warning</b>:  file_put_contents(./urlMap.cache) [<a href='function.file-put-contents'>function.file-put-contents</a>]: failed to open stream: Permission denied in <b>/home/A/B/C/RestServer.php</b> on line <b>86</b><br />

The first line, up through the closing square bracket, is the expected output of that page. But then there is that permission denied error regarding ./urlMap.cache.

So I made a test PHP script with just one file_put_contents() call, and that worked just fine--it created the file and wrote to it. Then I wondered if this problem might be happening because the call to file_put_contents() is in a destructor. So I added this statement to the destructor:

echo realpath('.');

and it printed out /usr/local/bin
So that explains the permission denied error. Since this is running on shared hosting, of course I would not have permission to write to /usr/local/bin.

This stackoverflow page addresses this issue, and the accepted answer points out that the PHP manual mentions this very possibility: "Destructors called during the script shutdown have HTTP headers already sent. The working directory in the script shutdown phase can be different with some SAPIs (e.g. Apache)."
http://stackoverflow.com/questions/6629061/php-file-creation-write-within-destructor

When I changed this line (line 56):

public $cacheDir = '.';

to

public $cacheDir = __DIR__;

it worked as expected.

Maybe you have a better idea of what to do to solve this. I will of course be glad to test whatever you decide to do.

Please let me know if you have any questions or need any additional information.

Thank you.
James Dietrich

Is there a way to sleep response for a while?

Hello,

I am using PhpServer for a while, it is so simple to implement. Thanks for it.

I have a generic question, I want to slow the response time say 5 secs on every call.
I tried sleep in controller method didnt help? any suggestion pls.

Karttin

$data object is not filled in PUT requests

I have a PUT request but the $data object is not filled:

    /**
     * Edit an author
     *
     * @url PUT /author/$id
     */
    public function editAuthor($id = null, $data) {
        print_r($data); // ""
        ...

Is this a bug?

document_root problems

on creating the object, the root path could be different in a linux and windows php server. it comes without slash in the beginning, causing 400 error... fixing in the class creator.

    if ($dir == '.') {
      $this->root = '/'; 
    }
    else {
        if (substr($dir, -1) != '/') {
            $dir = $dir . '/';
        }   
        if (substr($dir, 1) != '/') {
            $dir = '/' . $dir;
        }   
        $this->root = $dir;
    }  

Error Response status comes as 200 always

Hi,

In my new deployment I am getting a strange problem, all works fine in my local build. When i deploy the same to Server, RestException - response status is always 200 instead of throwing 401, 404 etc status.

throw new RestException(401, "Password empty not allowed");

In local build:
Status
401
Unauthorized

Response:
{
"error": {
"code": 401,
"message": "Empty password not allowed"
}
}

But in my development server:
Status:

200
OK

Response:

{
"error": {
"code": 401,
"message": "Empty password not allowed"
}
}

Any idea what could be wrong.

Kind Regards
Kay

Lazy loading without generating a map

I knew that this day would come: Generating a map of the whole API and all its classes is quite cumbersome and isn't a good decision when it comes down to performance. When you also don't have any cache at hand it gets pretty sluggish on every request.

My intention by opening this issue is a refactoring on that topic, so that the class facilitates an autoloader which only loads the class which matches the requested URL. So the first advantage would be that you don't need so much memory by loading any possible class into memory. And on the other side, you have the advantage that you don't have to generate the map for all classes. Just for the requested one and its methods/actions.

Using an autoloader will change the behavior of the RestServer class, so that it loads every class it's able to load. I suggest that there will be a mechanism which prevents certain classes from being autoloaded. Perhaps a class comment like:

/**
 * @noUse
 */
class DoNotLoadThisClass {}

I consider this as a draft, any opinions on that proposal?

POST not working

Hi !

Thanks for your job, very nice !
I have two methods GET who works perfectly, but my POST method not works :
/**
* Saves a content
*
* @url POST /files/$filename
*/
public function saveFile($filename, $data)
{
return $data;
}
The server respond 404 - Not found

If you get it before ?

Thanks

changes you made and I made :)

looks like this code went from a format of @url GET /foo/:var to @url GET /foo/$var
also, with the root element.
$this->root = ($dir == '.' ? '' : trim($dir,'/') . '/');
this works well for me.
I also applied the changes made by jk
thanks.

can't get resource

I can't get resource at link example.com/v1/resource/abc.png
can you explain me how to fix it or what i forgot when config ? Thank

.htaccess file is no longer working

Hello,
I had everything working great then my IP upgraded his version of Apache web server and upgraded my PHP to 5.6 I started getting Server 500 errors and I think I trace it back to the

.htaccess file, I'm using the below code. (which was working).
is there a upgrade to this file for newer Apache server or should it work on any version of Apache
Apache 2.2 to 2.4

# Apache needs to let you overwrite this (AllowOverride Indexes or AllowOverride All)
DirectoryIndex index.php
<IfModule mod_rewrite.c>
    # Turn Rewrite Engine on
    RewriteEngine On
    # Send all requests to index.php (index.php will parse the request url and routes accordingly)
    RewriteRule ^.*$ index.php [QSA,L]
</IfModule>

Rest Response Format

How does one change the Response format e.g. return an html response rather than a json response?

Calling rest without parameters

Hi,

I'm using the code below:

/**
 * Get Charts

 * @url GET /charts
 * @url GET /charts/$id
 * @url GET /charts/$id/$date
 * @url GET /charts/$id/$date/$interval/
 * @url GET /charts/$id/$date/$interval/$interval_months
 */
public function getCharts($id=null, $date=null, $interval = 30, $interval_months = 12) {
    echo "$id, $date, $interval, $interval_months";
            .....

But, when I call (from browser) /charts (without any parameter) I get this result from the echo above:
0, 1, 2, 3

Am I doing something wrong? is this a bug? Does it work this way by design?

Thanks
Federico

Cyrilics encoding problem

Result data is encoded by json_encode() in format \u0415\u0413. The solution is to add an option JSON_UNESCAPED_UNICODE

public function sendData($data) {
.....
+ $options = $options | JSON_UNESCAPED_UNICODE;
echo json_encode($data, $options);
}

PUT variables

How to get the put variables?

This is my curl request:
curl -i -H "Accept: application/json" -X PUT -d description=test http://..../100

My code:

    /**
     * Update a link
     * @url PUT /$id
     */
    public function updateLink($id = null, $data)
    {
        var_dump($data);
    }

I thought that the $data variable is the requested variables but it doesn't work (returns NULL)

problem with "production" mode

Hi,

I got things working the way I wanted them to in my project using RestServer. It's worked quite well; thanks for making the code available.

Then I noticed that in index.php the RestServer was being started in "debug" mode. So I switched it to "production" mode:
$server = new RestServer('production');

But then it didn't work anymore, and the following errors were produced. (I have replaced part of the path with A/B/C.)

[05-Jun-2014 07:48:31 America/Denver] PHP Notice: Undefined variable: map in /home/A/B/C/RestServer.php on line 220
[05-Jun-2014 07:48:31 America/Denver] PHP Warning: Cannot modify header information - headers already sent by (output started at /home/A/B/C/RestServer.php:220) in /home/A/B/C/RestServer.php on line 397
[05-Jun-2014 07:48:31 America/Denver] PHP Warning: Cannot modify header information - headers already sent by (output started at /home/A/B/C/RestServer.php:220) in /home/A/B/C/RestServer.php on line 398
[05-Jun-2014 07:48:31 America/Denver] PHP Warning: Cannot modify header information - headers already sent by (output started at /home/A/B/C/RestServer.php:220) in /home/A/B/C/RestServer.php on line 399

Please don't hesitate to let me know if there's any other information that would be helpful.

Thank you,
James Dietrich

Unable to get routing to work for new functions

I have setup my REST Server using your example and can successfully navigate to {SERVER}\RestApi which brings up "Hello World!".

However, when I navigate to anything else outside of the root, I get 404 Not Found errors for everything.

I have added a new basic function in my TestController:

    /**
     * Returns a list of sites
     *
     * @url GET /sites
     */
    public function getSites()
    {
        return "Site List";
    }

My index.php file looks like:

<?php
    $loader = include __DIR__ . '/vendor/autoload.php';

    require __DIR__ . '/vendor/RestServer/RestServer.php';
    require __DIR__ . '/controllers/TestController.php';

    spl_autoload_register(); // don't load our classes unless we use them

    $mode = 'debug'; // 'debug' or 'production'
    $server = new \Jacwright\RestServer\RestServer('debug');
    // $server->refreshCache(); // uncomment momentarily to clear the cache if classes change in production mode

    $server->addClass('TestController');

    $server->handle();
?>

And my .htaccess file looks like so:

# Apache needs to let you overrite this (AllowOverride Indexes or AllowOverride All)
DirectoryIndex index.php
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !index\.php$
    RewriteRule ^(.*)$ index.php [QSA,L]
</IfModule>

Then I am trying to navigate to {SERVER}\RestApi\sites

However, I cannot work out why it won't successfully redirect. If I add garbage to the .htaccess file I get internal server errors so I know it is reading my .htaccess file correctly.

Any ideas where I am going wrong?

Thanks

@url GET /dealer/:id - returns 404 error

Hello Jacwright,

Sounds silly but unfortunately, when i call this method it gives 404 error.
If i try the same with /dealer?id it seems work fine.

Not working code
URL requested: http://localhost/JA/dealer/1
/**
* @url GET /dealer/:id
*
*/
public function getDealer($id=null){
}
Throws 404 error

Working code:
URL requested: http://localhost/JA/dealer?id=1
/**
* @url GET /dealer
*
*/
public function getDealer(){
echo $_GET["id"];
}

Not sure this helps....
In findUrl() method, my request is going into "if (!strstr($url, '$')) {"

I added an echo statement just before

echo $url." - ".str_replace($this->root, '', $this->url);
if ($url == str_replace($this->root, '', $this->url)) {

dealer/:id - dealer/1

its failing at this point.

Any help appreciated.

Using RestServer without ReWrite

is there any way we cant use REST without the URLRewrite?

also can we map GET parameters to paths thus

e.g.

rest/?endpoint=user

can resolve to

/**
* @url GET rest/$endpoint/user
*/

parameters with period do not work

I have a method like:

/**
* Returns a parameter
*
* @url POST /parameter/$parameter
*/
public function parameter($parameter = null)
{
return $parameter;
}

My request is /parameter/12334556.pdf

From above method I get 12334556 and should be 12334556.pdf

Autoloading Classes in composer

Not sure if this is by design but I notice that RestServer contains multiple classes in a single file. when installed by composer

I'm encountering a problem where by RestException class can only be instantiated if I instantiate the RestServer class thus while

$server = new  \DeathMiner\RestServer\RestServer;
$exception = new \DeathMiner\RestServer\RestException;

succeeds

$exception = new \DeathMiner\RestServer\RestException;

throw an error

Class DeathMiner\RestServer\RestException not found

please advise as I am new to this composer utility

nginx 500 status

Hi,

I am trying to use RestServer.php in a nginx.

I have changed the htaccess to conf as mentioned in this http://stackoverflow.com/questions/10102616/i-cant-make-restler-work

I am getting a 500 error status

Same code works fine in Apache.

if (method_exists($obj, 'init')) { $obj->init(); //here i am getting 500 error } if (!$noAuth && method_exists($obj, 'authorize')) { if (!$obj->authorize()) { $this->sendData($this->unauthorized(true)); exit; } } $result = call_user_func_array(array($obj, $method), $params); if ($result !== null) { $this->sendData($result); }

Any help appreciated.

Kay

failed to add functions

i try to add my own function , but not works
help me to add function in this code for making post request

"Logged in " . $username); } /_* \* Gets the user by id or current user * \* @url GET /users/$id \* @url GET /users/current _/ public function getUser($id = null) { // if ($id) { // $user = User::load($id); // possible user loading method // } else { // $user = $_SESSION['user']; // } return array("id" => $id, "name" => null); // serializes object into JSON } /_* \* Saves a user to the database * \* @url POST /users \* @url PUT /users/$id _/ public function saveUser($id = null, $data) { // ... validate $data properties such as $data->username, $data->firstName, etc. // $data->id = $id; // $user = User::saveUser($data); // saving the user to the database $user = array("id" => $id, "name" => null); return $user; // returning the updated or newly created user object } /_* \* Get Charts \* \* @url GET /charts \* @url GET /charts/$id \* @url GET /charts/$id/$date \* @url GET /charts/$id/$date/$interval/ \* @url GET /charts/$id/$date/$interval/$interval_months _/ public function getCharts($id=null, $date=null, $interval = 30, $interval_months = 12) { echo "$id, $date, $interval, $interval_months"; } /_* \* Throws an error \* \* @url GET /error */ public function throwError() { throw new RestException(401, "Empty password not allowed"); } }

404 when new function is added

Hi,

I'm having problems adding a new function in my code, the test or main is working good but when I created a new GET function and test it with postman I'm getting 404 error. This is how my function looks like:

        /**
         * Get all customers functions
         *
         * @url GET /customers/$id
         */
        public function getCustomers{
            return "customer information working...";
        }

It happens also if I use a POST method. There's something additional I need to to or implement?

Thanks in advance,

Post parameters $data not returning

Hello,

I am trying to use $data using POST option

Javascript:

$.ajax({ type : "POST",
url : '/test/1",
data :{somedata: 'test'},
success : function(json) {

   });

/**
*@url POST /test/$id
*/
public function getData($id=null, $data){
//$data is undefined
// if i use $_POST['somedata'] it works
return array();
}

Am i missing something here?

Kind Regards
Karttin

doccomments problem.. disabling eacellerator works!

disabling eaccelerator to doccoments start to work.

in .htaccess:

php_flag eaccelerator.enable 0
php_flag eaccelerator.optimizer 0
DirectoryIndex index.php

RewriteEngine On
RewriteRule ^$ index.php [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]

Error in RestServer.php

Created a new Virtual Host, fresh install of RestServer.
Copied the example over to the root folder of the Virtual Host and got the following error.

PHP Parse error: syntax error, unexpected '[' in /RestServer/source/Jacwright/RestServer/RestServer.php on line 250

Checked the RestServer.php on line 250 and the error makes no sense.

Any ideas?

$data structure

Hi,

I'm sending information to my PHP from salesforce.com across a httpRequest, in the body I'm sending something like this:

{
"Contract" : [ {
"Id" : "800e0000000AoPNAA0",
"Name" : "Diana Guadalupe Camacho Jimenez",
"ContractNumber" : "00038248",
"N_mero_de_contrato__c" : "999999"
} ]
}

Debugging what is the value in $data it has something like this:

{Contract=({ContractNumber=00038248, Id=800e0000000AoPNAA0, N_mero_de_contrato__c=999999, Name=Diana Guadalupe Camacho Jimenez})}

How can I access to this properties?. I tried access with $data -> Id but it returns null.

Thanks in advance.

Content-Type response text/plain;charset=UTF-8 No JSON

Hi guys,

I'm running a GET method but in specific returning an object or a simple array is getting text/plain instead JSON here's mi function:

  /**
        * Returns a JSON string object with all geolocations with projects and stations
        *
        * @url GET /points/
        */
public function getEstaciones(){ 
      return array("success" => "Logged in ");
}

Do I need to set something additional here?

example dont work

hi,

ive tried the example but it always returns: 404 Not Found

pls help me

What is the format using DELETE

I tried passing the $data variable in through the function and accessing by $data->id, but this gives an error in the Rest Server. The body sent was {"id":"1"}. I also tried just putting $id in the function call and this also gave an error. There is no mention of DELETE in the example code. I am however very impressed with the simplicity of the rest server.

Do I send in the id as raw json in the body or as a url parameter as in GET

Apache settings to implement in production environment

Hi,

I modified the script to publish it in a developer server instance, there everything is working fine but when I deployed it to production It is not working. I activated mode_rewrite in my apache configuration file also i restarted apache.

AllowOverride is seted as None

And I would like to know if I need to setup other variables in my file, for security reasons in the company I only need to have access to my RESTServer folder.

Do you have any suggestions?

Thanks in advance!

URL with more than one level i.e. /lev1/lev2 does not work

Hi,

Following the example with TestController and changing i.e. the login function to @url GET /login/test and this will return "yay". It does not work for me somehow, it will return { "error": { "code": 404, "message": "Not Found" } }.

Note that everything works well if i use URLs with only one level i.e. change /login/test to /login.

/**
 * Logs in a user with the given username and password POSTed. Though true
 * REST doesn't believe in sessions, it is often desirable for an AJAX server.
 *
 * @url GET /login/test
 */
public function login()
{
    return "yay";
    // validate input and log the user in
}

Any suggestions?

how to add Access-Control-Allow-Origin

I am trying to access my service from another site and getting the following error:

XMLHttpRequest cannot load http://ibds.comp-solutions.org.uk/login. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

How do I add 'Access-Control-Allow-Origin', Can I do this for more than one site or even allow all sites?

Sample files for each "Method Types"

Hello,

First of all thank you for providing a clean and simple RestServer implementation.

It will really helpful if you could post some examples for

  1. How to use @nOAuth
  2. How to use GET, POST, PUT, DELETE

Waiting to know your response.

Regards
DeveloperOneX

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.