Wednesday, December 31, 2014

RESTful APIs with Bedrock (part V)

This is the 5th in a series of blogs on using Bedrock to create a RESTful API.  So far we've checked off several requirements for building a RESTful API.  We've been able to demonstrate the basics of creating a RESTful API using Apache and Bedrock.  We've satisfied requirements #1 through #4 and #6.
  1. Parse a URI
  2. Determine the operation to be performed
  3. Determine the result format requested by the client
  4. Retrieve, validate, and de-serialize client data
  5. Retrieve data from the back end
  6. Serialize data to send back to client
  7. Set HTTP response headers
  8. Handle errors
We'll round out the discussion by showing how Bedrock can satisfy the 3 remaining requirements.

Tuesday, December 30, 2014

RESTful APIs with Bedrock (part IV)

To recap our 8 requirements of a web development framework for creating our RESTful API:
  1. Parse a URI
  2. Determine the operation to be performed
  3. Determine the result format requested by the client
  4. Retrieve, validate, and de-serialize client data
  5. Retrieve data from the back end
  6. Serialize data to send back to client
  7. Set HTTP response headers
  8. Handle errors

In yesterday's blog we talked about using Apache directives to help us create meaningful URIs and using Bedrock to interpret the extra path information and HTTP method in order to satisfy requirements 1 & 2.

Today we'll examine #3 and #4 and touch on #6.

Monday, December 29, 2014

Perl Regular Expression Capture Groups

After cursing Bedrock for not giving me access to capture groups in regular expressions, I finally bit the bullet and figured out how to implement this in a somewhat sane manner.

RESTful APIs with Bedrock (Part III)

The other day I blogged about using Bedrock to create a RESTful API.  Today I'm going to talk about setting up Apache in order to support a RESTful interface based on URIs.  Last time we pulled these requirements for a REST API framework from Michael McClennen's talk:

  1. Parse a URI
  2. Determine the operation to be performed
  3. Determine the result format requested by the client
  4. Retrieve, validate, and deserialize client data
  5. Retrieve data from the back end
  6. Serialize data to send back to client
  7. Set HTTP response headers
  8. Handle errors

Let's configure Apache to help us with #1, and #2 as we implement a hypothetical RESTful interface for a contact database.

First, we'll create an Apache RewriteRule that maps our desired API's base URI to a Bedrock page.  We add the directives below to our Virtual host configuration file.

RewriteEngine On
RewriteRule  ^contacts(/.*)?$ rest-api/contacts-api.jroc/$1

Using this rule URIs that begin with contacts will now be rewritten to point to a URI that implements our REST interface in Bedrock.  The Bedrock file contacts-api.jroc is a Bedrock script (page) that returns a document of type application/json.  By convention (and as implemented by the Bedrock handler), any Bedrock script with an extension of .jroc will be considered to return a JSON document.

That's just another way of saying that Bedrock will set the mime-type header to application/json for you automatically.  Of course you could have named the file contacts-api.roc and then set the Content-Type header yourself.

<null $header.set('Content-Type', 'application/json')>

Files in the rest-api directory are configured using Apache directives so they will be processed by the either the Bedrock mod_perl Apache handler or the Bedrock handler implemented as a CGI.

<Directory /var/www/vhosts/myhost/htdocs/rest-api>
# Bedrock - mod-perl for .roc (if mod_perl)
  <IfModule mod_perl.c>
    AddHandler    perl-script .roc .jroc .html
    PerlHandler   Apache::Bedrock

  Action bedrock-cgi /cgi-bin/bedrock.cgi virtual

  <IfModule !mod_perl.c>
    AddHandler    bedrock-cgi .roc .jroc

