Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unable to create Requests #8

Open
terinjokes opened this issue Jan 30, 2024 · 2 comments · May be fixed by #9
Open

unable to create Requests #8

terinjokes opened this issue Jan 30, 2024 · 2 comments · May be fixed by #9

Comments

@terinjokes
Copy link

I would like to test my implementation of AuthFunc in isolation, however the parameters to the function include a lightweight wrapper around http.Request where the request field is not exported nor a constructor function provided. This makes it much more complicated to test an AuthFunc as instead of being able to call it directly in test, I must wrap it in the middleware and implement another http.Handler to thread the Info back to my test function.

Can the request field be exported, or a constructor function for authn.Request be created?


I would like to be able to do something like:

func TestAuthFunc(t *testing.T) {
	req := httptest.NewRequest(http.MethodGet, "/", http.NoBody)
	req.Header.Set("Authorization", "Basic YWxhZGRpbjpvcGVuc2VzYW1l")

	info, err := MyAuthFunc(context.Background(), authn.Request{req})
	if err != nil {
		t.Fatalf("unexpected error from AuthFunc: %w", err)
	}

	if username, ok := info.(string); !ok {
		t.Fatalf("info was not string")
	} else if username != "aladdin" {
		t.Fatalf("unexpected username: %s", username)
	}
}

Right now I have to do something similar to this, which is significantly less clear what is under test.

func TestAuthFunc(t *testing.T) {
	mw := authn.NewMiddleware(MyAuthFunc)

	req := httptest.NewRequest(http.MethodGet, "/", http.NoBody)
	req.Header.Set("Authorization", "Basic YWxhZGRpbjpvcGVuc2VzYW1l")
	resp := httptest.NewRecorder()

	infoCh := make(chan string, 1)
	h := mw.Wrap(http.HandlerFunc(func(w *http.ResponseWriter, r http.Request) {
		info, ok := authn.GetInfo(r.Context()).(string)
		if !ok {
			close(infoCh)
			w.WriteHeader(http.StatusForbidden)
			return
		}

		infoCh <- info
	}))

	h.ServeHTTP(rec, resp)
	if rec.Code != 200 {
		t.Fatalf("unexpected status code: %s", rec.Code)
	}

	info := <-infoCh
	if info != "aladdin" {
		t.Fatalf("unexpected username: %s", username)
	}
}

I also believe this example test has a channel bug, but I'm going to stop working on the example now. The real one became significantly more complex as a result of not being able to directly test outputs to inputs.

@terinjokes
Copy link
Author

Alternatively: change AuthFunc to accepting http.Request instead of the wrapper. The only two functions on the wrapper that aren't passing directly through to http.Request are Protocol() and Procedure(), both could be top-level helper functions (either here or in another Connect library).

@emcfarlane emcfarlane linked a pull request Feb 2, 2024 that will close this issue
@emcfarlane
Copy link
Collaborator

Hey @terinjokes, thanks for using the library and raising the issue. I've raised a PR to export the constructor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants