mirror of
https://github.com/kardolus/chatgpt-cli.git
synced 2024-09-08 23:15:00 +03:00
Test http-error assembly
This commit is contained in:
@@ -13,6 +13,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const expectedToken = "valid-api-key"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
onceBuild sync.Once
|
onceBuild sync.Once
|
||||||
onceServe sync.Once
|
onceServe sync.Once
|
||||||
@@ -81,6 +83,11 @@ func getModels(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := checkBearerToken(r, expectedToken); err != nil {
|
||||||
|
http.Error(w, creatAuthError(), http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const modelFile = "models.json"
|
const modelFile = "models.json"
|
||||||
response, err := utils.FileToBytes(modelFile)
|
response, err := utils.FileToBytes(modelFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -96,6 +103,11 @@ func postCompletions(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := checkBearerToken(r, expectedToken); err != nil {
|
||||||
|
http.Error(w, creatAuthError(), http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const completionsFile = "completions.json"
|
const completionsFile = "completions.json"
|
||||||
response, err := utils.FileToBytes(completionsFile)
|
response, err := utils.FileToBytes(completionsFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -105,6 +117,37 @@ func postCompletions(w http.ResponseWriter, r *http.Request) {
|
|||||||
w.Write(response)
|
w.Write(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkBearerToken(r *http.Request, expectedToken string) error {
|
||||||
|
authHeader := r.Header.Get("Authorization")
|
||||||
|
if authHeader == "" {
|
||||||
|
return errors.New("missing Authorization header")
|
||||||
|
}
|
||||||
|
|
||||||
|
splitToken := strings.Split(authHeader, "Bearer ")
|
||||||
|
if len(splitToken) != 2 {
|
||||||
|
return errors.New("malformed Authorization header")
|
||||||
|
}
|
||||||
|
|
||||||
|
requestToken := splitToken[1]
|
||||||
|
if requestToken != expectedToken {
|
||||||
|
return errors.New("invalid token")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func creatAuthError() string {
|
||||||
|
const errorFile = "error.json"
|
||||||
|
|
||||||
|
response, err := utils.FileToBytes(errorFile)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("error reading %s: %s\n", errorFile, err.Error())
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(response)
|
||||||
|
}
|
||||||
|
|
||||||
func validateRequest(w http.ResponseWriter, r *http.Request, allowedMethod string) error {
|
func validateRequest(w http.ResponseWriter, r *http.Request, allowedMethod string) error {
|
||||||
if r.Method != allowedMethod {
|
if r.Method != allowedMethod {
|
||||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
|
|||||||
@@ -156,7 +156,6 @@ func testIntegration(t *testing.T, when spec.G, it spec.S) {
|
|||||||
const (
|
const (
|
||||||
exitSuccess = 0
|
exitSuccess = 0
|
||||||
exitFailure = 1
|
exitFailure = 1
|
||||||
apiKey = "some-key"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -181,7 +180,7 @@ func testIntegration(t *testing.T, when spec.G, it spec.S) {
|
|||||||
apiKeyEnvVar = configmanager.New(config.New()).WithEnvironment().APIKeyEnvVarName()
|
apiKeyEnvVar = configmanager.New(config.New()).WithEnvironment().APIKeyEnvVarName()
|
||||||
|
|
||||||
Expect(os.Setenv("HOME", homeDir)).To(Succeed())
|
Expect(os.Setenv("HOME", homeDir)).To(Succeed())
|
||||||
Expect(os.Setenv(apiKeyEnvVar, apiKey)).To(Succeed())
|
Expect(os.Setenv(apiKeyEnvVar, expectedToken)).To(Succeed())
|
||||||
})
|
})
|
||||||
|
|
||||||
it.After(func() {
|
it.After(func() {
|
||||||
@@ -314,6 +313,21 @@ func testIntegration(t *testing.T, when spec.G, it spec.S) {
|
|||||||
Expect(output).To(ContainSubstring(`I don't have personal opinions about bars, but here are some popular bars in Red Hook, Brooklyn:`))
|
Expect(output).To(ContainSubstring(`I don't have personal opinions about bars, but here are some popular bars in Red Hook, Brooklyn:`))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should assemble http errors as expected", func() {
|
||||||
|
Expect(os.Setenv(apiKeyEnvVar, "wrong-token")).To(Succeed())
|
||||||
|
|
||||||
|
command := exec.Command(binaryPath, "--query", "some-query")
|
||||||
|
session, err := gexec.Start(command, io.Discard, io.Discard)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
Eventually(session).Should(gexec.Exit(exitFailure))
|
||||||
|
|
||||||
|
output := string(session.Out.Contents())
|
||||||
|
|
||||||
|
// see error.json
|
||||||
|
Expect(output).To(Equal("http status 401: Incorrect API key provided\n"))
|
||||||
|
})
|
||||||
|
|
||||||
when("there is a hidden chatgpt-cli folder in the home dir", func() {
|
when("there is a hidden chatgpt-cli folder in the home dir", func() {
|
||||||
var filePath string
|
var filePath string
|
||||||
|
|
||||||
@@ -487,7 +501,7 @@ func testIntegration(t *testing.T, when spec.G, it spec.S) {
|
|||||||
|
|
||||||
// config.yaml should have the expected content
|
// config.yaml should have the expected content
|
||||||
content := string(contentBytes)
|
content := string(contentBytes)
|
||||||
Expect(content).NotTo(ContainSubstring(apiKey))
|
Expect(content).NotTo(ContainSubstring(expectedToken))
|
||||||
Expect(content).To(ContainSubstring(newModel))
|
Expect(content).To(ContainSubstring(newModel))
|
||||||
|
|
||||||
// --list-models shows the new model as default
|
// --list-models shows the new model as default
|
||||||
@@ -565,7 +579,7 @@ func testIntegration(t *testing.T, when spec.G, it spec.S) {
|
|||||||
|
|
||||||
// config.yaml should have the expected content
|
// config.yaml should have the expected content
|
||||||
content := string(contentBytes)
|
content := string(contentBytes)
|
||||||
Expect(content).NotTo(ContainSubstring(apiKey))
|
Expect(content).NotTo(ContainSubstring(expectedToken))
|
||||||
Expect(content).To(ContainSubstring(newMaxTokens))
|
Expect(content).To(ContainSubstring(newMaxTokens))
|
||||||
|
|
||||||
// --config displays the new max-tokens as well
|
// --config displays the new max-tokens as well
|
||||||
|
|||||||
8
resources/testdata/error.json
vendored
Normal file
8
resources/testdata/error.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"error": {
|
||||||
|
"message": "Incorrect API key provided",
|
||||||
|
"type": "invalid_request_error",
|
||||||
|
"param": null,
|
||||||
|
"code": "invalid_api_key"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user