Currently, when defining a Web Service, you can set $operation['data'] = 'some parameter' which causes the 'some parameter' paramater to be removed from the arguments, and added to the POST data. This works when there is only only one argument in the POST data, but not if there are multiple. We need to be able to support multiple POST paramaters for a single operation.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mrfelton’s picture

Status: Active » Needs review
FileSize
792 bytes

Patch to make required change.

klausi’s picture

Not sure this is the right approach. You could also define a complex data type that holds all properties that you want in your request body.

You are casting to an array here - does that change the body contents if $operation['data'] is a string?

mrfelton’s picture

Not sure this is the right approach. You could also define a complex data type that holds all properties that you want in your request body.

In my case the API expects to receive 3 paramaters. 2 of them are complex data types, and one is an API key. eg.

Member
 - name
 - address
 - etc
Credit card
 - cc number
 - expiry
API Key

Member and Credit Card are both complex datatypes that I have defined. To do what you are suggesting I would need to define one more complex data type, and make Member, Credit Card, and API key properties of that. But then what I would be passing into the remote function would be one paramater, and not the three that it expects.

You are casting to an array here - does that change the body contents if $operation['data'] is a string?

No, it makes no difference. if you cast a string to an array, you just get an array with one element.

klausi’s picture

Status: Needs review » Needs work

Well, the current patch breaks the RESTWS test case in wsclient_examples. It adds an additional wrapper with the parameter name around the object. Request body:

{
    "node": {
        "type": "cAzRng8r",
        "title": "cAzRng8r",
        "author": "1"
    }
}

But RESTWS expects only the inner structure:

{
    "type": "cAzRng8r",
    "title": "cAzRng8r",
    "author": "1"
}

So I still think you should create a data structure that holds the specific fields for your use case.

cknowles’s picture

I'm pretty new to Drupal but I've been trying to use this module for a few REST calls. First I realised the service I'm calling requires form data input but responds with XML data. I've sorted that using a HttpClientCompositeFormatter and HttpClientXMLFormatter from http_client inside a custom module. Then I realised I can't use the UI to customise the operation type so had to look into a custom module to do that too.

I've been trying to call a service based on a User account where I have to POST some data. Could you point me in the right direction of how to create the custom data structure you speak about above based on:

1) Some fixed parameters, preferably global to the service.
2) Fields from the user.

I know how to do this based on separate parameters to the operation - in fact that's what I did first using the UI module. But the module just adds those to the URL and doesn't execute a POST as required.

cknowles’s picture

For anyone looking at this, I worked out this is possible at least with the service I'm using. What I did was this in my custom module set the type of the operation to POST but then just not add a "data" attribute to the operation. Instead I added parameters and the POST of the form data works fine (it's just URL not body based):

    // User Create Operation.
    $operation = array();
    $operation['label'] = 'User Create';
    $operation['url'] = 'URL/users.xml';
    $operation['type'] = 'POST';
    $operation['parameter']['x'] = array('type' => 'text', 'label' => 'X');
    $operation['parameter']['y'] = array('type' => 'text', 'label' => 'Y');
    $operation['parameter']['z'] = array('type' => 'text', 'label' => 'Z');
    $operation['result'] = array('type' => 'wsclient_myclient_rest_user', 'label' => 'User');
    $service->operations['user_create'] = $operation;