1
votes

I've implemented an API that authenticates users to react clients with Go. The handler for the authentication route is as follows,

func (app *application) authenticate(w http.ResponseWriter, r *http.Request) {
    err := r.ParseForm()
    if err != nil {
        app.clientError(w, http.StatusBadRequest)
        return
    }

    username := r.PostForm.Get("username")
    password := r.PostForm.Get("password")

    fmt.Println(r.PostForm)

    u, err := app.user.Get(username, password)
    if err != nil {
        if errors.Is(err, models.ErrNoRecord) || errors.Is(err, bcrypt.ErrMismatchedHashAndPassword) {
            app.notFound(w)
        } else {
            app.serverError(w, err)
        }
        return
    }

    token := jwt.New(jwt.SigningMethodHS256)
    claims := token.Claims.(jwt.MapClaims)

    claims["username"] = u.Username
    claims["name"] = u.Name
    claims["exp"] = time.Now().Add(time.Minute * 30).Unix()

    ts, err := token.SignedString(app.secret)
    if err != nil {
        app.serverError(w, err)
        return
    }

    user := models.UserResponse{u.ID, u.Username, u.Name, "Admin", ts}
    js, err := json.Marshal(user)
    if err != nil {
        app.serverError(w, err)
        return
    }

    w.Header().Set("Content-Type", "application/json")
    w.Write(js)
}

I'm trying to send a post request to the API from the react app using Axios as follows,

const data = JSON.stringify({
    username: params.username,
    password: params.password,
});

api.post('/authenticate', data, {
    headers: {'Content-Type': 'application/json' }
}).then(response => {
    console.log(response);
    resolve({ ok: true, json: () => response.data });
}).catch(err => {
    console.log(err);
    reject('Username or password is incorrect');
})

But the request returns a 404 error. Go console shows that the post data is empty map[] I've tried changing the Content-Type header in the Axios request to multipart/form-data and application/x-www-form-urlencoded with no luck. When the request is made using CURL,

curl -d "username=user&password=password" -X POST http://localhost:4000/authenticate

The request returns the proper response. Postman is also working fine. What could be the possible issue that the request body is not parsed in Go when only the request is made from Axios?

3

3 Answers

1
votes

Working solution is using the package qs to stringify data.

import qs from 'qs';

const data = {
    username: params.username,
    password: params.password,
};

api.post('/authenticate', qs.stringify(data)
).then(response => {
    console.log(response);
    resolve({ ok: true, json: () => response.data });
}).catch(err => {
    console.log(err);
    reject('Username or password is incorrect');
})
0
votes

Try to use FormData.

const data = new FormData();
data.set('username', params.username);
data.set('password', params.password);
0
votes

In your client request, you are sending a JSON body; however on the server you're expecting url-encoded values.

You should either change your client to send the correct data, e.g. like this, or you need to accept the JSON body by parsing it with the encoding/json package on the server side.