Reputation: 257
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?
Upvotes: 1
Views: 838
Reputation: 89
You shouldn't have to worry about Stringifying when using axios
. The library does it automatically by default. You should go for something like this:
import axios from 'axios';
const api = axios.create({
baseUrl: 'http://localhost:4000/api'
})
async signIn(username, password) {
try {
const resp = await api.post('/authenticate', data);
return resp.data
} catch(error) {
throw new Error(error?.message || "something went wrong")
}
}
you can then call it in a React component.
signIn(username, password)
.then(data => setState(data))
.catch(err => alert(error.message)
Upvotes: 0
Reputation: 257
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');
})
Upvotes: 1
Reputation: 2029
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.
Upvotes: 0
Reputation: 73
Try to use FormData.
const data = new FormData();
data.set('username', params.username);
data.set('password', params.password);
Upvotes: 0