Issues with post request in Flutter/Dart frontend with Go backend

1,225

In your code

    http.post(url,body:json.encode(body)).then((http.Response response){
      cookie = response.headers['session'];
    });
    debugPrint(cookie);

the line

debugPrint(cookie);

is executed before

cookie = response.headers['session'];

so it is expected that cookie is null when you print it. For some weird reason debugPrint(null) throws an exception about "slit on null"

Try instead

    http.post(url,body:json.encode(body)).then((http.Response response){
      cookie = response.headers['session'];
      debugPrint(cookie);   
    });
Share:
1,225
DanT29
Author by

DanT29

Updated on December 05, 2022

Comments

  • DanT29
    DanT29 6 months

    I am new to Flutter/Dart, Go and mobile development in general. I am currently coding a login authentication page in flutter that connects to a backend written in go. To check if everything worked I wanted to print out the cookie that my backend sends back in the console. Unfortunately I am getting errors not sure what to do.

    EDIT: I have been able to read the cookie, should I save the cookie in this format "session=UUID" or just the "UUID"? I want to send this cookie back in the header for future get requests. My Go code will check for the cookie name "session",but I'm not sure if sending it back in that format is correct.

    Flutter code (I read on another stackoverflow post to use 10.0.2.2 as localhost when using an android emulator):

    EDIT: After playing around with the code I was able to read the cookie in the header but it has the name as well not just the UUID.

    import 'package:flutter/material.dart';
    import 'package:http/http.dart' as http;
    import 'dart:convert';
    class Login extends StatefulWidget {
      @override
      State<StatefulWidget> createState(){
        return new LoginState();
      }
    }
    class LoginState extends State <Login> {
      final formKey = GlobalKey<FormState>();
      String _email, _password;
      String cookie;
      void loginApi(){
        var form = formKey.currentState;
        var url = "http://10.0.2.2:8080";
          if (form.validate()) {
            form.save();
            var body = { "Email":_email, "Pass":_password};
            http.post(url,body:json.encode(body)).then((response){
              print(response.headers['set-cookie']);
            });
          }
      }
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          appBar: new AppBar(
            title: new Text("Login"),
            backgroundColor: Colors.white,
          ),
          body: new Container(
            alignment: Alignment.center,
            child: Form(
                key: formKey,
                child: Column(
                  children: <Widget>[
                    TextFormField(
                      autocorrect: false,
                      decoration: InputDecoration(
                        labelText: "Email:",
                      ),
                      validator: (str) =>
                      !str.contains('@') ? "Not a Valid Email!" : null,
                      onSaved: (str) =>  _email = str,
                    ),
                    TextFormField(
                      autocorrect: false,
                      decoration: InputDecoration(
                        labelText: "Password:",
                      ),
                      validator: (str) =>
                      str.length <= 7 ? "Not a Valid Password!" : null,
                      onSaved: (str) => _password = str,
                      obscureText: false,
                    ),
                    RaisedButton(
                      child: Text("Submit"),
                      onPressed:loginApi,
                    ),
                  ],
                )
            ),
          ),
        );
      }
    }
    

    Golang code (EDIT: Inserted a missing curly bracket after the panic error and deleted the curly bracket at the end of the code):

    package main
    import (
        "encoding/json"
        "html/template"
        "net/http"
        uuid "github.com/satori/go.uuid"
        "golang.org/x/crypto/bcrypt"
    )
    type user struct {
        UserName string //Same as email
        Password []byte
    }
    type logindata struct {
        Email string
        Pass  string
    }
    var tpl *template.Template
    var dbUsers = map[string]user{}
    var dbSess = map[string]string{}
    func init() {
        bs, _ := bcrypt.GenerateFromPassword([]byte("password"), bcrypt.MinCost)
        dbUsers["[email protected]"] = user{"[email protected]", bs}
    }
    func main() {
        http.HandleFunc("/", login)
        http.Handle("/favicon.ico", http.NotFoundHandler()) //Don't have favicon
        http.ListenAndServe(":8080", nil)
    }
    func login(w http.ResponseWriter, req *http.Request) {
        var data logindata
        decoder := json.NewDecoder(req.Body)
        err_decode := decoder.Decode(&data)
        if err_decode != nil {
            panic(err_decode)
        }
        u, ok := dbUsers[data.Email]
        if !ok {
            http.Error(w, "Username and/or password do not match", http.StatusForbidden)
            return
        }
        err_compare := bcrypt.CompareHashAndPassword(u.Password, []byte(data.Pass))
        if err_compare != nil {
            http.Error(w, "Username and/or password do not match", http.StatusForbidden)
            return
        }
        // create session
        sID, _ := uuid.NewV4()
        c := &http.Cookie{
            Name:  "session",
            Value: sID.String(),
        }
        http.SetCookie(w, c)
        dbSess[c.Value] = data.Email
        return
    }
    

    Output from console for flutter code (after I put in username and password and click submit, username is "[email protected]" password is "password"):

    Performing hot reload...
    Reloaded 0 of 489 libraries in 544ms.
    I/flutter ( 3778): session=db3690d6-db6e-4658-8b5b-5f2d3f908a65
    

    I also went to localhost:8080 on my browser expecting to show a blank page but it displayed "page not working" and my terminal outputted the following error I guess because I was accessing it with a browser and I wasn't sending in JSON data, not sure:

    2018/05/24 23:29:38 http: panic serving [::1]:40010: EOF
    goroutine 6 [running]:
    net/http.(*conn).serve.func1(0xc82001a280)
        /usr/lib/go-1.6/src/net/http/server.go:1389 +0xc1
    panic(0x76c6c0, 0xc82000a160)
        /usr/lib/go-1.6/src/runtime/panic.go:443 +0x4e9
    main.login(0x7f96c9a848b8, 0xc82012c000, 0xc8201121c0)
        /home/daniel/Desktop/Workspace/Genesis/main.go:43 +0x176
    net/http.HandlerFunc.ServeHTTP(0x8a8688, 0x7f96c9a848b8, 0xc82012c000, 0xc8201121c0)
        /usr/lib/go-1.6/src/net/http/server.go:1618 +0x3a
    net/http.(*ServeMux).ServeHTTP(0xc820013020, 0x7f96c9a848b8, 0xc82012c000, 0xc8201121c0)
        /usr/lib/go-1.6/src/net/http/server.go:1910 +0x17d
    net/http.serverHandler.ServeHTTP(0xc82001a100, 0x7f96c9a848b8, 0xc82012c000, 0xc8201121c0)
        /usr/lib/go-1.6/src/net/http/server.go:2081 +0x19e
    net/http.(*conn).serve(0xc82001a280)
        /usr/lib/go-1.6/src/net/http/server.go:1472 +0xf2e
    created by net/http.(*Server).Serve
        /usr/lib/go-1.6/src/net/http/server.go:2137 +0x44e
    2018/05/24 23:29:38 http: panic serving [::1]:40012: EOF
    goroutine 18 [running]:
    net/http.(*conn).serve.func1(0xc82011c080)
        /usr/lib/go-1.6/src/net/http/server.go:1389 +0xc1
    panic(0x76c6c0, 0xc82000a160)
        /usr/lib/go-1.6/src/runtime/panic.go:443 +0x4e9
    main.login(0x7f96c9a848b8, 0xc8201161a0, 0xc820154000)
        /home/daniel/Desktop/Workspace/Genesis/main.go:43 +0x176
    net/http.HandlerFunc.ServeHTTP(0x8a8688, 0x7f96c9a848b8, 0xc8201161a0, 0xc820154000)
        /usr/lib/go-1.6/src/net/http/server.go:1618 +0x3a
    net/http.(*ServeMux).ServeHTTP(0xc820013020, 0x7f96c9a848b8, 0xc8201161a0, 0xc820154000)
        /usr/lib/go-1.6/src/net/http/server.go:1910 +0x17d
    net/http.serverHandler.ServeHTTP(0xc82001a100, 0x7f96c9a848b8, 0xc8201161a0, 0xc820154000)
        /usr/lib/go-1.6/src/net/http/server.go:2081 +0x19e
    net/http.(*conn).serve(0xc82011c080)
        /usr/lib/go-1.6/src/net/http/server.go:1472 +0xf2e
    created by net/http.(*Server).Serve
        /usr/lib/go-1.6/src/net/http/server.go:2137 +0x44e
    2018/05/24 23:29:43 http: panic serving [::1]:40016: EOF
    goroutine 7 [running]:
    net/http.(*conn).serve.func1(0xc82001a380)
        /usr/lib/go-1.6/src/net/http/server.go:1389 +0xc1
    panic(0x76c6c0, 0xc82000a160)
        /usr/lib/go-1.6/src/runtime/panic.go:443 +0x4e9
    main.login(0x7f96c9a848b8, 0xc82012c1a0, 0xc8201122a0)
        /home/daniel/Desktop/Workspace/Genesis/main.go:43 +0x176
    net/http.HandlerFunc.ServeHTTP(0x8a8688, 0x7f96c9a848b8, 0xc82012c1a0, 0xc8201122a0)
        /usr/lib/go-1.6/src/net/http/server.go:1618 +0x3a
    net/http.(*ServeMux).ServeHTTP(0xc820013020, 0x7f96c9a848b8, 0xc82012c1a0, 0xc8201122a0)
        /usr/lib/go-1.6/src/net/http/server.go:1910 +0x17d
    net/http.serverHandler.ServeHTTP(0xc82001a100, 0x7f96c9a848b8, 0xc82012c1a0, 0xc8201122a0)
        /usr/lib/go-1.6/src/net/http/server.go:2081 +0x19e
    net/http.(*conn).serve(0xc82001a380)
        /usr/lib/go-1.6/src/net/http/server.go:1472 +0xf2e
    created by net/http.(*Server).Serve
        /usr/lib/go-1.6/src/net/http/server.go:2137 +0x44e
    
    • Günter Zöchbauer
      Günter Zöchbauer almost 5 years
      What were you tapping on to get this error?
    • DanT29
      DanT29 almost 5 years
      Yes I tapped on the submit button
    • Günter Zöchbauer
      Günter Zöchbauer almost 5 years
      What line is Login.dart:32:19?
    • DanT29
      DanT29 almost 5 years
      debugPrint(cookie); part of the loginApi function I made for the onPressed field for the raised button
    • Günter Zöchbauer
      Günter Zöchbauer almost 5 years
      Can you try print(cookie) instead of debugPrint(cookie) or perhaps print(response.headers);? I get the impression there is something fishy going on with the headers.
    • DanT29
      DanT29 almost 5 years
      it is showing this as the error: I/flutter ( 5490): null for print(cookie), I will try the other one now
    • Günter Zöchbauer
      Günter Zöchbauer almost 5 years
      That doesn't look like an error.
    • DanT29
      DanT29 almost 5 years
      In my loginApi function I changed my debugPrint(cookie) to print(cookie), the output of the console just showed me this after putting in the username and password: Performing full restart... Restarted app in 2,049ms. W/IInputConnectionWrapper( 5490): getCursorCapsMode on inactive InputConnection I/flutter ( 5490): null
    • Günter Zöchbauer
      Günter Zöchbauer almost 5 years
      That doesn't look like an error, just that response.headers['session'] returns null.
    • DanT29
      DanT29 almost 5 years
      I can't seem to code print(response.headers) it is underlining response saying "undefined name response"
    • Anzel
      Anzel almost 5 years
      @DanT29, under your go code, are you sure you have put the closing } parentheses at the right place? You didn't close it after the panic(error) line seems very odd to me. The remaining code is unreachable
    • DanT29
      DanT29 almost 5 years
      @Anzel good call! my post requests are working on postman when i use raw JSON now. I'm still getting errors but will update my question details.
  • DanT29
    DanT29 almost 5 years
    I still seem to be getting the same error, could this be an issue on my back-end? I think I'm retrieving the headers correctly.
  • Günter Zöchbauer
    Günter Zöchbauer almost 5 years
    Same error as which one? "The method 'split' was called on null."? Then you don't get headers back. Perhaps you should check the responseCode
  • DanT29
    DanT29 almost 5 years
    Yes it showed me this : E/flutter ( 5490): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception: E/flutter ( 5490): NoSuchMethodError: The method 'split' was called on null. E/flutter ( 5490): Receiver: null E/flutter ( 5490): Tried calling: split("\n") ...followed by a bunch of other errors. I will try to look over my backend code...I'm guessing from what you see my post request is correct?