Michael, Thanks for the reply. I'm not too fussy about exactly what things look like, as long as it can function. Here are my 3 cents: I think config, stats, status are orthogonal selectors to the data's structure - so why not put them in the query string? When one knows what one needs, it's best not to have to make multiple requests. (.g. /views to get the view list, then /views/eachview/zones to get the zone list, then /views/eachview/zones/zone/eachzone to get the zone type...) For my present use, I build a dropdown for actively served, user (non-default) zones. This happens fairly frequently. So it's important to keep it efficient. I don't want to make more than one query to the server to get this configuration data. So maybe something like: /views/*/zones?view.zone.type=user&DataClass=config would work. The idea is that the query could be any xml path=desired value, and DataClass is a metavariable. Alternatively, if you want to think about the Data class as a part of the structure, I'd put in front, not after. This because the rest of the path is going from the most general to the most specific. And /config/views/*/zones/* ... means "just config data at every level", not just at the last one... Of course, my litmus test is whether I can issue one request and get what I need for my application. Perhaps an example to test your design against would help. The outline of my code is: Fetch config checksum if matches cache, use cache (don't even parse the string) else update cache & use result. Stripping out error handling and a bunch of other details (for clarity), my current code looks like: my $config = LWP::Simple::get( "http://$masterNs:8053/config" ); my $checksum = Digest::SHA1::sha1($config); my $cfgname = dirname(Cwd::realpath( $0 )) . '/DnsConfig.db'; My( $cfg, %zones, %validzone ); eval { cfg = Storable::lock_retrieve($cfgname); }; if( $cfg && $cfg->[0] == 1 && $cfg->[1] eq $checksum ) { %zones = @{$cfg->[2]}; %validzone = @{$cfg->[3]}; ... } else { my $xs = XML::Simple->new(); # Extract views (because it speeds up parsing) $config =~ m/(.*?<\/views>)/ms or die "Can't find views\n";; my $views = $1; $views = $xs->parse_string( $views ); # Build %zones from server's active view/zone list for my $view (keys %{$views->{view}}) { my $zones = $views->{view}{$view}{zones}{zone}; my( @fwd, @rev ); for my $z (keys %$zones) { next if( $zones->{$z}{type} ne 'user' ); next if( lc( $zones->{$z}{rdataclass} ) ne 'in' ); next unless( $z =~ m!^(.*)/IN/$view$! ); $z = lc( $1 ); if( $z =~ /^(.*)\.in-addr.arpa$/ ) { my @a = reverse( split( m/\./, $1 ) ); my $a = join( '.', @a ); # Split out [0] private and [1] public IP zones # note that is_privateip returns a classification code; ! reduces to 0 or 1 push @{$rev[!is_privateip($a . scalar('.0' x (4-@a) ))]}, [ $a, "$z/$view" ]; $validzone{"$z./$view"} = $a; } else { # Forward zones push @fwd, [ $z, "$z/$view" ]; $validzone{"$z./$view"} = $z; } next unless( @fwd || @rev ); # Skip empty views $zones{$view}{forward} = [ @fwd ] if( @fwd ); $zones{$view}{reverse}{private} = sortip @{$rev[0]} if( $rev[0] ); $zones{$view}{reverse}{public} = sortip @{$rev[1]} if( $rev[1] ); } } Storable::lock_store( [ 1, # [0] Version $checksum, # [1] Checksum of received network data [%zones], # [2] [%validzone], # [3] ... ], $cfgname ); } --------------------------------------------------------- This communication may not represent my employer's views, if any, on the matters discussed. -----Original Message----- From: Michael Graff via RT [mailto:bind-suggest@isc.org] Sent: Wednesday, September 15, 2010 16:03 To: litt@acm.org Subject: [ISC-Bugs #22096] FW: Statistics channel patch Thank you for your feedback on the XML channel. >From a design point of view, I intentionally did not split the data apart but instead returned the whole thing. This was intentional until we could make it into a more RESTful style. It is probably time to actually take on the work of splititng the data into chunks. A simple RESTful API for gathering information about a server, in my mind anyway, was along the lines of: /views -- returns a list of views /views/_default -- returns information about a specific view /views/_default/zones -- returns a list of zones in a particular view /views/_default//zones/isc.org -- returns detailed information about this particular zone and so on. I am not certain if the /config, /stats, or /status information should be before or after the URIs in this simple example. My gut tells me after. --Michael