Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

tutorial files

  • Loading branch information...
commit 6f920f9ba39efa2d35f7ccea9f9628471ab7abca 1 parent e785598
@nicferrier authored
Showing with 450 additions and 0 deletions.
  1. +323 −0 elnode_tutorial.creole
  2. +127 −0 elnode_tutorial.org
View
323 elnode_tutorial.creole
@@ -0,0 +1,323 @@
+= 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.
+
+
+== Intalling Elnode ==
+
+Elnode is now packaged in [[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 {{{ENTER}}} 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 8028 "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 [ENTER] elnode-webserver-docroot [ENTER]
+}}}
+
+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:
+
+{{{
+(defvar my-elnode-webserver-handler
+ (elnode-webserver-handler-maker "~/myspecialdocroot"))
+(elnode-start my-elnode-webserver-handler 8001 "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 [ENTER] 8028 [ENTER]
+M-x elnode-stop [ENTER] 8001 [ENTER]
+}}}
+
+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-server-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))
+ (insert (if (stringp change-text)
+ 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}}}:
+
+(defvar 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.
+
+== That's all for now! ==
+
+This is as far as Nic has got writing the tutorial. More will come soon I hope:
+
+* making the editor service better by adding static content
+* {{{defer}}} with an example based around the editor service
+* debugging a running Elnode service
View
127 elnode_tutorial.org
@@ -0,0 +1,127 @@
+
+* suggestions
+** How about going from "hello world" on?
+*** Start with that,
+*** and then, move on to publishing a static file,
+*** then a buffer,
+**** with calling functions to manipulate the buffer and re-present it?
+** That'd save me a fair bit of tinkering :)
+
+* installing
+** use elpa/marmalade
+* what elnode gives you by default
+** require elnode
+*** elnode-init
+**** starts a server
+***** on port 8000
+
+
+* hello world
+** install elnode with marmalade
+** open a new emacs buffer C-x C-f my-elnode-hello-world.el
+** make a handler
+(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 8028 "localhost")
+** now evaluate that with M-x eval-buffer
+** now open localhost:8028 in your browser
+
+* publish some files
+** elnode provides a webserver, more accurately a fileserver
+** the webserver is turned on by default
+** open localhost:8000 and you should see ~/public_html
+*** if you don't have ~/public_html then make one?
+*** or configure elnode-webserver-docroot
+** make a new webserver
+*** make a new docroot
+**** mkdir ~/myspecialdocroot
+*** put an html file in there
+cat <<EOF > ~/myspecialdocroot/saybum.html
+<html>
+<h1>BUM!</h1>
+</html>
+*** open a new emacs buffer
+*** put the following lisp in
+(defvar my-elnode-webserver-handler
+ (elnode-webserver-handler-maker "~/myspecialdocroot"))
+(elnode-start my-elnode-webserver-handler 8001 "localhost")
+*** now evaluate that with M-x eval-buffer
+*** now open localhost:8001/saybum.html
+*** now open localhost:8001
+**** you should see an automatic index
+
+* stopping a server
+** stop 8028
+** stop 8001
+
+* add a binding to the standard server
+** we can add bindings to the standard elnode server
+** go back to hello world - C-x b my-elnode-hello-world.el
+** remove the server-start and add this:
+(add-to-list 'elnode-hostpath-default-table '("/helloworld/" . my-elnode-hello-world-handler))
+** so now it should be:
+(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 localhost:8000/helloworld/ in your browser
+** just to prove the webserver is still there, open localhost:8000/
+*** check it's still the directory ~/public_html
+** check the variable elnode-hostpath-default-table with C-h v elnode-hostpath-default-table
+Its value is (("/helloworld/" . my-elnode-hello-world-handler)
+ ("[^/]+/.*" . elnode-webserver))
+** elnode-hostpath-default-table can also be customized
+*** but any handler will have to be loaded so you probably need to package and load your elnode module
+
+* publishing something else?
+** let's try and make an online editor
+** make a new file my-elnode-editor.el
+(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
+** go type some data in *my-elnode-editor-buffer*
+** then M-x elnode-start my-elnode-editor-handler 8002 localhost
+** try and hit localhost:8002
+** go update the buffer
+** refresh the webpage
+** but what about someone else updating the buffer?
+** make another handler to handle updates
+(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))
+ (insert (if (stringp change-text)
+ change-text
+ ""))))
+ (elnode-http-start httpcon 302 '("Location" . "/"))
+ (elnode-http-return httpcon))
+** now we need to map these two handlers
+*** one to / and the other to /update/
+** make a new variable
+(defvar my-elnode-editor-urls
+ `(
+ ("$" . my-elnode-editor-handler)
+ ("update/.*$" . my-elnode-editor-update-handler)))
+** and make a dispatcher handler for the urls
+(defun my-elnode-editor-dispatcher-handler (httpcon)
+ (elnode-dispatcher httpcon my-elnode-editor-urls))
+*** a dispatcher handler is a handler that accepts requests and dispatches them to further handlers.
+*** moar about dispatcher handlers.
+** now stop the old server
+** M-x elnode-stop 8002
+** Now start the new server with the dispatcher handler
+** then M-x elnode-start my-elnode-editor-dispatcher-handler 8002 localhost
+** now visit localhost:8002 and see the buffer
+** now visit localhost:8002/update/?change=lah+dee+dah%0d and see the updated buffer
Please sign in to comment.
Something went wrong with that request. Please try again.