Login with: Google Twitter Facebook Local

Avoiding The Needless Multiplication Of Forms

Implementing interactive features

Dr Andrew Moss


Part 1: How comments should work

After implementing OAuth2 last week I have authenticated access to pages on this server. Everything is sitting behind an nginx front-end server to handle TSL, so I can assume that the contents of pages (and the requests that fetch them) are confidential. This makes adding interactive features substantially easier. A rough conceptual overview of what I wanted to achieve looks like this:
Requests and responses are handled by the server fetching content from static and dynamic storage, splicing it together and delivering pages to the user. The easiest way to implement this is by writing handlers for the GET and the POST and creating a system that looks like this:
This is functional, but clunky. It behaves like most forums or comments have since those hooks were CGI scripts. It lacks interactivity - the only point of interaction is when the user presses submit. At this point they are commited to what they've already typed. They won't get to see what it looks like until after the comment has been commited to storage and the page has been reloaded.
This is problematic for two reasons:
  1. People typically see errors when what they have written changes form. This is because we do not really read what we've written again (without deliberate effort) - we simply scan it and remember what we intended to write.
  2. Supplying a richer text format (e.g. Markdown) means the user is reading/writing raw source, not the styled output, so it is difficult to parse and then project onto what it will look like after it is styled.
Both of these problems can be solved by providing a live preview of the comment: take the raw source as it is typed and regenerate the styled output. This is the modern type of interface that we see on a site such as stackoverflow. In order to convert the Markdown source into styled text we need to implement a parser and rendered. There are different options for how to structure this:
I've decided to use the Go implementation, mainly because it already runs on the server to render the blog pages. Reusing the same code means that I don't have to translate it into Javascript, and then try to keep both pieces of code in sync as they change over time.
The system looks something like this:
When a user logs in we create a session to store their credentials. Each GET from the user passes back a login cookie that identifies the session (it decodes to the key) so that we can associate requests with the user that made them. This is the only cookie that we need to store in the user's browser, and it is one that we do not need consent to store.
When the user starts typing (we only show the comment editor form to logged in users) a websocket is opened to the server and the login cookie is sent to identify the connection. We use a simple protocol over this connection, which is implemented by encoding the messages as JSON and using a label field to identify the kind of message:
preview To server Markdown source for rendering
post To server Markdown for finished post, add to storage
Preview To client HTML of comment for display
Update To client HTML of all comments on page
Posted To client Confirmation that comment is stored
One of the normal consequences of a CGI-style comment posting system is duplicate posts. Typically these happen because when the user presses submit they do not see any feedback quickly enough - so they get impatient and hit submit several times. This is easy to avoid when the system is implemented with a Javascript in the browser communicating with the Go server. Because there are no page loads during the comment posting process we have the same state in the browser across the process. We use this to disable the submit button when it is pressed. When the browser receives the confirmation that the comment has been stored it wipes the text entry field and re-enables the button. This happens shortly after the Update message causes the list of comments in the page to be rewritten - so we provide constant visual feedback to the user.
Next time I'll show the pieces of code and walk through how they work...


Markdown syntax...

Sign in at the top of the page to leave a comment