We can now use the PATH_INFO environment variable to interpret our URI since all the stuff after  contacts/ in our URI will be considered extra path information and presented to us in that environment variable...well sort of.   As it turns out, when Bedrock is configured using the CGI version, PATH_INFO will contain the filename (contacts-api.jroc) as well as the extra path info.  For this reason, Bedrock provides an environment variable named BEDROCK_PATH_INFO only available when the Bedrock handler is configured as a CGI script that contains only the extra path information.

PATH_INFO => (/env.roc/foo)

Our REST API script can now grab the extra path information necessary for us to interpret the URI.

<null:path_info --default=$env.PATH_INFO $env.BEDROCK_PATH_INFO>

Under mod_perl we'll use the PATH_INFO variable, but as a CGI handler we'll use the value Bedrock provides as BEDROCK_PATH_INFO.  Since the BEDROCK_PATH_INFO variable is only set when the Bedrock handler is a CGI, our $path_info will be set  using the default value under mod_perl.

The URI gives us the context, but what about the method?  Using Bedrock's $env object that exposes  environment variables to your Bedrock pages, we can examine the HTTP method sent by the client.  By testing  $env.REQUEST_METHOD we can determine the HTTP method.  The value will probably be either GET, PUT, POST, or DELETE, as set by the client and defined by your API.  It would then be easy enough to test that value along with the URI to determine the operation to be performed.  That is to say, the operation to be performed will be a function of the HTTP method and the URI.

<if $env.REQUEST_METHOD --eq 'GET'>

# /contacts/friends
   <if $path_info --eq '/friends'>
   <elseif $path_info --eq '/business'>
     <raise '400'>

<elseif $env.REQUEST_METHOD --eq 'PUT'>

This now satisfies our first two requirements we discussed last time, namely:
  • Parse a URI
  • Determine the operation to be performed
Next time: Determining the result format and de-serializing our input data.

Wednesday, December 24, 2014

RESTful APIs with Bedrock (Part II)

Reading the Perl blogs I saw a link to a Michael McClennen RESTful talk.  It was an interesting introduction to those with no background on REST and offered some insights and interpretations based on his experience.  The talk does a good job balancing an informational talk on RESTful interfaces in Perl with a gentle sales pitch for his new CPAN module (Web::DataServices).

First off, anyone that publishes on CPAN has my great respect.   Clearly this author knows his stuff, shares it and that's a very good thing.   I'm not sure I will become a user of this module, primarily because of the dependencies (Moo, etc), but more to the point I'm not (yet) convinced one needs a complete RESTful framework that sits on top of a web development framework.

Having said that, I reserve the right to change my mind and I imagine the author spent a lot of time thinking of that as well and ultimately concluded this his effort was worthy of the problem.   Congrats to Michael on publishing his module and adding another building block or at least reference for Perl developers.  I admire that effort and wish I had the time and energy to do the same.

So, do we really need a RESTful API framework?

I'm not sure.  Why don't I think we need a RESTful framework?  Well, I would hope that that the web framework itself that was chosen is robust enough to implement the RESTful architecture and your API without a lot of overhead or hair pulling.  After all, the RESTful architecture is supposed to reflect the stateless and simple nature of the web.  Sort of, I guess.  Paraphrasing a slide from Michael's presentation, there's not too much one needs from a framework to produce a RESTful API.  Here's what we'd like from our framework in order to implement our API.

Thursday, December 4, 2014

A RESTful API Using Bedrock?

As I've written before, writing AJAX services in Bedrock is actually pretty trivial.  In fact, Bedrock's support of the .jroc extension which automatically sets the mime-type of the output to application/json makes creating an AJAX widget to return the current environment for example, look something like this:

<var --json $env>

Not sure how it could get any easier than that...and with a properly configured Bedrock installation, AJAX services that access information stored in MySQL tables is equally as easy.

<sqlselect "select * from customers" --define-var"customers"></sqlselect>
<var --json $customers>

I've recently started looking at using Bedrock to prototype a RESTful interface and I've been very encouraged about the simplicity here as well.  Several features of Bedrock make creating a RESTful API pretty easy.

  • Ability to interpret the environment variables (URIs), etc.
  • JSON
  • Access to POST data
  • Ability to directly set status
  • Ability to interpret and set HTTP headers

