What steps did you take and what happened:
Followed tutorial located here:
https://www.howtographql.com/graphql-go/0-introduction/
I followed the tutorial as written and ran the application.
The application started fine, and I went to the application endpoint but got 404 not found.
After some testing, I found the issue was in the Middleware (but I'm not sure where or why it isn't working)
If I use http.Handle the application works as expected in that I get the playground page but I'm not able to authenticate.
If I use router.Handle() I get 404 Not Found error when trying to go to the Playground page.
Working but unable to authenticate
// server.go
/*...*/
http.Handle("/", playground.Handler("GraphQL playground", "/query"))
http.Handle("/query", srv)
/*...*/
Gets 404 error when routing to the playground page
router := chi.NewRouter()
router.Use(auth.Middleware())
/*...*/
router.Handle("/", playground.Handler("GraphQL playground", "/query"))
router.Handle("/query", srv)
I even completed the tutorials coding, thinking that maybe it was an issue with where I was in the tutorial and that it would be resolved with later code. But this was not the case.
I then tested things. I am able to create a user and get a token as well as hit the 'login' endpoint using the http.Handle method but not authenticate with the "Authorization:" header. Because I cannot authenticate fully I cannot create or view links.
Below is the Middleware code. I cross-referenced it with the code in the tutorial and in this Repository.
package auth
import (
"192.168.1.215/gnosthi/graphQLTest/pkg/jwt"
"192.168.1.215/gnosthi/graphQLTest/pkg/users"
"context"
"net/http"
"strconv"
)
type contextKey struct {
name string
}
var userCtxKey = &contextKey{"user"}
func Middleware() func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
header := r.Header.Get("Authorization")
// Allow unauthorized users in
if header == "" {
next.ServeHTTP(w, r)
return
}
// validate jwt token
tokenStr := header
username, err := jwt.ParseToken(tokenStr)
if err != nil {
http.Error(w, "Invalid Token", http.StatusForbidden)
return
}
// create user and check if user exists in db
user := users.User{Username: username}
id, err := users.GetUserIdByUsername(username)
if err != nil {
next.ServeHTTP(w,r)
return
}
user.ID = strconv.Itoa(id)
// put into context
ctx := context.WithValue(r.Context(), userCtxKey, &user)
r = r.WithContext(ctx)
next.ServeHTTP(w,r)
})
}
}
func ForContext(ctx context.Context) *users.User {
raw, _ := ctx.Value(userCtxKey).(*users.User)
return raw
}
What did you expect to happen:
I expected to get the Playground query IDE page, be able to authenticate and create links
Anything else you would like to add:
Everything appears to be working except the Middleware
Environment:
-Go Version: go version go1.17 linux/amd64
- OS: 20.04.1-Ubuntu
- Kernel-Version: 5.8.0-63-generic
- go.mod: (Direct deps only)
module 192.168.1.215/gnosthi/graphQLTest
go 1.17
require (
github.com/99designs/gqlgen v0.14.0
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/go-chi/chi v1.5.4
github.com/go-sql-driver/mysql v1.6.0
github.com/golang-migrate/migrate v3.5.4+incompatible
github.com/vektah/gqlparser/v2 v2.2.0
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
)