MindTouch Developer Center > MindTouch Dream > Tutorials > Creating a service to inspect HTTP headers

This tutorial builds on what we learned with our Magic 8-ball service.  This time, we'll explore how to build a service with multiple features and we'll learn about more capabilities of the Dream framework.  The goal of our service will be to provide a tool to visualize Dream messages: the messaging building block of the system.

This tutorial shows:

  • How to build a service with multiple features.
  • How to use request verb wildcards.
  • How to use the XDoc class.

Getting Started

Ok, let's begin by creating our service skeleton.  As before, we'll start by including the MindTouch.Dream namespace and defining a new class derived from DreamService.

using MindTouch.Tasking;

namespace MindTouch.Dream.Samples {
    using Yield = System.Collections.Generic.IEnumerator<IYield>;

    [DreamService("Dream Tutorial Show Headers", "Copyright (c) 2006, 2007 MindTouch, Inc.",
        Info = "http://doc.opengarden.org/Dream_SDK/Tutorials/Show_Headers",
        SID = new string[] { "http://services.mindtouch.com/dream/tutorial/2007/03/showheaders" }
    )]
    public class ShowHeadersService : DreamService {
    }
}

A Dream message is composed of three parts:

  • Status code: this is the result code associated with the message.  A successful message has status code 200 (ok). Go here to learn morea about HTTP status codes.  If the message is a request, its status code is always 200 (ok).
  • Headers: a message has associated headers describing its contents and providing context around the body.
  • Body: a message contains a payload or body.  Message can either have an XML document or a binary stream as a body.
    • Document: this property is set when the body of a message is an XML document.  It can be accessed multiple times.
    • Bytes: this property converts the body into a byte array.  It can be accessed multiple times.
    • Text: this property converts the body into a string.  It can be accessed multiple times.
    • Stream: this property is set when the body of a message is a binary stream.  A stream can only be read once!

Our service will allow us to visualize these parts for any message.

Flexible Features

In our 8-ball service example, we were introduced to HTTP verbs.  We learned that we could associate a feature with a specific verb.  However, in our case, we're interested in capturing a request to our feature regardless of its verb.  This can easily be accomplished by using the the wildcard symbol "*", which will match any verb.

Let begin by defining a feature to return the headers of our Dream message.

[DreamFeature("*:headers", "Get message headers of request")]
public Yield WildCardHeaders(DreamContext context, DreamMessage request, Result<DreamMessage> response) {

}

This will match any request to our service that invokes the headers feature.  So, if our service runs at http://localhost:8081/show-headers then any request to http://localhost:8081/show-headers/headers will invoke the above method.

Now onto the brunt of our service.  We want to capture a Dream message and convert its headers to an XML document and return it.  Fortunately, there is already a class that takes care of most of this.  The XMessage class is derived from XDoc, our handy XML document class. XMessage is responsible for converting any Dream message into a XML document.  It's particularly useful when wanting to embed Dream messages into a larger context.

However, in our case, it does too much since we only want the headers.  This is where XDoc starts to show its magic.  Every XDoc is always a valid XML document.  Thus, we can use its indexer property (doc[index]) to select the desired node from XMessage and return it.  This is exactly what the following code does:

public Yield WildCardHeaders(DreamContext context, DreamMessage request, Result<DreamMessage> response) {

    // convert dream message into an XML document
    XDoc xmessage = new XMessage(request);

    // select <headers> element
    XDoc headers = xmessage["headers"];

    // send it back
    response.Return(DreamMessage.Ok(headers));
    yield break;
}

Without going into further detail, it is worthwhile mentioning that the "headers" string used in the indexer property of XMessage (which is really just a specialized XDoc) is actually an XPath expression.  It is thus possibly to create very sophisticated expressions to select a desired node or set of nodes. Learn more about XDoc here.

Let's add two more features: one for returning just the body and another for returning the complete message.

[DreamFeature("*:body", "Get message body of request")]
public Yield WildCardBody(DreamContext context, DreamMessage request, Result<DreamMessage> response) {

    // convert dream message into an XML document
    XDoc xmessage = new XMessage(request);

    // select first child of <body> element
    XDoc body = xmessage["body"];

    // respond by sending only the body back
    response.Return(DreamMessage.Ok(body));
    yield break;
}

[DreamFeature("*:message", "Get entire request message")]
public Yield WildCardMessage(DreamContext context, DreamMessage request, Result<DreamMessage> response) {

    // convert dream message into an XML document
    XDoc xmessage = new XMessage(request);

    // respond by sending the message back
    response.Return(DreamMessage.Ok(xmessage));
    yield break;
}

Running the service

Now we only need to write our launch script and we're ready to roll. Let's save it as show-headers.startup.xml.

<script>
  <!-- register the blueprint for our show-headers service -->
  <action verb="POST" path="/host/load?name=dream.sample.show-headers" />

  <!-- instantiate it -->
  <action verb="POST" path="/host/services">
    <config>
      <path>show-headers</path>
      <sid>http://services.mindtouch.com/dream/tutorial/2007/03/showheaders</sid>
      </config>
  </action>
</script>

Compile the service into an assembly file and copy into your bin folder where the other dream binaries are.  (Note: this is automatically done by the Visual Studio.Net samples solution file and the makefile.)

Let's start the MindTouch Dream host application with our service configuration file:

mindtouch.host.exe script show-headers.startup.xml

Now, let's try it out by using our browser to go to http://localhost:8081/show-headers/message .  If everything worked as planned, you should see something like the following output in your browser:

<message>
	<status>200</status>
	<headers>
		<Connection>keep-alive</Connection>
		<Keep-Alive>300</Keep-Alive>
		<Accept>text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5</Accept>
		<Accept-Charset>ISO-8859-1,utf-8;q=0.7,*;q=0.7</Accept-Charset>
		<Accept-Encoding>gzip,deflate</Accept-Encoding>
		<Accept-Language>en-us,en;q=0.5</Accept-Language>
		<Host>localhost:8081</Host>
		<Content-Length>0</Content-Length>
		<Content-Type>text/plain</Content-Type>
		<Content-Encoding>Windows-1252</Content-Encoding>
	</headers>
	<body format="text"/>
</message>

The <status> element holds the status code of the message.  Since this message was a request, it's status is 200.  The <headers> element contains the list of HTTP headers sent by the browser. Finally, there is the <body> element, which is an empty text string since this was a GET message.

Tag page

Files 2

FileSizeDateAttached by 
 show-headers.startup.xml
Show-Headers service startup XML
396 bytes21:04, 23 Mar 2007SteveBActions
ShowHeaders.cs
Show-Headers service sample
2.97 kB15:14, 14 Oct 2007SteveBActions
You must login to post a comment.