I've been studying up on creating robust, secure and compliant RESTful interfaces and think I can use Bedrock to prototype a RESTful API.  Some interesting resources I've found so far include:

REST Video Tutorial
REST API Design Rulebook
API Security Considerations

So what might a Bedrock based RESTful API look like anyway?  Consider this API:

/accounts      => returns a collection of accounts
/accounts/{id} => returns a single account's record
/books         => returns a collection of books
/books/{id}    => returns a single book record

Let's give this a shot in Bedrock...

<sink><null:uri $env.BEDROCK_URI>
<null:parts $uri.split('/')>


<if $parts.[1] --eq 'accounts'>
 <if $parts.[2]>
   <sqlselect "select * from account where id = ?"
   <sqlselect "select * from account" --define-var="out></sqlselect>

<elseif $parts.[1] --eq 'books'>
  <if $parts.[2]>
    <sqlselect "select * from book where id = ?"
   <sqlselect "select * from book" --define-var="out></sqlselect>

</if></sink><var --json $out>

Okay, this is a really simple and featureless example that doesn't consider authentication, or setting status on error, but you get the idea.  I'll be blogging about this subject as soon as I do the deep dive, but it looks promising.

Acer C720 Demand Sparks Price Increase

Apparently I'm not the only one that thinks the Acer C720 is the best damn Chromebook you can get for the money.  The price and availability this Christmas are moving in opposite directions.

Prices are going up, and the stock and availability are going down.

Yes, I'm pimping this product, because I love me some Chromebook!  I literally use this device every day and yes I am writing this blog on my Acer C720 Chromebook (11.6-Inch, 2GB).

 Full disclosure...I've made about $20 after a year of blogging about this product using the Amazon Associates links - so apparently I'm not very good at it, my blog is not that popular and I'm clearly not making a living at this. Note to self, don't quit your day job. The links are really for your convenience, just in case you feel the urge and need a push. ;-)

Love me some Chromebook!

I may just re-moniker this blog Love Me Some Chromebook!  But honestly, this is an extremely easy product to fall in love with for anyone that wants a low cost, well made device for email, browsing, watching videos and even doing software development in the cloud.  Fast boot, long battery life, and light weight, I take this puppy EVERYWHERE!   No, it doesn't run Microsoft Office, but this is 2014 people!  Stop the MS Office malarkey already!

Google Docs and Google Sheets are absolutely awesome and you are doing yourself and your grand kids a disservice if you continue to pound that damn MS Office drum.  Ever watch a 14 year old write a paper for school on Microsoft Word?  They spend the first 20 minutes adjusting margins, font-size and the font face in order to make 3 paragraphs of drivel expand into a 2 page Hemingway masterpiece.
"Everything is your fault...if you're any damn good!" - Ernest Hemingway
 Buy your kids a Chromebook and teach them to write instead of format.   But that's America these days, style over substance I guess...if they have to hand in an MS Office paper, they can save their Google Doc as an MS Word file.

Still not convinced?  Don't buy a Chromebook, just install Chrome on your Windows machine and play with Google Docs/Sheet/and Slides.  Print to a cloud enabled device (see my reviews and howto's from last year)...and then decide.  It's been a year with my Chromebook and the honeymoon is definitely not over.  It just gets better with every update.  Which happens transparently for me by the way!

As of today (December 4th, 2014), the device is out of stock at Amazon but they claim it will ship in a few days.

I'm still doing some research and will blog on this subject (performance) soon, but I've concluded that the Acer C720 is not just a good Chromebook, it is THE Chromebook.  Why?  I'll summarize my research by saying, it's simply the best value.  It uses the best CPU for the money (Intel Celeron 2955u)  and still delivers exceptional battery life while keeping the cost under $200...well it was under $200 until this morning.  Hopefully as stocks are replenished you can grab one at a lower price.

