Whilst the very latest versions of Cache now include some very useful
new methods and functions, eg the encryption-related ones, not
everyone is in the position of being able to use them because they're
still using older versions of Cache.
Frustratingly, PHP includes a ton of libraries that allow you to do
pretty much anything under the sun.
Wouldn't it be nice if we could extend Cache's capabilities by making
use of all those PHP libraries? How would you do that? Actually a
lot more simply than you might think. Here's how.
You'll need to have PHP installed on a machine, ideally (but not
necessarily) on the same machine as the one you're running Cache on.
Indeed if PHP is on a different machine on your network, all your
Cache servers can make use of this trick.
Let's take an example. If you need to create an HMAC-MD5 hash from a
message and a secret key, you can do this directly in Cache 2007.1,
but not natively in earlier versions of Cache. I was able to find a
PHP version within a few minutes using Google. I created the
following simple PHP page:
<?php
function hmacmd5($key,$data) {
$b = 64;
if (strlen($key) > $b) {
$key = pack("H*",md5($key)) ;
}
$key = str_pad($key,$b,chr(0x00)) ;
$ipad = str_pad('',$b,chr(0x36)) ;
$opad = str_pad('',$b,chr(0x5c)) ;
$k_ipad = $key ^ $ipad ;
$k_opad = $key ^ $opad ;
return md5($k_opad . pack("H*",md5($k_ipad . $data)));
}
$key = $_REQUEST['key'] ;
$data = $_REQUEST['data'] ;
$hash = hmacmd5($key,$data) ;
header('Content-type: text/plain') ;
print('hash=' . $hash . chr('13') . chr('10')) ;
?>
I saved this as hmacmd5.php in one of my PHP directories and tested it
using a browser. If I put in the URL:
http://127.0.0.1/php/misc/hmacmd5.php?key=abcde&data=hello
then back comes:
hash=750c397713f9a8ee37b7aa593e8da225
OK so now to hook it up to Cache. Just create a method wrapper around
a %Net.HTTPRequest call to this URL, eg:
ClassMethod hmacmd5(key As %String, message As %String) As %String
{
s server="127.0.0.1"
s path="/php/misc/hmacmd5.php"
s data=$zcvt(message,"O","URL")
s http=##class(%Net.HttpRequest).%New()
s http.Server=server
s http.Port=80
s url=path_"?key="_$g(key)_"&data="_$g(data)
d http.Get(url)
s resp=http.HttpResponse.Data
s response=resp.Read(37)
QUIT $p(response,"=",2,2000)
}
And there you go! You can now get an HMAC-MD5 digest on any version
of Cache that supports %Net.HttpRequest:
USER> w ##class(php.commands).hmacmd5("abcde","hello")
750c397713f9a8ee37b7aa593e8da225
Of course you can adapt and apply this simple technique to access any
PHP functionality you want from Cache.
---
Rob Tweed
M/Gateway Developments Ltd
Just one thing people should be aware of with your example. The
requests will be stored in the web-server's log files in clear text. In
this instance it would be better to use POST rather than GET so the
arguments don't get logged. You might even consider using https rather
than http if the traffic goes outside of a secure zone.
If I'm already using Cache 2007.1 what are the benefits of using this
service oriented approach rather than a built-in function?
Regards
George
George James Software
www.georgejames.com
See inline...
On Fri, 23 Nov 2007 11:49:28 -0000, George James
<Geo...@georgejames.com> wrote:
>Rob
>This is a nice illustration of a lightweight service oriented solution
>and can be applied to any kind of service that Some Other Technology
>(tm) can do more easily than Cache. Or, as with your previous web-link
>example, use Cache to provide a sevice that other technologies find hard
>to implement.
Agreed. Cache's ability to act as an HTTP client via the
%Net.HttpRequest class, and its ability to act as a back-end to an
HTTP server (via WebLink or CSP, or via PHP, JSP etc using our MGWSI
gateway) are hugely powerful and, I'd hazard a guess, largely untapped
within the Cache community outside the pure web/HTML arena
It also serves to show that HTTP-based services don't need to be based
around the heavyweight SOAP/WSDL approach, or even use XML as a
response format. A very simple text/plain response can be ideal
particularly if you just need a simple, lightweight service for
internal use and/or requiring a minimum of parsing of the request or
response.
>
>Just one thing people should be aware of with your example. The
>requests will be stored in the web-server's log files in clear text. In
>this instance it would be better to use POST rather than GET so the
>arguments don't get logged. You might even consider using https rather
>than http if the traffic goes outside of a secure zone.
Yes, definitely. You always need to be aware of the security risks
when using HTTP as a transport. POST is a good way of avoiding things
getting logged by the web server.
By the way I also noticed something that needed changing in the
Cache-side method wrapper: the key would need URL encoding also, in
case it contained dodgy characters. So, adding your suggestion about
using POST, it should probably look like this:
ClassMethod hmacmd5(key As %String, message As %String) As %String
{
s server="127.0.0.1"
s path="/php/misc/hmacmd5.php"
s data=$zcvt(message,"O","URL")
s key=$zcvt(key,"O","URL")
s http=##class(%Net.HttpRequest).%New()
s http.Server=server
s http.Port=80
s http.ContentType="application/x-www-form-urlencoded"
d http.InsertFormData("key",key)
d http.InsertFormData("data",data)
d http.Post(path)
s resp=http.HttpResponse.Data
s response=resp.Read(37)
QUIT $p(response,"=",2,2000)
}
It will outwardly behave identically to the GET version:
USER>w $$hmacmd5^protx("abcde","hello")
750c397713f9a8ee37b7aa593e8da225
>
>If I'm already using Cache 2007.1 what are the benefits of using this
>service oriented approach rather than a built-in function?
Probably none - if you're using Cache 2007.1, I would hope that the
built-in function for HMAC-MD5 would be more efficient than a
round-trip to PHP via HTTP! (Note, however, that the response over
HTTP/PHP will be probably be more than adequate unless you're
hammering requests in at a very high rate).
However, I used this as an example because I specifically needed a way
of getting an HMAC-MD5 digest for an ealier version of Cache, and
really didn't like the idea of having to shell out in some way to some
third party utility (which I couldn't find anyway). Of course the
HTTP approach makes the integration totally OS/platform-independent,
whereas integrating with a third-party utility would usually require a
different technique if I was using Windows, Linux, Mac OSX or VMS.
Even with 2007.1, I'm sure there are plenty of other opportunities for
using this kind of technique for all manner of things that may not be
provided natively by Cache. When you discover the huge treasure-trove
of pre-written functionality in PHP, it may not make sense to spend
the time and money re-inventing a wheel within Cache if you can simply
hook in to someone else's work via a simple HTTP-based call and
wrapper.
Of course this technique isn't limited to PHP. If you find a cool
Java utility, you could interface it via a JSP page, or you could do
the same with a .Net utility via an ASP.Net page. The Cache-side
method wrapper would just be adjusted to call the different URL and
process the different name/value pairs.
Rob
>Or, as with your previous web-link
>example, use Cache to provide a sevice that other technologies find hard
>to implement.
Just a head's up on this issue. Watch for the next version of EWD
(www.mgateway.com/ewd.htm) which is going to include a REST server
framework to allow you to very simply and quickly expose your Cache
methods/data to the outside world as simple, lightweight REST-based
services.
The cool thing about the EWD REST server framework is that you'll be
able to choose any supported gateway to Cache to support your
services: eg WebLink, CSP, PHP etc. EWD will compile the service to
use the gateway/web technology of your choice and look after the
formatting and structure of the wrappering PHP or CSP etc page, or
WebLink routine.
All you'll need to focus on is your back-end method. It won't need to
know or care which web transport/gateway service is being used, or how
it gets invoked. You'll just focus on what your service needs to do
when it's triggered. Also, how you structure/format your output (ie
the HTTP response) will be entirely up to you - as simple or as
complex as you like.
Ideal, for example, for building the kind of event handler described
by Pasi Leno in his earlier thread. But also for all manner of
things, allowing the outside world to take advantage of Cache where it
provides a better solution than other technologies.
Now if I'd referred to extrinsic functions, I'd have been inundated by
calls to get modern, so I really can't win can I?
Anyway most people seem to have forgotten what that old stuff was, so
I need to keep up to date with readers of these threads! ;-)
I'll document how to do it the way *I'd* do it if you really want!!
Reminds me of one of the catch lines from my talk at Slipstream. "All
you'll be left with is servers, services and service". Well, it sounded
good at the time :)
Seriously, making everything into a service means that it is both
platform and implementation independent. And you can easily switch from
being a consumer of one service to that of another just by changing the
url. I quite like the Xobjex services which are small and atomic and
each one try's to do one simple thing well. For example:
http://xobjex.com/service/date.xsl gives you a date in every whichway
you might want it.
I'm not sure what you'd get if you tried to build a complex application
using this kind of architecture. I'm imagining that it would look a bit
like an Ensemble production. Or would it be more like Google's APIs
which have stimulated a proliferation of mash-ups and the Balkanisation
of real applications.
Lastly, as far as treasure troves of pre-written functionality goes -
perl's CPAN is a superb resource. If only we had libraries like that
for Cache.
Regards
George
ClassMethod hmacmd5(key As %String, message As %String) As %String {
s server="127.0.0.1"
s path="/php/misc/hmacmd5.php"
s http=##class(%Net.HttpRequest).%New()
s http.Server=server
s http.Port=80
s http.ContentType="application/x-www-form-urlencoded"
d http.InsertFormData("key",key)
d http.InsertFormData("data",data)
d http.Post(path)
s resp=http.HttpResponse.Data
s response=resp.Read(37)
QUIT $p(response,"=",2,2000)
}
>
>Lastly, as far as treasure troves of pre-written functionality goes -
>perl's CPAN is a superb resource. If only we had libraries like that
>for Cache.
>
I wonder why we don't? We all know there's little you can do in other
languages that also can't be done, often more efficiently and
effectively, in Cache. IMHO there's really no excuse for the lack of
an equivalent resource in the Cache community, but it's never too late
to start. Indeed we created the Utility Library
(www.mgateway.com/utility.htm) some years ago to try to encourage
people to create such a resource. While there's a certain amount of
stuff in there, I'm sure there are plenty more people out there that
have stuff they could contribute to the benefit of others.
I think the evidence is pretty clear that what makes a language really
take off is the ready availability of third-party utilities and a
thriving community of users who create them and make them available to
others.
Good point. I was actually aware of this COS version of MD5, but note
that HMAC-MD5 is different from simple MD5 hashing in that it creates
a digest from the message and a secret key. I'm not aware of a native
COS version of this algorithm, though I've no doubt one could be
written.
Similarly, I'm not aware of any native COS version of the algorithm
needed to create an SHA-1 digest. I'm finding more and more
situations where I need encryption stuff like this for users of
pre-2007.1 versions of Cache.
On Sun, 25 Nov 2007 18:34:33 -0800 (PST), David <rappe...@gmail.com>
wrote:
Also, it would be useful if there was some way of easily seeing what
license was applicable for each contribution (Public Domain, GPL, etc).
The library has reached the size where some kind of categorisation or
grouping would make it easier to find things.
Regards
George
George James Software
www.georgejames.com
-----Original Message-----
From: Rob Tweed [mailto:rtw...@blueyonder.co.uk]
Posted At: 23 November 2007 21:10
Posted To: Caché Newsgroup
Conversation: Extending Cache using PHP
Subject: Re: Extending Cache using PHP