Hey Graham,
Post by Graham ChartersHi Rob, I like your ideas very much. The only thing I would like to
see is something at the annotation level which could be related to the
broader SCA (i.e. the Intents). I think this would then give us the
flexibility to specify some QoS requirements and then have it
configured via the associative array approach or the SCA policySet
approach.
/**
*
*/
We could then specify a policy array that defines what
$policy =
array('soap'=>array('authentication'=>array('local_cert'=>...,
'passphrase'=>...)));
The actual intents can be named whatever the developer likes, although
the SCA specs do define the meaning of a small set.
I'm not sure where the developer would provide the options, and that
may also affect flexibility - ie. would all uses of soap have to share
the same configuration?
Does something like this make sense?
Yes this does, but before worrying about the annotations which would
be on the server side of things, I think implementing something for
the client first would be the quickest way to provide a good amount of
functionality, while also demonstrating how it would work for the more
advanced things. Before thinking about all the questions you raised,
read my entire reply first. I answered the flexibility one at the end
as the examples I provided here hopefully lead to that answer.
I took the helloWorld SCA example from pecl. Now, say I needed to pass
a local cert and its passphrase so that the client can authenticate.
Here because this really isnt a specific intent other than I want to
send some SoapClient options, I would write it as:
include 'SCA/SCA.php';
$policy = array('soap'=>array('options'=>array('local_cert'=>...,
'passphrase'=>...)));
SCA::setPolicy($policy);
$greeting_service = SCA::getService('./wsdl/Greeting.wsdl');
/* For the following, the binding checks if any policies are set for
it.
Here it finds options, so the options are passed to the SoapClient
constructor. */
$greeting = $greeting_service->greet($name);
I called it "options" because thats what they are. Options for the
constructor.
This implementation would be the basis for future policies/intents,
such as authentication (which may possibly include the loca_cert stuff
from the above or limited to just WS-Security, etc..)
Going forward, saw we wanted to implement authentication on the
server.
These policies are not for every Soap server we have, just for this
particular one. By particular one I consider any class we use a
particular one.
If the developer wants different policies for the different methods,
then he makes different classes. I dont see why any logical grouping
of methods using the same binding would require different options.
Different options to me would mean that the methods do not belong
grouped together as they serve different unrelated purposed.
Anyways.... the code would look like:
include 'SCA/SCA.php';
$policy = array('soap' =>
array('authentication' => array(
'type' => 'usertoken',
'methodname' => 'validation');
SCA::setPolicy($policy);
/**
* @service
* @binding.soap
* @requires authentication
*/
class Greeting
{
private function validation($username, $password) {
return true;
}
/**
* @param string $name
* @return string
*/
public function greet($name)
{
return 'hello ' . $name;
}
}
The server would call the validation method with the username/password
and act upon the return value.
Then on the client side:
include 'SCA/SCA.php';
$policy = array('soap' =>
array('authentication' => array(
'type' => 'usertoken',
'username' => 'rob',
'password' => '123456',
'digest' => false);
SCA::setPolicy($policy);
$greeting_service = SCA::getService('./wsdl/Greeting.wsdl');
/* For the following, the binding checks if any policies are set for
it.
Here it finds authentication. It sees it is usertoken type, so creates
the WS-Security usertoken with the supplied username and password and
does not use password digest. */
$greeting = $greeting_service->greet($name);
Because there are no annotations on the client side, the client always
checks if there are any policies set and processes the ones it knows
how to process.
The flexibility lies with the options/policies being set on a per file
basis. Typically an endpoint utilizes the same authentication
mechanism for all of the exposed operations. The options/policies are
set as a static member of the SCA class, so would pertain only within
that scope. If different policies are desired, then the operations
should be separated out to their own endpoint. At least this is my
opinion on that.
DISCLAIMER: I'm also not saying lets jump right in and implement WS-*
or anything like that. I just used authentication as an example going
off of your post. Outside of the "options" policy, thought should be
given to what type of functionality would be most useful to the end
user (depends upon what binding type is used the most, what would it
benefit from the most, and is it doable) and then go from there rather
than just picking policies arbitrarily to implement.
Make note that the naming and structures I have used here are most
likely not optimal, nor are what I am suggesting. They were what came
to mind and allowed me to code these examples without too much
thought, but hopefully illustrate my point. Let me know if anything is
unclear?
Rob