-
Notifications
You must be signed in to change notification settings - Fork 3
Home
This tutorial will cover the basics of the Web Framework Done Right (WFDR) and detail how to write a module conforming to the framework. You should be familiar with the following terms used throughout this walkthrough.
-
Source directory: The root of the Git repository, usually
/somewhere/git-web
. -
Module source directory: The root directory of the module you are working on (
<source directory>/modules/helloworld/
in this tutorial) - Module source tree: The root directory of the module you are working on or a sub-directory thereof that is most convenient for your current task
This step will eventually be removed, but for now you have to find a free port to run your hello world example on. At the time of this writing, port 8085 is free so we will use that. In order to tell the reverse HTTP proxy server where we are and what it should do when it gets a request for us, we have to add our port to the list in /modules/base/src/proxy.go .
Find this line:
Servers = map[string]string {"clubs": ":8082", . . . }
And at the end of the map, before the closing brace, add your module:
Servers = map[string]string {"clubs": ":8082", . . ., "helloworld": ":8085"}
The proxy server is now configured to serve requests to your module, listening on port 8085, when it gets requests on /helloworld or any sub-paths thereof. Now, recompile and restart the base module:
wfdr recompile base
wfdr restart base
If you visit http://localhost:8080/helloworld/ , you should get a 503 error. If you get a different error, make sure you did everything right and ask me.
You can write modules in any language you like, but the supporting framework and general support is best for Go (which is what I know). Thus, I will write this section using Go as an example.
First, make a directory for your module in modules/ .
mkdir modules/helloworld
Next, make the source directory. Here it is likely helpful to have two terminals or tabs open, one at the source root (for wfdr start/stop), and one in the module source tree, to actually work on the files.
mkdir
modules/helloworld/src
cd
modules/helloworld/src
# Do this in terminal for working on the source
Now, we are going to write the actual go code. You can name your go files anything you like, but for the purposes of explanation we are naming our main file helloworld.go .
package main
import
(
“fmt”
“http”
)
func
HelloHandler(c http.ResponseWriter, r *http.Request) {
fmt.Fprintln(c, “hello world!”)
}
func
main() {
http.HandlerFunc(“/helloworld/”, HelloHandler)
http.ListenAndServe(“:8085”,
nil
)
}
Ok, that’s great, but how does the framework know how to compile it? For that, we need a Makefile . Fortunately, go makes this easy:
include
$(
GOROOT
)
/src/Make.inc
TARG
=../bin/helloworld
GOFILES
=
\
helloworld.go
include
$(
GOROOT
)
/src/Make.cmd
Whew! Alright, now it’s time to test our module. Switch to the terminal that is *not* in the source directory, and compile + start the module:
wfdr compile helloworld
wfdr start helloworld
Ok, now go to http://localhost:8080/helloworld/ again, and you should see “Hello world” displayed, plain and simply, with no menus, footer, or any of the other “usual” elements. Don’t worry about this for now, it is to be expected. Double check what you’ve done up to this point, and let me know if you can’t get it to work.
Ok, so you’ve made your hello world module, but it’s plain . No menus, no footers, no fancy html5 canvas animations. If a visitor were to visit your page, they would most likely become quite confused. However, it your module only provides, say, a javascript API, then this is not an issue. For example, the openid module doesn’t use any pretty elements, since the user never actually sees it. Nevertheless, you want users to flock to your fancy helloworld module, so lets give it some pretty elements. In order to achieve this, you’ll want to use the “util/template” library, and make your templates in tmpl/. JavaScript files can go in js/, css files in css/, etc. See the layout section of the framework documentation for more details on the layout of these folders and how they work. Our new module looks like this:
package main
import
(
“fmt”
“http”
// Local imports
"util/template"
)
func
HelloHandler(c http.ResponseWriter, r *http.Request) {
template.Render(c, r,
"Hello World!"
,
"main"
,
nil
)
return
}
func
main() {
template.SetModuleName(
"helloworld"
)
http.HandlerFunc(“/helloworld/”, HelloHandler)
http.ListenAndServe(“:8085”,
nil
)
}
Now, we are going to add the template referenced by the template.Render() call to tmpl/. From the module source directory:
mkdir -p tmpl/base
Here, base is the layout that the template belongs to. Now, edit the main file that we referenced above:
{{>shared/html-header}}
{{>shared/head-header}}
{{>shared/head-end}}
{{>shared/body-header}}
Hello World!
{{>shared/body-end}}
{{shared/html-end}}
Here, each of the {{>something}} parts is a partial , and is analogous to include in other languages/frameworks. It is used in order to avoid you repeating the same boilerplate over and over again, and provides something similar to sections in other web frameworks, such as django. However, it is more extensible, since you can define the markup required for the start of a particular section, as well as for the end, and allow individual templates to customize the contents. You’re done! To see the changes, compile and restart the module:
wfdr compile helloworld
wfdr restart helloworld
Generally, there are “best practices” when programming modules; concepts that are encouraged, but not required. First of all, you should stick to the formatting guidelines , in order to ensure that your code has optimum readability for other programmers or developers who might have to deal with it down the line. That is perhaps the most important, but there are several other best practices that you should stick to.