|
| 1 | +--- |
| 2 | +sidebar_position: 3 |
| 3 | +description: Build a simple "Counter" application. |
| 4 | +--- |
| 5 | + |
| 6 | +# Counter β |
| 7 | + |
| 8 | +:::info |
| 9 | +**Difficulty**: π’ Beginner<br/> |
| 10 | +**Length**: 15 minutes |
| 11 | + |
| 12 | +Before getting started, [read the prerequisites](/docs/overview#prerequisites) to make sure your development environment is ready. |
| 13 | +::: |
| 14 | + |
| 15 | +## Overview |
| 16 | + |
| 17 | +In this tutorial, we're going to build an app that exposes a single endpoint and responds with the number of times the route was requested. |
| 18 | + |
| 19 | +When we're done, we should be able to make multiple `GET` requests to the `/` endpoint: |
| 20 | + |
| 21 | +```bash |
| 22 | +# 1st time |
| 23 | +curl --request GET \ |
| 24 | + --url http://localhost:8080 |
| 25 | + |
| 26 | +# 2nd time |
| 27 | +curl --request GET \ |
| 28 | + --url http://localhost:8080 |
| 29 | +``` |
| 30 | + |
| 31 | +And our server should respond with the following responses: |
| 32 | + |
| 33 | +``` |
| 34 | +HTTP/1.1 200 OK |
| 35 | +Connection: close |
| 36 | +Content-Length: 21 |
| 37 | +Content-Type: text/plain; charset=utf-8 |
| 38 | +
|
| 39 | +
|
| 40 | +You have requested this route 1 time(s). |
| 41 | +
|
| 42 | +--- |
| 43 | +
|
| 44 | +HTTP/1.1 200 OK |
| 45 | +Connection: close |
| 46 | +Content-Length: 21 |
| 47 | +Content-Type: text/plain; charset=utf-8 |
| 48 | +
|
| 49 | +
|
| 50 | +You have requested this route 2 time(s). |
| 51 | +``` |
| 52 | + |
| 53 | +## Creating a new app |
| 54 | + |
| 55 | +To create a new Dart Frog app, open your terminal, `cd` into the directory where you'd like to create the app, and run the following command: |
| 56 | + |
| 57 | +```bash |
| 58 | +dart_frog create counter |
| 59 | +``` |
| 60 | + |
| 61 | +You should see an output similar to: |
| 62 | + |
| 63 | +``` |
| 64 | +β Creating counter (0.1s) |
| 65 | +β Installing dependencies (1.7s) |
| 66 | +
|
| 67 | +Created counter at ./counter. |
| 68 | +
|
| 69 | +Get started by typing: |
| 70 | +
|
| 71 | +cd ./counter |
| 72 | +dart_frog dev |
| 73 | +``` |
| 74 | + |
| 75 | +## Running the development server |
| 76 | + |
| 77 | +You should now have a directory called `counter` -- `cd` into it: |
| 78 | + |
| 79 | +```bash |
| 80 | +cd counter |
| 81 | +``` |
| 82 | + |
| 83 | +Then, run the following command: |
| 84 | + |
| 85 | +```bash |
| 86 | +dart_frog dev |
| 87 | +``` |
| 88 | + |
| 89 | +This will start the development server on port `8080`: |
| 90 | + |
| 91 | +``` |
| 92 | +β Running on http://localhost:8080 (1.3s) |
| 93 | +The Dart VM service is listening on http://127.0.0.1:8181/YKEF_nbwOpM=/ |
| 94 | +The Dart DevTools debugger and profiler is available at: http://127.0.0.1:8181/YKEF_nbwOpM=/devtools/#/?uri=ws%3A%2F%2F127.0.0.1%3A8181%2FYKEF_nbwOpM%3D%2Fws |
| 95 | +[hotreload] Hot reload is enabled. |
| 96 | +``` |
| 97 | + |
| 98 | +Make sure it's working by opening [http://localhost:8080](http://localhost:8080) in your browser or via `cURL`: |
| 99 | + |
| 100 | +```bash |
| 101 | +curl --request GET \ |
| 102 | + --url http://localhost:8080 |
| 103 | +``` |
| 104 | + |
| 105 | +If everything succeeded, you should see `Welcome to Dart Frog!`. |
| 106 | + |
| 107 | +## Updating the root route |
| 108 | + |
| 109 | +Now that we have a running application, let's start by updating the root route at `routes/index.dart`: |
| 110 | + |
| 111 | +```dart |
| 112 | +import 'package:dart_frog/dart_frog.dart'; |
| 113 | +
|
| 114 | +Response onRequest(RequestContext context) { |
| 115 | + const count = 1; |
| 116 | + return Response( |
| 117 | + body: 'You have requested this route $count time(s).', |
| 118 | + ); |
| 119 | +} |
| 120 | +``` |
| 121 | + |
| 122 | +Save the changes and hot reload should kick in β‘οΈ |
| 123 | + |
| 124 | +```bash |
| 125 | +[hotreload] - Application reloaded. |
| 126 | +``` |
| 127 | + |
| 128 | +Now if we visit [http://localhost:8080](http://localhost:8080) in the browser or via `cURL`: |
| 129 | + |
| 130 | +```bash |
| 131 | +curl --request GET \ |
| 132 | + --url http://localhost:8080 |
| 133 | +``` |
| 134 | + |
| 135 | +We should see our new response: |
| 136 | + |
| 137 | +``` |
| 138 | +You have requested this route 1 time(s). |
| 139 | +``` |
| 140 | + |
| 141 | +Awesome! There's just one small issue... |
| 142 | + |
| 143 | +Make another request and note that the count does not increment. This is expected because we hard-coded the count in our route handler. Let's fix that by introducing some middleware! |
| 144 | + |
| 145 | +## Creating middleware |
| 146 | + |
| 147 | +In Dart Frog, middleware allows you to execute code before and/or after a request is processed. In this example, we're going to create a piece of middleware that provides a count to our routes. |
| 148 | + |
| 149 | +:::note |
| 150 | +A piece of middleware can modify the inbound request and outbound responses, provide dependencies, and more! [Learn more about middleware](/docs/basics/middleware). |
| 151 | +::: |
| 152 | + |
| 153 | +For this example, we're going to create a single global piece of middleware but a Dart Frog application can consist of multiple pieces of middleware which are scoped to nested routes. |
| 154 | + |
| 155 | +To create a global piece of middleware, we just need to create a file called `_middleware.dart` in the `routes` directory and define a `middleware` method: |
| 156 | + |
| 157 | +```dart |
| 158 | +import 'package:dart_frog/dart_frog.dart'; |
| 159 | +
|
| 160 | +// This piece of middleware does nothing at the moment. |
| 161 | +Handler middleware(Handler handler) { |
| 162 | + return handler; |
| 163 | +} |
| 164 | +``` |
| 165 | + |
| 166 | +Now that we've defined the middleware, we can create our private `count` and provide the count to all sub routes: |
| 167 | + |
| 168 | +```dart |
| 169 | +import 'package:dart_frog/dart_frog.dart'; |
| 170 | +
|
| 171 | +int _count = 0; |
| 172 | +
|
| 173 | +Handler middleware(Handler handler) { |
| 174 | + return handler.use(provider<int>((_) => ++_count)); |
| 175 | +} |
| 176 | +``` |
| 177 | + |
| 178 | +:::tip |
| 179 | +The `use` method on a `Handler` allows you to chain multiple `middleware`. |
| 180 | +::: |
| 181 | + |
| 182 | +In the above snippet, we are automatically incrementing the `_count` whenever the value is read. |
| 183 | + |
| 184 | +The last thing we need to do is update our route handler to use the provided count. |
| 185 | + |
| 186 | +Open `routes/index.dart` and replace the hard-coded count with the provided value using `context.read`: |
| 187 | + |
| 188 | +```dart |
| 189 | +import 'package:dart_frog/dart_frog.dart'; |
| 190 | +
|
| 191 | +Response onRequest(RequestContext context) { |
| 192 | + final count = context.read<int>(); |
| 193 | + return Response( |
| 194 | + body: 'You have requested this route $count time(s).', |
| 195 | + ); |
| 196 | +} |
| 197 | +``` |
| 198 | + |
| 199 | +:::note |
| 200 | +`context.read<T>()` allows a route to access an instance of type `T` which was provided via `middleware`. |
| 201 | +::: |
| 202 | + |
| 203 | +Be sure to save all the changes and hot reload should kick in β‘οΈ |
| 204 | + |
| 205 | +```bash |
| 206 | +[hotreload] - Application reloaded. |
| 207 | +``` |
| 208 | + |
| 209 | +Now if we visit [http://localhost:8080](http://localhost:8080) in the browser or via `cURL`: |
| 210 | + |
| 211 | +```bash |
| 212 | +curl --request GET \ |
| 213 | + --url http://localhost:8080 |
| 214 | +``` |
| 215 | + |
| 216 | +We should see our response: |
| 217 | + |
| 218 | +``` |
| 219 | +You have requested this route 1 time(s). |
| 220 | +``` |
| 221 | + |
| 222 | +Now if we reload the page or make another request, the count should update: |
| 223 | + |
| 224 | +``` |
| 225 | +You have requested this route 2 time(s). |
| 226 | +``` |
| 227 | + |
| 228 | +:::note |
| 229 | +If you restart the server, the count will be reset to 0 because it is only maintained in memory. |
| 230 | +::: |
| 231 | + |
| 232 | +π Congrats, you've created an `counter` application using Dart Frog. View the [full source code](https://github.com/VeryGoodOpenSource/dart_frog/tree/main/examples/counter). |
0 commit comments