= Getting Started with Elnode - the webserver for Emacs =

This is a tutorial that will hopefully show you how to install and get
started making web services with Elnode.

Elnode is a node.js like webserver tool for Emacs. It let's you make
and run web servers and services from inside Emacs.


== Installing Elnode ==

You should install Elnode from the package available on
[[http://marmalade-repo.org/packages/elnode|Marmalade]].

For dealing with package repositories check out the
[[http://www.emacswiki.org/emacs/ELPA|Emacs Wiki]] but the short version
is to add the following to your {{{.emacs}}} or your
{{{.emacs.d/init.el}}}:

{{{
(add-to-list 
   'package-archives
   '("marmalade" . "http://marmalade-repo.org/packages/"))
}}}

And then do:

{{{
M-x list-packages
}}}

find Elnode in the list and press {{{i}}} or {{{RET}}} to install it.

If you don't want to use packages you can just install {{{elnode.el}}}
on your {{{load-path}}} somewhere and:

{{{
(require 'elnode)
}}}

== Hello World! ==

Now we've installed Elnode you'll want to start making web services
with it. Let's start with a Hello World example.

open a new Emacs file 

{{{
C-x C-f my-elnode-hello-world.el
}}}

enter the Lisp code for the handler, for that old time feel you could type this in, or if you're under 35, maybe just cut and paste 

{{{
(defun my-elnode-hello-world-handler (httpcon)
   (elnode-http-start httpcon 200 '("Content-Type" . "text/html"))
   (elnode-http-return 
       httpcon 
       "<html><body><h1>Hello World</h1></body></html>"))
(elnode-start 'my-elnode-hello-world-handler :port 8028 :host "localhost")
}}}

make the Lisp code //live//

{{{
M-x eval-buffer
}}}

now open [[http://localhost:8028]] in your browser - you should see //Hello World!//


== Publish some files ==

Elnode provides a builtin webserver that can serve files from a
directory on your computer. The Elnode webserver is turned on by
default (it's all configurable though).

=== The default webserver ===

By default the webserver delivers files from:

{{{
~/public_html
}}}

so if you have a public_html directory in your home directory then
just browse to [[http://localhost:8000]] and you should see an index
of that directory.

If you don't have a {{{~/public_html}}} directory then just make one
and drop a file or two in it.

Alternately, try configuring the webserver root directory:

{{{
M-x customize-variable RET elnode-webserver-docroot RET
}}}

to another directory. Then try hitting [[http://localhost:8000]]
again.


=== Making another webserver ===
Now let's make a new webserver service.

Make a new docroot:

{{{
mkdir ~/myspecialdocroot
}}}

Put an html file in there:

{{{
cat <<EOF > ~/myspecialdocroot/saybum.html
<html>
<h1>BUM!</h1>
</html>
}}}

Now we have something to serve we can use Elnode to make the web service.

Open a new Emacs file:

{{{
C-x C-f my-elnode-webserver.el
}}}

Add this Lisp:

{{{
(defconst my-elnode-webserver-handler
   (elnode-webserver-handler-maker "~/myspecialdocroot"))
(elnode-start my-elnode-webserver-handler :port 8001 :host "localhost")
}}}

Now evaluate that with: {{{M-x eval-buffer}}}

Now open [[http://localhost:8001/saybum.html]]

Now open [[http://localhost:8001]] - you should see an automated index
of {{{~/myspecialdocroot}}}.

== Stopping a server ==

We've started a couple of servers now. Let's stop the two servers that
we've started:

{{{
M-x elnode-stop RET 8028 RET
M-x elnode-stop RET 8001 RET
}}}

Those servers are now stopped and you won't be able to hit them.

== Add a binding to the builtin server ==

Instead of starting new servers all the time we can add bindings to
the standard Elnode server. Why would we do this? I think using a
separate server for developing something initially is a good idea, but
then you either have something you want to package up as it's own
server (a wiki engine you've developed and want to give to other
people, for example) or you have something you want to make available
in your own default server. Of course, it's always a judgement, the
way URLs work mean that you can pretty much always make any service
available on it's own server or under a URL on another one.

Let's make our Hello World example available again by binding it to
the default server (which is still listening on port 8000 if you
haven't changed anything).

Go back to hello world:

{{{
C-x b my-elnode-hello-world.el
}}}

Remove the {{{elnode-start}}} line and add this:

{{{
(add-to-list 'elnode-hostpath-default-table '("/helloworld/" . my-elnode-hello-world-handler))
}}}

So now it should look like this:

{{{
(defun my-elnode-hello-world-handler (httpcon)
   (elnode-http-start httpcon 200 '("Content-Type" . "text/html"))
   (elnode-http-return 
       httpcon 
       "<html><body><h1>Hello World</h1></body></html>"))
(add-to-list 'elnode-hostpath-default-table '("/helloworld/" . my-elnode-hello-world-handler))
}}}

Now eval the buffer with {{{M-x eval-buffer}}}

Now open [[http://localhost:8000/helloworld/]] in your browser.

Just to prove the webserver is still there, open
[[http://localhost:8000/]]. This should still show your
{{{~/public_html}}} directory (or whatever you configured
{{{elnode-webserver-docroot}}} to).

Check the variable {{{elnode-hostpath-default-table}}} with {{{C-h v elnode-hostpath-default-table}}}

The value should be something like:

{{{
(("/helloworld/" . my-elnode-hello-world-handler)
("[^/]+/.*" . elnode-webserver))
}}}

{{{elnode-hostpath-default-table}}} can also be customized to add more
services. But any handler mapped in there will have to be loaded in at
Emacs startup so you either need to package and load your Elnode code
or put it in your {{{load-path}}} and {{{require}}} it from Emacs
init.

== A more advanced example - publishing a buffer ==

So far, all the examples have been quite trivial. Though I hope you
think it's interesting that you can do all these things quite easily
from inside Emacs.

But now let's try something harder - let's make an web based editor.

This is an exercise that will grow with the tutorial. I hope you'll be
interested in the first draft, even though it's going to be relatively
simple.

Make a new file {{{C-x C-f my-elnode-editor.el}}}.

Add the following Lisp code:

{{{
(defvar my-elnode-editor-buffer (get-buffer-create "*my-elnode-editor-buffer*"))

(defun my-elnode-editor-handler (httpcon)
  (elnode-http-start httpcon 200 '("Content-Type" . "text/plain"))
  (elnode-http-return 
   httpcon 
   (with-current-buffer my-elnode-editor-buffer
     (buffer-substring-no-properties (point-min) (point-max)))))
}}}

Eval that with {{{M-x eval-buffer}}}.

Now go and type some text in ~*my-elnode-editor-buffer~*. This will be
served by the editor service.

Now let's start the service:

{{{
M-x elnode-start 
my-elnode-editor-handler 
8002 
localhost
}}}

Now try and hit [[http://localhost:8002]] - you should see whatever
you typed in the ~*my-elnode-editor-buffer~*.

Try updating the text in the buffer and refreshing the browser. We're
displaying that buffer whatever it has in it.

Ok. So we've published a buffer. But what about someone else updating
it?

Let's make another handler to handle updates, add this to your {{{my-elnode-editor.el}}}:

{{{
(defun my-elnode-editor-update-handler (httpcon)
  (let ((change-text (elnode-http-param httpcon "change")))
    (with-current-buffer my-elnode-editor-buffer
      (goto-char (point-max))
      (if (stringp change-text)
          (insert change-text))))
  (elnode-http-start httpcon 302 '("Location" . "/"))
  (elnode-http-return httpcon))
}}}

Now we have two handlers we'll have to map them together
somehow. Let's map one to the root ({{{/}}}) and one to
{{{/update/}}}. Add the following code to {{{my-elnode-editor.el}}}:

{{{
(defconst my-elnode-editor-urls
  `(("^/$" . my-elnode-editor-handler)
    ("^/update/.*$" . my-elnode-editor-update-handler)))
}}}

And now we need to add a handler to do the dispatching for these URLs,
add this to {{{my-elnode-editor.el}}} as well:

{{{
(defun my-elnode-editor-dispatcher-handler (httpcon)
  (elnode-dispatcher httpcon my-elnode-editor-urls))
}}}

//What is a dispatcher?// - a dispatcher is a handler that take a list
of URL pattern mappings and works out, by reading the data from the
HTTP connection, what handler should be invoked for what request.

Now we have our new dispatcher based code we need to stop the old server:

{{{
M-x elnode-stop 8002
}}}

And now start the new server with the dispatcher handler:

{{{
M-x elnode-start 
my-elnode-editor-dispatcher-handler 
8002 
localhost
}}}

Now visit [[http://localhost:8002]] and see the buffer as it stands
and then visit
[[http://localhost:8002/update/?change=%0dlah+dee+dah%0d]] and see the
updated buffer.

== More advanced again - Make a webapp around the service ==

Let's take our editor on another step. Let's add some static files and
have the Elnode handlers be called by client side Javascript.

If we're going to add some static files, we'll need a webserver. We
already know how to do that. Once we've got some javascript though,
we'll probably not want to retrieve the text by {{{HTTP GET}}}ing the
root url, so let's alter that binding to {{{/text/}}} as well:

{{{
(defconst my-elnode-editor-webserver-handler
   (elnode-webserver-handler-maker "~/my-directory")
   "The webserver handler.")

(defconst my-elnode-editor-urls
  '(("^/text/$" . my-elnode-editor-handler)
    ("^/update/.*$" . my-elnode-editor-update-handler)
    ("^/[^/]+/.*$" . my-elnode-editor-webserver-handler)))
}}}

Obviously {{{~/my-directory}}} needs to be the place where you are
going to save your HTML and Javascript files.

Now we need those HTML and Javascript files. Let's make the HTML
first:

{{{
<html>
    <head>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js" 
                language="Javascript">
        </script>
        <script src="my-elnode-editor.js" language="Javascript">
        </script>
    </head>
    <body>
        <textarea id="text" cols="60" rows="10">
        </textarea>
    </body>
</html>
}}}

We're going to pull jQuery from Google's Content Delivery
Network. We've put in a placeholder for our own Javascript file and
other than that the HTML is really just a {{{textarea}}}
element. We'll use //that// for putting the buffer text in.

Now, what should the Javascript do? 

* when the page loads
* make an AJAX call to Elnode for the buffer text
* stick the received text into the {{{textarea}}}

Ok. So here is {{{my-elnode-editor.js}}}:

{{{
var my_elnode_editor = (function () {
  var self = {
    /** Get the text from Emacs.
     */
    get_text: function () {
      $.ajax("/text/", {
        dataType: "text",
        success: function (data, textStatus, jqXHR) {
          $("#text").text(data);
        }
      });
    }
  };
  return self;
})();

$(document).ready(
  function () {
    my_elnode_editor.get_text();
  }
);
}}}

Save this as {{{my-elnode-editor.js}}} (in whatever directory the
webserver is serving) and save the HTML in the same directory, call it
{{{my-elnode-editor.html}}}, say?

You don't even have to restart the Elnode handler, because it already
is pointing to the dispatcher handler. If you just:

{{{
M-x eval-buffer
}}} 

this will re-evaluate the URL mappings. Now if you visit
[[http://localhost:8002/my-elnode-editor.html]] you should see the
webpage with the {{{textarea}}} and the text of your buffer.



== That's all for now! ==

This is as far as Nic has got writing the tutorial. More will come soon I hope:

* {{{defer}}} with an example based around the editor service
* debugging a running Elnode service
