Developer. School /flutter-mob…

The original author: developer. School/author/Paul…

Published: 27 February 2020-9 minutes to read

Handle GET, POST, PUT, and DELETE requests.

This is the second in a seven-part series.

  1. An introduction to
  2. HTTP requests (you are here)
  3. The database
  4. test
  5. certification
  6. Production server
  7. Flutter client application

introduce

In the previous lesson, you set up the Dart, Aqueduct, and IDE. You also make a simple GET request from the browser to the running Aqueduct server and send the response back to the browser.

In this lesson, you will learn a few more ways to make HTTP requests. In addition to GET requests, you also make POST, PUT, and DELETE requests. On the server side, you write code for Aqueduct to handle these requests.

Method of making an HTTP request

If you prefer watching videos to reading texts, here’s the next video.

www.youtube.com/watch?v=QGh…

There are many different ways you can make HTTP requests. In addition to browsers, you can also use a program called Postman, a command-line utility called curl, a browser tool called Swagger, the Aqueduct testing framework, and even a Flutter application.

We’ll look at each briefly, but first open the Aqueduct project you created in the previous lesson. In the lib/channel.dart file, replace the entryPoint() method with the following code.

@override
Controller get entryPoint {
  final router = Router();

  router.route("/example").linkFunction(
    (request) async {
      return Response.ok('Hello world').. contentType = ContentType.text; });return router;
}
Copy the code

Note:

  • I modified the response to return it as plain text instead of JSONHello world.
  • The route path is still/example.

Now, in the root directory of the Dart project, run the following command on your terminal to start the server.

aqueduct serve
Copy the code

The browser

Open any browser and navigate to the following address.

http://localhost:8888/
Copy the code

Aqueduct should return a 404 Not Found response because you did Not process/root paths. Now enter the route you defined.

http://localhost:8888/example
Copy the code

You should get a Hello World response.

Success in the browser.

Postman

The browser’s address bar is only good for basic GET requests, but you’ll need to make other requests as well. Postman is a handy program. This will be your main tool for making HTTP requests throughout this series.

Download Postman here. If you continue clicking, you don’t need to register anything. Once you’ve downloaded it, install it. Type the following in the Postman address bar and click Send.

localhost:8888/example
Copy the code

You should get a response from Aqueduct that says Hello World in the body.

Postman 200 replied OK

Notice that the status is 200 OK. All is well with the server.

Using Postman succeeded.

curl

Curl is a powerful command-line tool. Sometimes you don’t have a graphical user interface to make requests (such as when you’re on a server), so having a tool like this is very useful.

Open a terminal and run the following command to see if you have Curl installed.

curl --version
Copy the code

If you don’t have one, feel free to skip this section. We don’t use it that much. But if you want to install it, the official website is here.

To make a GET request, run the following command.

curl -X GET "http://localhost:8888/example"
Copy the code

You should get a Hello World response.

The screenshot I made was a lowercase H, so I didn’t bother to fix it.

Use curl to succeed.

Swagger

Swagger, now called OpenAPI, is a way for you to create client applications in your browser to test server applications. I haven’t actually found it useful so far, so I’m not going to go into the details of how to use it right now.

But if you’re interested, here’s the official page, and here’s Aqueduct’s documentation about it.

Aqueduct testing framework

The Aqueduct testing framework is a great way to make HTTP requests. You’ll do more in The Part 4 test, but for now let’s do a brief preview. In your project, open the file test/example.dart.

Right-click on the code to display the context menu. Select “Run”, or press Control Shift R.

The test fails because it expects the subject to be{"key": "value"}. But we’ve changed the bodyHello world. Tests need to be updated.

Replace the entire file with the following code.

import 'harness/app.dart';

Future main() async {
  finalharness = Harness().. install(); test("GET /example returns 200 {'key': 'value'}", () async {
    expectResponse(
      await harness.agent.get("/example"),
      200,
      body: "Hello world",); }); }Copy the code

Run the test again and it should pass.

The request was made successfully with the Aqueduct test framework.

Flutter application

I say Flutter app, but it could be an Android or iOS app. You can use any of these options to make HTTP requests.

We will make a Flutter application in Part 7, but if you want to make one first and test the server, you can do so.

The way you make HTTP requests in Flutter is by using HTTP packets. You can read more about it in the article below.

How to make HTTP requests in Flutter

Processing GET requests

The server is already handling GET requests to the /example route, but we will now extend this functionality.

www.youtube.com/watch?v=sqh…

In this series, you will be building a dictionary application, so you will define a route with a path of /words instead of /example.

In lib/channel.dart, replace the entryPoint() method with the following.

@override
Controller get entryPoint {
  final router = Router();

  router.route("/words").link(() => WordsController());

  return router;
}
Copy the code

Note the following points:

  • The path is a/words.
  • We use thelinkFunctionInstead oflink. This will all go to/wordsIs forwarded to the controller class. This will keep our router code clean.
  • You haven’t built yetWordsController()Class. You’ll do it next.

Create a controller

Create a subfolder named Controller in the lib folder.

Then create a file called word_controller.dart in lib/controller. Paste the following code.

import 'package:dart_server/dart_server.dart';

class WordsController extends ResourceController {

  final _words = [
    {'word': 'horse'},
    {'word': 'cow'},
    {'word': 'camel'},
    {'word': 'sheep'},
    {'word': 'goat'},];@Operation.get()
  Future<Response> getAllWords() async {
    returnResponse.ok(_words); }}Copy the code

