Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 232 lines (159 sloc) 6.561 kb
020e707 @gregorycollins Write most of the README
gregorycollins authored
1 # CUFP 2011 Tutorial: Web programming in Haskell with the Snap Framework
2
3 This repository contains code for the CUFP 2011 tutorial
4 [The Snap Framework for web applications in Haskell](http://cufp.org/conference/sessions/2011/t7-snap-framework-web-applications-haskell-gregory).
5 You will be building a simplified web application implementing multi-user chat.
6
7
8 ## Getting started
9
10 From the project root directory, running `cabal install` should build the
11 `snap-chat` and `snap-chat-sample` executables. You can find these executables
12 in the `dist/build/` subdirectory. To run the sample application (to see what
13 the result should look like), run
14 `dist/build/snap-chat-sample/snap-chat-sample` and point your browser to
15 [`http://localhost:8000/`](http://localhost:8000/).
16
17 The sample implementation of the code you're expected to provide can be found
18 in the `sample-implementation/` directory; however **please don't peek** unless
19 you get really stuck. We'll be working through the code together.
20
21 Test code (so you can test your implementation against the expected result) can
22 be found in the `test/` directory; to run it:
23
24 cd test
25 cabal install
26 ./runTestsAndCoverage.sh
27
28
29 ## Specifications
30
31 Snap Chat is split into three functional components:
32
33 * a data model, consisting of Haskell code for interacting with a chat
34 channel; see `src/Snap/Chat/Types.hs`, `src/Snap/Chat/ChatRoom.hs`, and
35 `src/Snap/Chat/Message.hs` for the implementation here.
36
37 * a JSON API that provides access to the data model; this consists of HTTP
38 `POST` handlers for the URL endpoints:
39
40 * `/api/join`, to join the chat channel
41 * `/api/leave`, to leave the chat channel
42 * `/api/fetch`, to fetch new messages written to the chat channel (using
43 long-polling)
44 * `/api/write`, to write a message to the chat channel.
45
46 These API endpoints will be described in further detail later.
47
48 * an HTML5/Javascript front end that calls the JSON api.
49
50 For brevity and to bound the amount of work students are expected to do in the
51 short tutorial, most of the code is already provided, including all of the
52 JavaScript (this is a Haskell tutorial!), the data model code, and all of the
53 datatypes. More advanced students who quickly breeze through the small amount
54 of work provided can check out the "extra credit" section at the end of this
55 document.
56
57
58 ### API documentation
59
60 Each of the four API calls (`/api/join`, `/api/leave`, `/api/fetch`,
61 `/api/write`) share a similar structure: they all respond only to POST requests
62 containing a UTF8-encoded JSON document as the request body; i.e. the
63 `Content-Type` of the input request is `application/json`, and they all produce
64 a JSON document as the result. The output responses have the following common
65 structure: either they succeed, producing a document like the following:
66
67 {
68 "status": "ok",
69 "session": "DF1642....038A=",
70 "response": { ...some json object... }
71 }
72
73 When they fail, the output document looks like this:
74
75 {
76 "status": "failure",
77 "statusCode": "some_failure",
78 "reason": "blah blah blah blah."
79 }
80
81 The "session" variable above deserves some special mention: upon successfully
82 joining the chat room, the user will receive an encrypted session token, which
83 will be used on subsequent requests to re-authenticate the user with the chat
84 room. Upon each response, a fresh session token will be generated. The contents
85 of the session token are opaque to the API user, but can be decrypted on the
86 server-side.
87
88 The data type for the encoded session looks like this (see
89 `src/Snap/Chat/Internal/API/Types.hs`):
90
91 data EncodedSession = EncodedSession {
92 _sessionToken :: UserToken
93 , _sessionTime :: EpochTime
94 , _apiUser :: UserName
95 }
96
97 A session will only be considered valid if:
98
99 * the session time is not too old.
100
101 * the user name and user token match what is contained in the chat room data
102 model.
103
104
a1f389c @gregorycollins Tweak readme.md
gregorycollins authored
105 #### /api/join
020e707 @gregorycollins Write most of the README
gregorycollins authored
106
107 The "join" command is responsible for connecting a user to the chat room with a
108 given user name.
109
110 Example request:
111
112 { "desiredUserName": "george" }
113
114 Example successful response:
115
116 {
117 "status": "ok",
118 "session": "abc.....def",
119 "response": {}
120 }
121
122 Example unsuccessful response:
123
124 {
125 "status": "failure",
126 "statusCode": "user_already_exists",
127 "reason": "Cannot log in; a user with that name is already connected \
128 to the channel."
129 }
130
131
a1f389c @gregorycollins Tweak readme.md
gregorycollins authored
132 #### /api/leave
020e707 @gregorycollins Write most of the README
gregorycollins authored
133
134 The "leave" command logs the user out of the chat room.
135
136 Example request:
137
138 {
139 "session": "abc.....def",
140 "requestData": {}
141 }
142
143 Example successful response:
144
145 {
146 "status": "ok",
147 "session": "abc.....def",
148 "response": {}
149 }
150
a1f389c @gregorycollins Tweak readme.md
gregorycollins authored
151 #### /api/fetch
020e707 @gregorycollins Write most of the README
gregorycollins authored
152
153 The "fetch" command gets new messages from the chat room, blocking for up to 50
154 seconds before it returns with a list of new messages, possibly empty.
155
156 Example request:
157
158 {
159 "session": "abc.....def",
160 "requestData": {}
161 }
162
163 Example successful response:
164
165 {
166 "status": "ok",
167 "session": "abc.....def",
4f81bc3 @gregorycollins Commit tests for JSON instances
gregorycollins authored
168 "response": { "messages": [ ...messages... ] }
020e707 @gregorycollins Write most of the README
gregorycollins authored
169 }
170
171 The JSON type of messages is as follows:
172
173 { "contents": {
174 "type": <<one of "talk", "action", "join", "leave">>,
175 "text": "message text"
176 },
177 "user": "fred",
178 "time": <<posix timestamp>>
179 }
180
181
a1f389c @gregorycollins Tweak readme.md
gregorycollins authored
182 #### /api/write
020e707 @gregorycollins Write most of the README
gregorycollins authored
183
184 The "write" command writes a message to the chat room.
185
186 Example request:
187
188 {
189 "session": "abc.....def",
190 "requestData": {
191 "type": <<one of "talk", "action">>,
192 "text": "message text"
193 }
194 }
195
196 Example successful response:
197
198 {
199 "status": "ok",
200 "session": "abc.....def",
201 "response": {}
202 }
203
204
205 ## What students must implement
206
8cec333 @gregorycollins Stub out functions to be implemented by students.
gregorycollins authored
207 Several functions and instances in the source tree have been marked as
208 "toBeImplemented". Tutorial attendees must implement:
209
210 * `ToJSON` and `FromJSON` instances for the types in
211 `src/Snap/Chat/Internal/API/Types.hs`.
212
213 * `ToJSON` and `FromJSON` instances for the message types in
214 `src/Snap/Chat/Internal/Types.hs`.
215
216 * all of the stubbed-out functions in `src/Snap/Chat/API/Handlers.hs`.
217
218 You'll need to use the functions from `src/Snap/Chat/ChatRoom.hs`, which
219 contains all of the "business logic" for the chat rooms.
020e707 @gregorycollins Write most of the README
gregorycollins authored
220
221
222 ## Extra credit
223
224 If you finish early and get bored, here are some ideas for "extra-credit"
225 assignments:
226
227 * extend the chat channel with a user list
228
229 * add private user-to-user messages
230
231 * support multiple chat rooms
Something went wrong with that request. Please try again.