package graphiql
import (
"context"
"fmt"
"net/http"
"strings"
)
var page = `
<html>
<head>
<title>GraphiQL</title>
<link href="https://unpkg.com/graphiql/graphiql.min.css" rel="stylesheet" />
</head>
<body style="margin: 0;">
<div id="graphiql" style="height: 100vh;"></div>
<script crossorigin src="https://unpkg.com/react/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom/umd/react-dom.production.min.js"></script>
<script crossorigin src="https://unpkg.com/graphiql/graphiql.min.js"></script>
<script>
const graphQLFetcher = graphQLParams =>
fetch('/api', {
method: 'post',
headers: { $headers 'Content-Type': 'application/json' },
body: JSON.stringify(graphQLParams),
theme: 'dark',
})
.then(response => response.json())
.catch(() => response.text());
ReactDOM.render(
React.createElement(GraphiQL, { fetcher: graphQLFetcher }),
document.getElementById('graphiql'),
);
</script>
</body>
</html>
`
type Login func(ctx context.Context, username, password string) (http.Header, error)
func GetHandler(login Login) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user, pass, ok := r.BasicAuth()
if !ok && login != nil {
w.Header().Set("WWW-Authenticate", `Basic realm="Please enter your username and password"`)
w.WriteHeader(401)
w.Write([]byte("Unauthorised.\n"))
return
}
var headerString strings.Builder
if login != nil {
header, err := login(r.Context(), user, pass)
if err != nil {
w.Header().Set("WWW-Authenticate", fmt.Sprintf(`Basic realm="%s"`, err))
w.WriteHeader(401)
w.Write([]byte("Unauthorized.\n"))
return
}
for key, values := range header {
for _, value := range values {
headerString.WriteString(fmt.Sprintf(`"%s":"%s",`, key, value))
}
}
}
w.Write([]byte(strings.ReplaceAll(page, "$headers", headerString.String())))
})
}