3
\$\begingroup\$

I met the RESTful ideology and I fell in love with it. However the only request methods supported by HTML forms so far are GET and POST, which is kind of sad, because this means that to use REST as it's supposed to be used I need to use some work around which is likely to not be pretty, as it really is.

So the only way I found I can send PUT or DELETE requests is from the XhrHttpRequest object in JavaScript.

How I send data seems pretty simple:

xhr = new XMLHttpRequest();
xhr.open('PUT' /*for example*/, URL, true);
xhr.send('MyData=HelloWorld');

Then on the other side I fetch the data:

class Input {
    private static $input;

    public static function init(){
        parse_str(file_get_contents('php://input'), self::$input);
    }

    public static function data($key = null){
        return $key ? self::$input[$key] : self::$input;
    }
}

Input::init();

My concern is that the header Content-Type is always text/plain;charset=UTF-8 no matter what the request type is, as opposed to using standard form submission, where Content-Type becomes application/x-www-form-urlencoded. I can of course put that on POST requests as well but in this case what should I put on PUT and DELETE requests?

Are there any potential problems I may run into with browsers by using this nonstandard method of sending requests? Do you see any drawbacks in general, apart the one that users who don't run JavaScript will be unable to use my site?

P.S.: I was wondering, if it turned out OK to use this method, wouldn't it be more efficient and secure to use JSON formatting to send data instead of the query string one I have shown in the example? I primarily want to avoid the query string format because I remember reading that JavaScript's URL encoding functions aren't the best.

\$\endgroup\$
1
\$\begingroup\$

You can set header fields with the .setRequestHeader method, for example:

xhr = new XMLHttpRequest();
xhr.open('PUT' /*for example*/, URL, true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify({MyData: 'HelloWorld'});

JSON is a good format for receiving responses from a RESTful API, from server to client. But for passing data in the other direction, from client to server, it's better to use query parameters or a FormData object (if your browser supports it), for example:

var data = new FormData();
data.append('user', 'person');
xhr = new XMLHttpRequest();
xhr.open('PUT' /*for example*/, URL, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(data);

Btw, I find this blog post extremely useful for designing a RESTful API:

http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api

Passing parameters to the server

It will help to explain this in the context of the example on the blog post I recommended earlier:

  • GET /tickets - Retrieves a list of tickets
    • Query parameters are acceptable to adjust the formatting and output fields
    • The most important "input" is the URL component /tickets
  • GET /tickets/12 - Retrieves a specific ticket
    • Query parameters are acceptable to adjust the formatting and output fields
    • The most important "input" is the URL component /tickets/12
  • POST /tickets - Creates a new ticket
    • All parameters should be posted as form data
  • PUT /tickets/12 - Updates ticket #12
    • All parameters should be posted as form data
  • PATCH /tickets/12 - Partially updates ticket #12
    • All parameters should be posted as form data
  • DELETE /tickets/12 - Deletes ticket #12
    • No parameters

The common ways of passing data to the server:

  • Query string with key-value pairs
  • Form data with key-value pairs
  • Cookies with key-value pairs

Basically it's always key-value pairs. You could send JSON embedded inside a value, but it's not natural. The server has to deserialize it. Given some client-side parameters as key-value pairs, why pass to the server somekey => json_encoded_blob_of_key_value_pairs when you can pass the key-value pairs in a more direct way.

\$\endgroup\$
  • 2
    \$\begingroup\$ Why is JSON a good format for response data but not request data? Also setting the application/x-www-form-urlencoded header will have PHP parse the input and fill it into $_POST even if the request method is not POST, which is not correct. Please support your statements with arguments. \$\endgroup\$ – php_nub_qq Aug 28 '14 at 8:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.