CAUTION!  Don't be fooled with other Chromebooks that claim higher clock speeds. That DOES NOT TELL THE WHOLE STORY.  Read the reviews.  If it ain't using the 4th Generation Haswell architecture 2955U it's either an ARM processor or an Intel M-series (Baytrail architecture) and the performance will not match the Acer C720.  The exception being the Acer C720 with the i3 processor.  You'll get slightly better performance with that device, but at a higher price point.  

If streaming music and video while you're doing other tasks is important to you, then this C720 will give you the ultimate experience.  I've been listening to Earbits Radio streamed to my iSound Twist Bluetooth Wireless Mobile Speaker (Rubberized Blue) with more than 6 tabs open while writing this blog on my plain 'ol 2955U based C720 with just 2MB.  If you typically run with a lot of tabs open, you might want to consider the Acer C720-3404 11.6-Inch Chromebook (Intel Core i3, 4 GB) Granite Gray version of the C720.   If I get carried away, I have been able to crash a tab or two and run out of memory.

If you are considering a Chromebook, my advice after a LOT of research is that you will not find a better Chromebook for the money right now.  I keep looking, but right now, the Acer C720 is hands down the best Chromebook on the market.  Don't take my word for it though, go try to find one right now!  Good luck.

Tuesday, December 2, 2014

Using tmux and lovin' it!

So I've been using tmux for a few months now and here are some observations, a philosophy lesson, motivational speech and even some tips that might be useful.

At first you ask yourself, do I really need this?

Yes, use it.  Like many tools that are powerful, the first few confusing encounters that expose the complexity of the tool and your ignorance of it, prevent the less persistent among us from sticking with it.  Be persistent and dogged in your experiments with new tools that have the potential to make you more productive. Always.

My experience tells me that you need to stay with something for more than 10 minutes and work through the frustrations that are primarily a result of your lack of mastery and knowledge of the subject matter.  Learn to read man pages.  Exercise your patience.  Stare at your microwave for the entire 30 seconds as your coffee warms up!  Embrace the meditative potential of the countdown toward your caffeinated nectar!

While sticking with hard things and being patient as you peel away your ignorance (paradoxically only to reveal more of it)  seems obvious to those of us that have done hard things in our life, it's a lesson many folks never embrace.  Most find it easier to reach for the simpler, albeit less powerful implement, hence why there are so few master craftsmen in the world today.  Instead we have Certified Charlatans (IT people with certifications out their butts, with no real mastery of anything).  Of course, the entire lesson of learning your tools well can applied to your approach to life.  ;-)

Your fingers will be confused.  It takes a while to get used to the key sequences

Get over it.  Ctrl-b is hard for me to reach too and confuses my already confused, arthritic, emacs trained fingers.  Again, my ignorance of the tool shows, since customization is indeed possible and appears to be in my future.  I'll probably suffer a bit more before heeding my own advice to master this tool.

Buddy Programming on Steroids

Pair or buddy programming is all the rage these days I guess.  Technically I think pair programming requires a physical proximity, but maybe the term should be Virtual Pair Programming or Remote Pair Programming (RPP) or is that an oxymoron?  Or is RPP like Remote Viewing (RV) where we can use our psychic abilities to debug and troubleshoot?  Cool!

Sharing a tmux session and talking on Skype or Hangouts is infinitely better than IM alone and probably more effective that RV.  I can't really imagine doing remote buddy programming (RBP?) without using tmux, Google Hangouts (screen sharing and audio) and the occasional IM message thrown in for good measure.  It works.  In fact, I think remote buddy programming may be even more compelling and tolerable for some technical people who don't like the concept of close proximity with other humanoids.  ;-)

