I have attached a suggested patch for this. What it does is:
- only declare the add method in hook_xmlrpc, not the substract method
- declare a "bad" method in hook_xmlrpc, as an example of how to use the hook to hide a method from another module
- in hook_xmlrpc_alter, remove the bad method and add the substract method, as an example of how to add methods to another module
I've also fixed minor coder_review items.
FWIW, here is tiny python script to test the module:
import xmlrpclib
syo = xmlrpclib.ServerProxy("http://localhost/xmlrpc.php").system
for method in syo.listMethods():
if 'xmlrpc_example' in method:
print method + ': ' + syo.methodHelp(method)
| Comment | File | Size | Author |
|---|---|---|---|
| #72 | xmlrpc_example_72.patch | 22.82 KB | ilo |
| #70 | xmlrpc_example_68.patch | 22.83 KB | ilo |
| #68 | xmlrpc_example_68.patch | 22.77 KB | ilo |
| #60 | xmlrpc_example_60.patch | 13.66 KB | ilo |
| #50 | xmlrpc_multicall_50.patch | 13.58 KB | ilo |
Comments
Comment #2
fgmFWIW, the XMLRPC test is currently broken even without this patch, but this is another issue.
Comment #3
rfay@fgm, thanks for your work on this! Please fix the test in this issue though (HEAD status seems OK: http://qa.drupal.org/pifr/test/26934) because we can't commit until your patch is green.
Comment #4
fgmHere is the other issue with its patch #894972: XML-RPC test no longer passes
Comment #5
fgmexample_xmlrpc_alter.patch queued for re-testing, now that #894972: XML-RPC test no longer passes has been fixed.
Comment #6
fgmSimplified version.
Comment #7
fgmHm, patch is missing a few lines, need to reroll.
Comment #8
fgmRerolled.
Also fixed spelling of "substract".
Comment #10
fgmError is in core, not in this patch (form.inc test). Will have to retest once core is fixed.
Comment #11
fgm#8: example_xmlrpc_alter.patch queued for re-testing.
Comment #12
rfayA core commit seems to have broken form example, so I'm trying to solve that. Thanks for the good work!
Comment #13
rfayHEAD is fixed now. I'll get this reviewed and committed in the next week. Thanks so much for your work on this.
Comment #14
rfayUnfortunately, the spelling is in fact "subtract", so the changes here are wrong.
I'm also opposed to taking a very simple example and making it require an alter. Is there a way this can be done while *adding on* the alter? If people can understand it without understanding the alter, then I'm OK with it. But if they have to understand the basic approach *and* al alter, I'm not.
Thanks very much for the work and for sorting out the core API change.
substract misspelled
misspelled again.
Powered by Dreditor.
Comment #15
fgmFunny about the spelling: wiktionary and webster have both spellings, with the same definition and etymology. So no problem with either.
Regarding the hook_xmlrpc_alter (HXA) example, making the basic example require an alter may indeed make understanding more complex, or make devs think that this is required, when in fact this is just an optional step, like any *alter hook. An other way to to this would be to make the use of alter depend on a module setting, showing how the alter can be used to change something about a method, like introducing access control. Adding a new method is also possible, but there is no reason to use HXA for this, so using it to change access or change the callback of an other method seems (to me) better.
Comment #16
rfayI like the idea of enabling the alter based on a module setting. I think it would be better to conditionally alter the existing behavior than to alter a nothing-behavior like in #8. This will mean we have to explain a bit more in the xmlrpc_example_demo_form() so that people can discover the setting. And they don't have to grok the alter to grok the basic usage of xmlrpc.
Comment #17
fgmAnother idea: change the callback method based on ip_address(), gettimeofday() or whatever, to show how an identical web service can answer differently based on non-site/non-callback info ? This would avoid having to expose any setting.
Comment #18
rfayIt has to be obvious and easy to understand what's going on. The two techniques you suggest are confusing to everybody but the author (I use them often, but sometimes confuse even myself :-)
Perhaps only alter depending on a value in the payload?
Comment #19
fgmThere is no payload being passed to hook_xmlrpc(_alter) implementations, unless we do not use the word in the same sense.
The problem is that HXA is only needed to alter the HX implementation by core or another module. But since this is a single demo module, it can very well do the changes to its own HX implementations in the implementations themselves. The only implementations of HX in core, which we could want to alter, are the system.* ones.
Comment #20
ilo commentedSorry, but I'm going to bump seriously into this example:
- D6 and D7 examples of xmlrpc are very different
- D6 version does not have an UI to verify this example
Here is my proposal:
- xmlrpc example (for both D6 and D7) will include
- xmlrpc server code (with a settings form)
- xmlrpc client code (with a testing form)
The xml client part (basically it is a form)
- will include an endpoint field (where is the xmlrpc located, to localhost by default)
- a function field (probably grabbed automatically using xmlrpc:system.listMethods)
and fields to call the selected service.
The xml example server part
- A set of defined services (very simple) (addition and substraction of two values)
- add (arg1, arg2)
- sub (arg1, arg2)
- the hook_xmlrpc_alter can be used (with some values in the settings page) to insert a third argument (a session key or something like) in all the methods.. resulting in add( key, arg1, arg2) and sub(key, arg1, arg2)
the hook_xmlrpc_alter can't be backported to D6
May this be clear enough?
Comment #21
ilo commentedApologies, after reading the hook_xml_alter declaration I've come to the conclusion that it can't be used in that way. fgm, this _alter hook can only be used by the server to alter the input from the client before processing it, it can't be used to include/modify current xmlrpc methods defined in the server.
So, a new proposal:
Actually, I love the way xmlrpc example is declared in D7, so I'm going to backport 'as is' to D6 (as long as D6 does not support hook_xmlrpc_alter).
For the D7 part, the way to introduce hook_xmlrpc_alter and put some 'learning' skills there is explain clearly that it may alter the input from the client.. Due to the current example implementation it can be done by:
- remove or add services being called,
- change the service being called,
- change the arguments of the service
Any ideas?
Comment #22
fgmIt seems you misread how HXA works: it can actually not be used to alter the input from the client, because all it receives and modifies is the list of methods, so it only changes the methods, as you describe further in your explanation: change the method associated to a package.method description, change the parameters description, the help, the callback, and so on. A typical use case is per-IP service blocking independently of the methods implementing the services. But it can not alter the client data, since it never receives them anyway.
What it can do, though, is install an alternate callback in front of an existing one, and this callback can then act upon the data, possibly passing them back to the original callback is if has been designed to do so. Typically, this means something like this in pseudocode:
Existing signature on foo.bar: callback foo_bar($baz)
HXA implementation: alter $items['foo.bar'] so that callback = qux($baz)
function qux($baz) {
// perform something, maybe alter $baz
$raw_ret = foo_bar($baz);
// do some more work on $raw_ret
return $processed_ret;
}
A practical case of such a front method can be encryption wrapping for services methods not supporting it.
Comment #23
ilo commentedOh, I see, you are right, the description in the API confused me a little bit: "This hook lets at module modify the callback definition for already declared XML-RPC methods, when they are being invoked by a client." So, it allow to alter the methods and is called on every call to the services. Ok, I get the point (the previous one).
So clearly we need to find an use case where to implement this hook, and adding a new method is not the answer definitely. Modifying an existing method is the right way to do so, but what part? the callback?, the number of arguments? I'll be working on this patch tonight, so if you have an idea we can discuss here or on irc.
Thanks for the correction!
Comment #24
rfayWorks for me.
Comment #25
ilo commentedSo, I've separated client, server, and alterations part in the code, and documented each of them. I've updated the testcases to reflect all the changes. It is a major rewrite, I know, probably it is better to patch, and test, and then review the comments than trying to review the patch itself.
who will put some time on this review? ;)
Comment #26
ilo commentedok:Detect invalid patch format, Ensure the patch only contains unix-style line endings.
I'd try to.. now!
Comment #27
ilo commentedonce more and I give up..
Comment #28
ilo commenteduff.. apologies for this boring notifications, I have a devel environment just installed and I'm missing some configs to avoid all these situations..
Comment #29
ilo commentedarfm... I'll hate netbeans and tortoisecvs for the rest of my life! XD
Comment #30
ilo commentedJust changing the title according to the new patch and module code.
Comment #31
ilo commentedI have to fix a lot of issues pointed by chx on irc, so I'll be rewritting it.
Comment #32
ilo commentedUpdated with chx review:
- clearly specify what is required and what is optional to create a XML-RPC server or client.
- Notice that error numbers are arbitrary, selected for our implementation.
- Spelling and grammar issues, of course
- Comments now are on the right place
So I guess it is ready for review again.
Comment #33
fgmLooks better indeed. I am not convinced by the claim that Services is the "more common way", though. Services is definitely an interesting extension (core in D8, anyone ?), with lots of extra features over the core implementation, but not necessarily the "more common way".
It is a bit as if the documentation for db_query mentioned Views and its API. These are different topics.
Comment #34
fgmThe example should also include the use of a multicall, which is currently not demonstrated. Multicall is an important feature, performance-wise, for web services in the real, and Drupal provides a very peculiar (and interesting) way to use it in clients, by making its use implicit instead of explicit.
Comment #35
rfayOK, here's my update with mostly quite minor changes, improving comments, improving UI text, etc.
I've also attached a diff of this against #32.
This does not include fgm's suggestion from #34
Comment #36
rfayFYI: Since HEAD is broken by the render example patch, we'll have to look at the actual testing results to see this succeed/fail (It comes back green in my environment)
EDIT: Unfortunately with HEAD broken all testing gets deferred.
Comment #37
rfayGreen now, and HEAD is fixed.
Comment #39
rfayHmm. I guess I won't call patch-to-patch comparisons ".diff" any more. Don't know if I can set this to needs review or not.
Comment #40
ilo commentedI'll do the tests for this locally to verify it, I do have to take a look to the changes yet! leaving as needs review for now.
Thanks rfay,
ilo
Comment #41
ilo commentedI'm unable to apply the patch at #35, however I've been reviewing the .diff (as I know the rest of the code) and here are my comments:
the following line has two typos: implEmentation and fiRSt (they were my fault, of course)
Edited:
Now I saw why I was unable to apply the patch, and solved it (the .install file was lost, things that happen with netbeans). By the way, there is another typo in the xmlrpc_example.install file: this is not the simpletest example ;)
Please, rfay, can you fix these typos also and commit this change so I can start working with the multicall implementation?
Comment #42
rfayCommitted to HEAD: http://drupal.org/cvs?commit=430838 (and followed up with the typo fixes)
@ilo: You might be interested in the far easier git workflow for your patching as well: http://groups.drupal.org/node/91424. Not that I'm partial to it.
And of course, you're welcome to commit something like this that you approve of.
Comment #43
ilo commentedOk, rfay, I'll consider next time!
Comment #44
ilo commentedso.. I've updated some documentation in the server and client also, fixed a wrong t(), and implemented two new buttons:
- Request methods: ask the xmlrpc server for available methods
- Add and Subtract: performs a multicall to add and subtract the numbers in the same request.
fgm, please review if this complies with what you suggested.
Comment #45
fgmFunctionality-wise, this is just fine. There are a few typos and coding standards issues, though:
The writing is a bit unclear: it makes it think that multicall is introspection-related, but it was an RFC by Eric Kidd, not part of Edd Dumbill's work.
XML-RPC, not XML-RCP
@link should be terminated by @endlink
per coding standards, arrays going beyond column 80 should wrap.
ditto
nitpicking: space at end of line
array content should be indented from array()
nitpicking: space at end of line
Powered by Dreditor.
Comment #46
ilo commentedThanks for the review fgm!, fixed all the coding and descriptions, and added an autoreplacement in the IDE for xml-RCP hehe.. Yes, you are right, description was confusing because I copied the wrong link. Anyway I've removed all of them.
Comment #47
rfayLooks OK to me. Waiting for @fgm's RTBC.
Comment #48
fgmGetting there, mostly typos remaining.
multicall, not mutilcall
missing "this" or extra "is"
Probably better to avoid using $GLOBALS, and use $server = url('xmlrpc.php', array('absolute' => TRUE)); instead
"be", not "is"
This is an error case, so the 'error' message type for drupal_set_message() should be added.
ditto, error case
ditto, error case
"builds", not "build"
"one", not "on"
ditto, url(), not $GLOBALS
ditto, error case
Powered by Dreditor.
Comment #49
ilo commentedThanks fgm, I'll do the changes and update the patch. I'm not sure, but looks like I no longer receive any email from the examples issue queue.
Comment #50
ilo commentedRerolled with @fgm's suggestions. No additional changes.
Comment #52
ilo commentedwow.. It passed all the tests locally :/
Comment #53
fgmJust in case you did not see the failure, the test on d.o. does not seem to see any of the methods.
Comment #54
rfayThe change of info files went in today, so don't neglect the possibility that there may be something in that that affects this. #1007580: Remove unnecessary files[] declarations from .info file
Comment #55
ilo commentedI've seen that only the page tests are failing, it is the output of a drupal_set_message() that is being checked. Looks like that request is failing (not in my local setup), however everything else, I mean the method calls, even the multicall are working. If someone can test the patch locally to see if this is only my case I'd appreciate it. Otherwise I'll put a debug message to see how is the output in the d.o. test environment.
Comment #56
rfayRemember the two major things different between you and the bot:
* Clean URLs are not on on the bot
* The bot executes the installed D7 in a subdirectory
I'll run the tests and report back
Comment #57
ilo commentedYeah, thanks rfay, but the failing tests are just a Post submission result, and it is anoying me because the methods are all working, and other checks following the same procedure are working also. Perhaps the testbot has not the 'system.listMethods' method enabled? that is the only clue I have about these failings tests.
Comment #58
rfaysystem.listMethods is already in the unpatched example - I added it the other day in #1004918: Improve xmlrpc_example by adding system.listMethods, and tests pass.
Doing a retest on HEAD: http://qa.drupal.org/pifr/test/26934
Edit: it passed, but there is no test that invokes it. So maybe that was kind of silly.
Comment #59
rfayI do get the failures when running Drupal in a subdirectory and with clean URLs turned off.
Comment #60
ilo commentedThanks so much for the test, rfay. The only difference with my setup was the clean urls, and as the test passed in #46 I think that it must be something in the patch that has to do with urls.. My bet is that fgm's suggestion about use url() instead of $GLOBALS has the key.
Thank you both!
Comment #61
rfayIMO when fgm & ilo are good with this it can be committed.
Comment #62
ilo commentedthen we are waiting for fgm's last word here.
Comment #63
fgmSeems quite good to me. Just a few problems with comments/messages not kept up to date with the latest changes:
Open question: would it not be useful to point to the relevant specifications (introspection, multicall...), since this is a tutorial module ?
why not use url('xmlrpc.php', array('absolute' => TRUE)) ? (happens twice in the file)
Comment disagrees with code: it used to be correct until the latest API changes regarding xmlrpc() late in the D7 cycle.
Inconsistency: assertion about multicall, message about subtract.
Plus a recurring nitpicking: AFAIK, strings should be single-quoted when double quotes are not necessary, even in D7/PHP5.x although this is much less of an issue than it used to be with PHP4.x.
Comment #64
ilo commentedThanks fgm!
My comments (rfay, feel free to unbalance and resolve)
- Open question: we must not talk about xmlrpc, as long as we don't document php. We are teaching/explaining Drupal's XML-RPC system. I don't see any problem including resource links, but we are not explaining what XML-RPC is, just using it with Drupal.
- url() works fine for urls, and perfect for menu entires. It happens that xmlrpc.php is a file, not a menu link, and using url() when clean urls are disabled renders a final RPC endpoint with '?q=xmlrpc.php' that made the module fail (that was the reason for the latest failing tests).
Totally agree in the rest of comments. I will fix them, but wait for Randy to unbalance these issues before submitting the patch.
Thank you for being so rabidly picky! hehe
Comment #65
fgmYou're right about the url() question, indeed. Which could well be a core bug: there does not seem to be a good reason for url() /not/ to check whether a link matches an actual file (performance, maybe ?). But at any rate, this is a core issue (#1009120: url() fails on files without clean URLs), not one for this patch to fix, and since D7 we have a new way of writing such URLs without building the strings by hand:
This allows dev a way to keep using url() (hence letting hook_url_outbound_alter() work), which seems better to me.
Comment #66
fgmSide node: the 'script' parameter was introduced in #437228: Remove hard-coded check for "Apache" for deciding whether to add "index.php" within url()
Comment #67
ilo commentedThanks for the follow up on this, fgm. I'll rewrite the patch for the comments at #63 in the following days.
Comment #68
ilo commentedLooks like url() only considers the 'script' parameter when clean urls are disabled. So, I guess the only way to make it working redgardless the status of clean urls is submitting both: path and script. Luckly, xmlrpc.php ignores the 'q' argument without clean urls (the request is something like this: xmlrpc.php?q=xmlrpc.php).
Size has increased because of double quote changes.
Comment #70
ilo commentedayyye.. the paths!
Comment #71
fgmGood for me regarding XML-RPC, and it works.
I'm worried about this 'script' issue, the resolution of which is not really satisfying, but this does not relate with XML-RPC anyway, so setting RTBC.
Comment #72
ilo commentedTo be honest I don't like it either. We have been playing ping pong with that patch for many many issues, I'm pretty sure it can wait a few days untill we find a better way, fgm.
Sun helped me on irc to get a fix for this using url($GLOBALS['base_url'] . '/xmlrpc.php', array('external' => TRUE));. This way hook_url_outbound_alter() could still handle it, but 'script' parameter is only for alternative index.php when clean urls are disabled (phpDoc description for the script parameter is very clear on that.)
So.. fgm, final review, I only changed that in this last patch.
Comment #73
fgmLet's go with #72.
Comment #74
ilo commentedFinally!, thanks fgm, rfay.
committed as http://drupal.org/cvs?commit=481996
Comment #75
ilo commentedNow, lets backport this do DRUPAL-6--1 to keep both branches as close as possible.
Comment #76
sbvish commented#8: example_xmlrpc_alter.patch queued for re-testing.
Comment #77
rfaySetting to correct status; this is waiting for a port to d6.
Comment #78
mile23It's end-of-life time for the 6.x-1.x branch of Examples. See #2642596: D6, D7 Roadmap for Examples