Sergio and the sigil

Language Envy - C# needs Ranges

Posted by Sergio on 2010-01-02

As soon as I started learning Ruby, a few years ago, I got immediately hooked on its Range class. I could not believe I had been programming in .NET without them for so long.

I like to think of range objects as the specification for a for loop, packaged in an object that can be passed around. That's not the whole story, though. Ranges also represent sequences or intervals, which can be queried for intersection or containment. See the following Ruby sample code.

#declare a Range object
summer_months = 6..9
#enumerate it
summer_months.each {|m| puts "#{Date.new(2000, m, 1).strftime('%B')} is a Summer month." }
#other handy features
summer_months.include? 7 # ==> true
summer_months.to_a # ==> [6, 7, 8, 9]  (converted to array)

I needed that in C#

That was back when the CLR 2.0 was just about to be released and I ended up writing my own Range

Language Envy - Juicy, a simple webserver

Posted by Sergio on 2009-04-13

Many times when I'm writing JavaScript code with Ajax calls I don't have an URL to call and get the data yet. Or sometimes I have an URL that gives me valid data and I need to test the code against invalid data or some other variation that I don't have handy.

WEBrick

In these situations, instead of creating a temporary ASP.NET application, I learned to love using Ruby and the adorable simplicity of WEBrick. Imagine that I needed an URL that simulated latency on the server.

require 'webrick'
include WEBrick

server = HTTPServer.new( :Port => 2000 )

server.mount_proc("/getData"){|req, res|
  res.body = "{result: 'ok', accountId: 123}"
  res['Content-Type'] = "application/json"
  delay = req.query['delay'] || "0"
  sleep(delay.to_i)
}

trap("INT"){ server.shutdown }
server.start

After running the script I can open use the URL http://localhost:2000/getData?delay=5 in my Ajax call and, after a delay of five seconds, the JSON string {result: 'ok', accountId: 123} will be returned. The server will stay there, in a console window, running until I kill it with CTRL+C.

I could add more mount points on that server for as many test URLs as I wish. I find this incredibly practical.

I wish there was something as simple in .NET

Well, I couldn't find anything as easy in .NET. The few offerings I found were not as straight forward. Some of the alternatives are distributed in .msi files, which makes them less convenient, especially for integration testing or JavaScript unit testing (which is my end goal.)

Hello Juicy

Envy sometimes makes you move forward. I played around with sockets and the HTTP protocol and ended up with a library that looks promising. See that same code written using the Juicy.DirtCheapDaemons.Http.HttpServer class, a.k.a. the Juicy Web Server.

using System;
using System.IO;
using System.Threading;
using Juicy.DirtCheapDaemons.Http;

  class Program
  {
    static void Main(string[] args)
    {
      HttpServer server = new HttpServer{ PortNumber = 2000 };
      server.Start();

      server.Mount("/getData", 
        (req, resp) =>
          {
            resp.Output.Write("{result: 'ok', accountId: 123}");
            resp["Content-Type"] = "application/json";
            var delay = int.Parse(req.QueryString["delay"] ?? "0");
            Thread.Sleep(1000 * delay);
          }
      );

      Console.WriteLine("Press enter to stop server");
      Console.ReadLine();
      server.Shutdown();
    }
  }

There are a few things more that can be done with HttpServer.

//mounting virtual path with a lambda (shown in previous example)
server.Mount("/virtual/path", (req, resp) => DoSomethingWith(req, resp));

//mounting virtual path to serve static files
server.Mount("/virtual/path", @"c:\some\directory");

//hiding a virtual path
server.Mount("/virtual/path/subdir", new ResourceNotFoundHandler());

As it is, HttpServer supports only GET requests. The plan is to add more support (for features that make sense in a unit testing scenario) with time.

I obviously don't envision Juicy becoming a full-fledged web server that I can recommend using in a live web site. But I can see it being helpful in the scenarios I've just described and for testing in general.

I'm sold. Where can I get it?

This project is hosted at GitHub: http://github.com/sergiopereira/juicy/tree/master, where you can download the source directly or even clone the repository :

c:\projects>git clone git://github.com/sergiopereira/juicy.git