Han Solo
I think the jury is still out on pair programming in general and taken to the eXtreme (pun intended) and forced on teams like cod liver oil on children probably stinks as badly.  Imposed on an unwilling group of programmers, PP will surely be as ineffective as Han Solo, your supposed rock star developer who ignores personal hygiene for several days and emerges from the cave with the next VisiCalc.  I like to throw those historical references out there for the kids.

Like all things in life, it depends, and your mileage may vary, for it is for the ends that you perform these actions, not merely the means themselves.  As promised, a philosophy lesson, so let Aristotle explain...

Every art and every inquiry, and similarly every action and pursuit, is thought to aim at some good; and for this reason the good has rightly been declared to be that at which all things aim. But a certain difference is found among ends; some are activities, others are products apart from the activities that produce them. Where there are ends apart from the actions, it is the nature of the products to be better than the activities. Now, as there are many actions, arts, and sciences, their ends also are many; the end of the medical art is health, that of shipbuilding a vessel, that of strategy victory, that of economics wealth. But where such arts fall under a single capacity- as bridle-making and the other arts concerned with the equipment of horses fall under the art of riding, and this and every military action under strategy, in the same way other arts fall under yet others- in all of these the ends of the master arts are to be preferred to all the subordinate ends; for it is for the sake of the former that the latter are pursued. It makes no difference whether the activities themselves are the ends of the actions, or something else apart from the activities, as in the case of the sciences just mentioned. 

Savin' Your Bacon

The use case for tmux if you have a spotty internet connection, or if you simply have to pick up and go because of some non-maskable interrupt  is quite compelling.  I can't tell you how many times I've been happy to have my session pick up right where I left it after I was disconnected or told to take the trash out, which morphed into doing the dishes, walking the dog and oh by the way don't you dare go back to that computer!

Today's software development modus operandi  is develop anywhere, anytime.  Starbucks (or Dunkin' Donuts), on an airplane with my Chromebook and Gogo inflight access, in bed, by the TV, in my office, in my den, at the trade show making last minute changes, and even in my car on I-95 using a wifi hotspot and my Macbook while my wife gets lost going around Baltimore.   If you want to open your Chromebook, boot in seconds (yup!), and fix a bug, then ssh to your server, attach to your tmux session and you're ready to rock 'n roll.  No blog is complete without a plug for the Chromebook and specifically the Acer C720 (stick with Chromebooks that use the Intel Haswell architecture for now) me some Chromebook!

Tips & Discoveries of the Clueless

This wasn't supposed to be a tmux tutorial, but quickly:

Open a new tmux session

$ tmux -S /tmp/$USER new -s $USER

Attach to an existing session

$ tmux -S /tmp/$USER attach -t $USER

Detaching from a session

To detach from your system (not end the session), press Ctrl-b d.  To end the session, exit the shell by typing exit.  The important point here is you want to detach from your session and keep it active, then reattach at some later time.

$ tmux -S /tmp/$USER attach -t $USER

Sharing Your Session

Create a group such as developers and make sure each user you want to allow in your session is a member of the group.  Modify the group of your session socket.

$ sudo groupadd developers
$ sudo usermod -a -G developers fred
$ sudo chgrp developers /tmp/rlauer

What No Scroll Buffer?

Yes, there is a scroll buffer however my ignorance regarding using tmux is so deep that I didn't even know where to look.  Google to the rescue!  Ctrl-PgUp (or Ctrl-b [) puts you in scroll mode or what tmux calls copy-mode.  Use PgUp, PgDn to move around the scroll buffer, 'q' to quit scroll mode.

Multiple Windows

As you become more comfortable with tmux, you'll want to create multiple shells so you can perform parallel tasks (editing, building, monitoring logs, etc).  Use Ctrl-b % to create a window vertically and Ctrl-b " to create windows horizontally.  Use Ctrl-b & to kill current window or type exit to exit the shell.

Be aggressive in using new windows and it will increase your productivity.  Go for it!

Changing the window size