Note:

  • This class is extendedResourceController, which is an Aqueduct class that handles many of the details of the request.
  • We haven’t built the database yet, so for the data, we’re just using an array of map objects.
  • @Operation.get()Is an annotation that tells Aqueduct that this method will handle GET requests. It returns aResponse.ok()This is a200 OKAnd we’re going to pass in the list of data. Aqueduct automatically converts this to a JSON string and places it in the body of the response.

Import the class you just made in lib/channel.dart.

Test your new controller

Stop the server with Control+C. Then restart the server.

aqueduct serve
Copy the code

Open Postman and make the request as we did before, but this time change the address to the following.

localhost:8888/words
Copy the code

When you click Send, you should see the JSON list in the body of the response.

Getting a single project

The server now returns the entire list of data. What if you only want to get one data item? A common approach is to add an ID to the path, such as this.

localhost:8888/words/1
Copy the code

This is a request to the server for the word id=1, but we haven’t processed it yet.

Open the lib/channel. The dart. Replace the entryPoint() method with the following.

@override
Controller get entryPoint {
  final router = Router();

  router.route("/words/[:id]").link(() => WordsController());

  return router;
}
Copy the code

Note:

  • Now,/wordsAttached to the path/[:id].
  • :saididPhi is a variable. You can call this variable at will.
  • The square brackets[]Indicates that this variable is optional.

Back to the lib/controller/words_controller. Dart. You will create a new method to handle individual requests. Paste the following method under the getAllWords() method.

@Operation.get('id')
Future<Response> getWordByID(@Bind.path('id') int id) async {
  return Response.ok(_words[id]);
}
Copy the code

Note:

  • In the annotations'id'Is used to distinguish this method from our previous plain@Operation.get()The method. Here,'id'The same variable names we used in channel.dart.
  • @BindPart means Aqueduct will accept the path in'id'Variable and try to convert it to oneint. If the conversion is unsuccessful, Aqueduct will return404 Not Found. But if it succeeds, then you can return an item from the data list using an integer as the index.

Restart the server.

aqueduct serve
Copy the code

Send a GET request in Postman with the following address.

localhost:8888/words/1
Copy the code

The response you should get is that there is only one item in the body.

The item in index 1 is returned. Success! You can trick GET requests by sending different index values. If you choose a large value, you will cause a server error and Aqueduct will give you a response of 500.

Handle POST, PUT, and DELETE requests.

In this section, we simply create methods to handle POST, PUT, and DELETE requests. Because these requests are to modify data on the server, we won’t finish until part 3 when we add the database.

www.youtube.com/watch?v=T-X…

Add the following methods to the WordsController class in lib/controller/words_controller.dart.

@Operation.post()
Future<Response> addWord() async {
  return Response.ok(null);
}

@Operation.put('id')
Future<Response> updateWord(@Bind.path('id') int id) async {
  return Response.ok(null);
}

@Operation.delete('id')
Future<Response> deleteWord(@Bind.path('id') int id) async {
  return Response.ok(null);
}
Copy the code

Note:

  • OperationAnnotations identify the type of request the method handles. POST requests are used to create server resources. A PUT request is used to update an existing resource. DELETE has a nice name, so it does need explaining.
  • Because PUT and DELETE work on existing data, we bind an ID to an integer to determine which data item to update or DELETE.
  • Currently, everything returns a default200 OKThe response. We’ll change that later.

Restart the server with Aqueduct Serve.

Test it out in Postman

Open the Postman. Select POST instead of GET from the drop-down menu.

Write the following in the requested URL, then presssend.

localhost:8888/words
Copy the code

You should get a 200 OK response.

Repeat this process for PUT and DELETE using urls with ids.

localhost:8888/words/1
Copy the code

I should still get 200 OK.

The complete code

If you get lost, here’s the full code for what we did today.

lib/channel.dart

import 'package:dart_server/controller/words_controller.dart';

import 'dart_server.dart';

class DartServerChannel extends ApplicationChannel {
  @override
  Future prepare() async {
    logger.onRecord.listen(
        (rec) => print("$rec ${rec.error ?? ""} ${rec.stackTrace ?? ""}"));
  }

  @override
  Controller get entryPoint {
    final router = Router();

    router.route("/words/[:id]").link(() => WordsController());

    returnrouter; }}Copy the code

lib/controller/words_controller.dart

import 'package:dart_server/dart_server.dart';

class WordsController extends ResourceController {

  final _words = [
    {'word': 'horse'},
    {'word': 'cow'},
    {'word': 'camel'},
    {'word': 'sheep'},
    {'word': 'goat'},];@Operation.get()
  Future<Response> getAllWords() async {
    return Response.ok(_words);
  }

  @Operation.get('id')
  Future<Response> getWordByID(@Bind.path('id') int id) async {
    return Response.ok(_words[id]);
  }

  @Operation.post()
  Future<Response> addWord() async {
    return Response.ok(null);
  }

  @Operation.put('id')
  Future<Response> updateWord(@Bind.path('id') int id) async {
    return Response.ok(null);
  }

  @Operation.delete('id')
  Future<Response> deleteWord(@Bind.path('id') int id) async {
    return Response.ok(null); }}Copy the code

conclusion

You now know the basics of how to handle any type of request. Of course there’s more to fill out later, but as you can see, it’s not that difficult. In this lesson, the path is /words. You can easily handle other paths by defining some other paths and assigning a new controller to handle it.

In part 3, you will learn how to connect a PostgreSQL database to an Aqueduct server.

I’ll add a link here when I’m done with part 3. Until then, keep watching the series of videos or follow the Aqueduct documentation.

www.twitter.com/FlutterComm


Translated through (www.DeepL.com/Translator) (free version)