Issues

ZF-7825: Zend_Rest_Controller postAction cannot access request data

Issue Type: Bug Created: 2009-09-10T19:26:06.000+0000 Last Updated: 2012-11-21T08:07:57.000+0000 Status: Resolved Fix version(s): Reporter: AJ Coon (ajcoon) Assignee: Matthew Weier O'Phinney (matthew) Tags: - Zend_Rest_Route

Related issues: Attachments:

Description

I am extending Zend_Rest_Controller, and in my postAction method trying to access variables in the post request. I am calling:

$this->view->username = $this->getRequest()->getParam('username');

The username value returned from getParam() is null.

I am making this exact same call in my getAction and it finds the value fine in the request. Is getParam() not the correct call for a post request?

Comments

Posted by Matthew Weier O'Phinney (matthew) on 2009-09-10T19:32:01.000+0000

Changed component and assignee.

Posted by Matthew Weier O'Phinney (matthew) on 2009-09-10T19:48:18.000+0000

What is the value of $this->getRequest()->getRawBody()?

What I'm getting at is: what kind of payload is being sent to the action?

I've used getParam() in my own code with all actions with success, so my suspicion is that the parameter is either not present, or is part of the raw body -- which you'll then need to parse.

Posted by AJ Coon (ajcoon) on 2009-09-10T19:56:29.000+0000

Here is my modified postAction

<pre class="highlight">
public function postAction() {
        error_log('this->getRequest()->getRawBody(): ' . print_r($this->getRequest()->getRawBody(),true));

        $this->view->username = $this->getRequest()->getParam('username');
        $this->view->requestid = $this->getRequest()->getParam('requestid');
        //$this->_forward('index');
    }

Here is the Apache error log output:

<pre class="literal">
==> /var/log/apache2/error.log <==
[Thu Sep 10 22:04:27 2009] [error] [client 127.0.1.1] this->getRequest()->getRawBody(): {"username":"ajcoon","password":"foobar","requestid":"4aa9be3b22fe98.65658205"}

So, the data is being passed in by the client....so then you're saying, I need to define parsing logic myself? I guess that makes sense...

Perhaps this could result in a feature request for a helper class to parse POST/PUT data based on content type?

Posted by Matthew Weier O'Phinney (matthew) on 2009-09-10T20:13:52.000+0000

So, yes, you've stumbled onto one of the pitfalls of the request object: it doesn't currently have a way to decode the raw request body based on the Content-Type passed in.

I've built up an action helper for myself that checks the Content-Type request header for the string "application/json" , and, if found, pulls the data from there, passes it to Zend_Json::decode(), and then passes that data back into the request object. It's trivial to write currently, but we do need a standard solution for this.

I'm closing the issue for now (as it's marked as a bug); when I get a proposal written for the new functionality, I'll link here to it.

Posted by AJ Coon (ajcoon) on 2009-09-10T20:16:33.000+0000

Great, thanks!

Posted by Luke Crouch (lcrouch) on 2009-09-11T12:14:06.000+0000

That's a good point. I think there's some RESTful Zend_Controller enhancements we should wrap up into a proposal as a consequence of people using Zend_Rest.

  1. Helper(s) to digest request bodies based on popular Content-Type values - xml, json, http-form-encoded
  2. Enhance ContextSwitch helper to be sensitive to Accept request headers for determining view modes so the format doesn't have to be in the URI

Others?

Posted by AJ Coon (ajcoon) on 2009-09-11T12:35:47.000+0000

I would add:

  1. Extending views to support the concept of one response, many formats, again based on the Accept header. What I've done in my REST controllers is this:
<pre class="literal">
ll application/views/scripts/helloworld/
total 24
-r--r--r-- 1 root root  82 2009-09-10 08:41 get.json.phtml
-r--r--r-- 1 root root 279 2009-09-09 16:40 _get_response.php
-r--r--r-- 1 root root  62 2009-09-10 08:41 get.xml.phtml
-r--r--r-- 1 root root  83 2009-09-10 23:16 post.json.phtml
-r--r--r-- 1 root root 279 2009-09-10 16:53 _post_response.php
-r--r--r-- 1 root root  63 2009-09-10 23:16 post.xml.phtml

I've defined a response structure in the _$action_response.php file. I then include this in my "resolvable" views, and just output different formats. For example:

cat application/views/scripts/helloworld/_get_response.php

<pre class="highlight">
<?php
$doc = new DOMDocument();
$doc->formatOutput = true;

$root_element = $doc->appendChild($doc->createElement("response"));
$root_element->appendChild( new DOMElement("requestid", $this->requestid));
$root_element->appendChild( new DOMElement("hello",$this->username) );

?>

cat application/views/scripts/helloworld/get.json.phtml

<pre class="highlight">
<?php
require('_get_response.php');
print Zend_Json::fromXML($doc->saveXML());
?>

cat application/views/scripts/helloworld/get.xml.phtml

<pre class="highlight">
<?php
require('_get_response.php');
print $doc->saveXML();
?>

What I'm envisioning is that the developer only has to implement the _$action_response.php file. Then, depending on the Accept format (assuming there is an encoder that supports it), we provide the encoding auto-magically. In my case, this would mean that by enabling json and xml in my ContextSwitch:

<pre class="highlight">
        $contextSwitch = $this->_helper->getHelper('contextSwitch');
        $contextSwitch->setAutoJsonSerialization(false);
        $contextSwitch->addActionContext('get', array('xml','json'))->initContext();\

...I've auto-magically made "get.json.phtml" and "get.xml.phtml" available as views.

Does this make sense?

Posted by Matthew Weier O'Phinney (matthew) on 2009-09-11T12:54:09.000+0000

In the projects I've been working on, I look for the Content-Type and Accept header in the request; based on that, I will then add all the various REST actions to the appropriate context (currently, only json). So, in the end, I'm doing similarly to what you describe.

As for the formatting -- I leave that entirely to my individual views. HTML, JSON, and XML all have very different needs, so I simply pass in the values, and then serialize them as necessary. One technique I'm using is to have my service layer always return Zend_Paginator objects for lists -- that way I know that I have the same general type of object, and there are particular serialization formats automatically available. (I've also built a view helper that will setup my "Content-Range" header based on the Paginator object, which is tremendously useful.)

I think having either ContextSwitch or a new action helper setup the ContextSwitch mappings for REST controllers makes sense; developers may always selectively switch off actions they don't want responding in the given format. Additionally, as Luke suggests, some automated scaffolding for pulling in the POST/PUT data based on the Content-Type of the request would be useful.

Posted by Luke Crouch (lcrouch) on 2009-09-11T14:13:12.000+0000

Matthew,

Do you want to write up a Zend_Rest proposal that incorporates all these? Or should we just make task tickets for them and get started? Or I can write a proposal if we want.

-L

Posted by nike shox (nike shox) on 2012-11-21T08:07:57.000+0000

Kanten of vulkanisert Salé is betont http://www.nikeshoxsko.biz with a fargerik 90'erne stil geometriske Mønster, which tar the already existing vintage Appell of this http://www.nikeshoxsko.biz silhuetten løbet top.Stop at the endClothing å legge the recent http://www.nikeshoxsko.biz Hardland from adidas Originals to the sneaker lineup today.

Have you found an issue?

See the Overview section for more details.

Copyright

© 2006-2016 by Zend, a Rogue Wave Company. Made with by awesome contributors.

This website is built using zend-expressive and it runs on PHP 7.

Contacts