To change the window size use Ctrl-b left/right, but quickly.  tmux times out after the Ctrl-b press fairly quickly so you need to pound the left and right arrows to adjust your window size.

More Info

$ man tmux

...or if you are in a session, Ctrl-b ? to see the key bindings.


The least you to need to know to say that at least you know the least...

Ctrl-b ?                   => show key bindings
Ctrl-b d                   => detach session
Ctrl-b left/righ5/up/down  => navigate to other window
Ctrl-b [                   => scroll mode (then q to quit)
Ctrl-b PgUp                => likewise
Ctrl-b %                   => split window vertically
Ctrl-b "                   => horizontally

What Else?

Sunday, November 30, 2014

Acer C720 - Best Selling Laptop on Amazon!

I just took a look on Amazon's website and the Acer C720, 2GB model is now only $149.  Wow.  This is probably the best bargain in laptops today.  I'll say it once more...this is one amazing machine.  For those that think they HAVE to have a Windows or Mac machine, you really should try this.

Google Docs has a come a long way and while you may not have the exact same features as Microsoft Word, I have not missed MS Office one bit.  Some places where some might have problems: Widows and orphans, formatting the header/footer, tables. In practice these have not been a show stopper for me. Creating even complex spreadsheets with advanced formulas is supported and I've done some really complex pro-formas with Google Sheets.

I've been using Google Hangouts to do some offshore collaborating and the Hangouts experience on the Chromebook is fantastic.  Audio and video quality are very good and I have had no problems talking to people across the globe.

I recently attended the Amazon re:Invent in Las Vegas, and The Acer C720 came along for the ride.  The battery life is fantastic and paired with my free Gogo inlight wifi coupon I got when I purchased the device I was able to work the entire 4 hour trip!  I received 12 free coupons (value = $12).  Not sure if that promo is still valid, but when you consider the free 100GB of storage I got as well, the C720 was practically free.

The light weight and long battery life make this device a must have business travel partner.  The lost cost of the device alleviates the fear of loss factor.

I still love me some Chromebook!

Saturday, November 1, 2014

Acer C720 - One Year Later

Well, it's been a year and it's time for a Chromebook blog...

I gave away my C720 4GB and C720 2GB models but not because I didn't love them.  The former to a colleague and the latter as a gift.  I miss me some Chromebook!

After being without my Chromebooks for quite awhile (I was primarily using my Mac-book Pro) I decided to see if there were any new Chromebooks out there and if so, if there was a compelling reason to pick something up other than a C720.  I'll cut straight to the chase...there is no compelling reason to purchase anything except the Acer C720.

After reviewing several alternatives, including the new Acer model that uses the Intel i3 CPU, I can confidently say that the original C720 is every bit as hot "sh*t" as  I thought it was when I reviewed it back in 2013.

The fact is, unless you really feel like spending more money or need a bigger display, this Chromebook is about as big a bang as you can get for your Chromebook money.  You might want to go with the 4GB model if you typically roll with lot's of tabs open, but in practice I have not had issues with performance.

I've researched a bunch of different models (HP, Samsung, Asus), read the reviews read the specs and checked them all out at Best Buy (don't ever ask their sales people questions if you want to get the correct answers).

It can be confusing, especially when sales people give you wrong information and are generally ignorant about Chromebooks to begin with.  Bottom line is that the Haswell architecture is going to give you the best price, performance, battery life of all of the Chromebooks.  If you want to sacrifice a bit of performance for battery life (and we're talking a little more, not a lot more battery life) then the new models with the NVIDIA Tegra K1 chipset should be considered.  The new Acer 13.6" model sports the new chipset and a higher price, but might be best for those looking for a little more screen real estate and as I mentioned, increased batter life.  The other features are pretty much the same (same number of USB ports and interfaces).  The new model supports MIMO Dual-Band 2.4Ghz & 5GHz wifi.

According to the Acer specs, you'll enjoy 13 hours of battery life for their HD (1366x768) and 11 hours for the Full HD model (1920x1080).  I'd probably cut that down by 10-20% depending on how bright you like your display.  It also adds about 1/2 pound to the weight over the original C720 (2.76lbs vs 3.3lbs).

Throwing a C720 on my coffee table is a no brainer.  It's cheap and powerful and I can browse, check my email and even run SSH to do some Linux development.  As a first or second laptop it works for me.  When I travel, I'm not taking my $2k Mac-book Pro, I'm throwing my C720 in my messenger bag and heading to the airport.  One of the great comforts of this is, if I lose the Chromebook, there's nothing on it that someone can steal.  If I do lose the C720, it wasn't all that expensive in the first place.

I love me some Chromebook!

Wednesday, October 29, 2014

Redis & Bedrock

Been playing a bit with Redis, a really cool in-memory database based on keys and values.  It's a key/value database on steroids and has a lot of applicability for web applications that need to scale or just want better performance.

A Perl module is available on CPAN, appropriately named Redis.  One might therefore be tempted to do something like:

<plugin:Redis server localhost:6379>
<null $Redis.set('key', 'value')>

Great idea, however it turns out that didn't work.  Is Bedrock broken? Hmmm...let's find out.

Perl modules like Redis that utilize a large number of AUTOLOAD subroutines and do not implement an appropriate can method are not going to present a code reference when Bedrock's parser calls the module's can as a recognition of this possibility the module within Bedrock's parsing does this:

my $funcref;
$funcref = $obj->can($func);
if ( $funcref ) {
    @ref_v = $funcref->( $obj, @funcargs );
  else {
     "$self: eval function in case implemented via AUTOLOAD\n\@ref_v = $obj->$func(\@args);"

    eval '@ref_v = $obj->' . $func . '(@args);';

    if ( $@ ) {
      if ( $@ =~/TagX::Scalar/ ) {
  die "attempt to invoke possibly non-existent method ($func) on a possibly non-existent scalar\n";
      else {
        die "$@\n";

Hey, umm...what's that? @args? Shouldn't that be @funcargs? Yup....bug.  Fixed in 2.4.1-snapshot today.  Okay, so anyway...

What can we do with Bedrock and Redis?

Well, generally we can use it as a persistent storage mechanism similar to the way we use the $session object.

<null $Redis.set('foo', 'bar')>

...on one page and then...

<var $Redis.get('foo')>

...on the next...

Of course that example is like saying you can use a brick to prop open a door!  There are lot more interesting and exciting things you can do with Redis.

How about counting page hits from unique IPs?

<null $Redis.pfadd('home-page', $env.REMOTE_ADDR)>

Using Redis' HyperLogLog (requires Redis 2.8.9) facility we can add a member and let Redis keep track of counting unique hits.

<var $Redis.pfcount('home-page')>

Or resetting a counter at midnight by specifying a time value (seconds since the epoch) to the expireat function.

<sqlselect "select unix_timestamp(date_add(curdate(), interval 1 day)) exp">
<null $Redis.expireat('home-page', $exp)></sqlselect>

...and of course we can store serialized data to Redis.

<null $Redis.set('env', $env.json()>

and deserialize it later to a Bedrock object...

<null:user_env --json $Redis.get('env')>

Yup...this is cool!  ;-)

Sunday, October 19, 2014

Pretty Print JSON objects

Added --pretty as an option to the <var> tag for pretty printing JSON objects.  Changes pushed to git master.

<sink><null $header.content_type('application/json')>
<hash:foo red 1 blue 2 green 3>
</sink><var --pretty --json $foo>

...would yield

   "green" : "3",
   "blue" : "2",
   "red" : "1"

Saturday, October 18, 2014

AWS with Bedrock

I'm starting to tinker with using Amazon's web services from Bedrock pages.  Embedding AWS in Bedrock applications is not new - particularly if you are running Bedrock on an EC2 instance, RDS (hosted MySQL) or you are using Amazon's S3 object storage system.   There are other Amazon web services that are particularly useful in any web development environment, exposing these to Bedrock pages looks interesting.

Plugin Bug

Fixed a bug in the <plugin>  tag.   Class names were not being parsed correctly if there was more that 1 level to the namespace.

For example, Amazon::SNS::VerifySignature was being incorrectly parsed as Amazon::SNS which happens to be valid Perl module.

Fix pushed to master.

Saturday, October 11, 2014

Amazon SNS - Verifying Signatures

While creating a Bedrock example of using Amazon's Simple Notification Service, I was surprised to find that Googling for a Perl example of verifying the signature from an SNS notification message came up empty.  So I wrote my own...

Sunday, September 28, 2014

Custom Error Pages

The default page when Bedrock encounters errors during the parsing of a page is error.roc and is distributed with the other core Bedrock files.  The page shows the developer the error and the contents of the page with each line numbered for easy correlation to the error reported by Bedrock.
Bedrock Error Page

You can customize the error.roc page if you'd like or replace it.  You probably don't want to spill code to users in a production environment.

To specify your own custom error page, set the BEDROCK_ERROR_LOCATION variable in the tagx.xml file to the fully qualified path of your own Bedrock file.

<scalar name="BEDROCK_ERROR_LOCATION">/var/www/html/error.roc</scalar>

Bedrock exposes the $ERROR object that has several methods you can use to report the error.

$ERROR.mesg() - the error message

$ERROR.line() - the line number where the error was encountered.

$ERROR.file() - the name of the file where the error occurred.

$ERROR.view_source() - an HTML representation of the source code.

Simple Example

This example uses the $ERROR object to display the error message, location of the error, and the file that was being processed when the error occurred.

<h1>Whoops! We're sorry, our slip is showing!</h1>
message: <var $ERROR.mesg()>
location: <var $ERROR.line()>
file: <var $ERROR.file()>
source: <var $ERROR.view_source()>

E-Mail Me the Error

Here's an example error page that will give the user a message and send an email to the developers notifying them of an error...I'm using the $SMTP plugin distributed with Bedrock to email the error message.

<h1>Whoops! We're sorry, our slip is showing...</h1>

<i>Thanks for your patience...our staff is on it!</i>

<plugin:SMTP localhost>

<null $SMTP.subject('A Bedrock Error has occurred!')>
<null $SMTP.header('Content-Type', 'text/html')>

<sink $SMTP>
An error has occurred <b><var $ERROR.file()>[<var $ERROR.line()>]</b>
<b>REMOTE_ADDR:</b> <var $env.REMOTE_ADDR>
<b>SERVER_ADDR:</b> <var $env.SERVER_ADDR>
File: <var $ERROR.file()>
Line: <var $ERROR.line()>

<span style="color:red;"><var $ERROR.mesg()></span>


...and voila!  I get an email when an error occurs.

Saturday, September 27, 2014

Friday, February 7, 2014

Expanding the Use of Perl Plugins

The <plugin> tag allows you create Perl classes that provide specific functionality for your pages.  But what about using CPAN modules as plugins?  Most CPAN modules that have a new() constructor can be used as plugins.  One of my favorite CPAN modules is Text::CSV_XS so it was disappointing to find I had some issues with this one.


Bedrock has had a limitation on using some CPAN modules because of the way Bedrock coerces lists into Bedrock array objects when invoking method calls on objects...until now.

Wednesday, January 1, 2014

Bedrock, jQuery and HTTP Status Codes

Using Bedrock to create AJAX components is trivial.  Name your Bedrock file with a .jroc extension and return your result.

<var --json $result>

Can it get any easier?  I just created a wiki page that shows how Bedrock handles exceptions for application/json files you serve up using Bedrock.   I also describe how you can customize the HTTP status code that Bedrock returns to the browser.