diff --git a/netbox/client.go b/netbox/client.go index f1274d0d540298fa51da335645297d5089a548b2..4269b8d65c39958439d473ccc8240f3c8e60b1c7 100644 --- a/netbox/client.go +++ b/netbox/client.go @@ -38,16 +38,20 @@ type Client struct { // Tenancy provides access to methods in NetBox's Tenancy API. Tenancy *TenancyService + token string u *url.URL client *http.Client } // NewClient returns a new instance of a NetBox client. addr specifies the address -// of the NetBox server, and client specifies an optional HTTP client to use -// for requests. +// of the NetBox server, token specifies the api key to use, +// and client specifies an optional HTTP client to use for requests. +// +// If token is the empty string, no Authentication will be included in requests, +// providing anonymous read-only access depending on your NetBox config. // // If client is nil, a default HTTP client will be used. -func NewClient(addr string, client *http.Client) (*Client, error) { +func NewClient(addr string, token string, client *http.Client) (*Client, error) { if client == nil { client = &http.Client{} } @@ -65,6 +69,7 @@ func NewClient(addr string, client *http.Client) (*Client, error) { } c := &Client{ + token: token, u: u, client: client, } @@ -116,18 +121,23 @@ func (c *Client) NewDataRequest(method string, endpoint string, options Valuer, u := c.u.ResolveReference(rel) - // If no valuer specified, create a request with no query parameters - if options == nil { - return http.NewRequest(method, u.String(), body) + // If a valuer is specified, add the values as the query string + if options != nil { + values, err := options.Values() + if err != nil { + return nil, err + } + u.RawQuery = values.Encode() } - values, err := options.Values() + req, err := http.NewRequest(method, u.String(), body) if err != nil { return nil, err } - u.RawQuery = values.Encode() - - return http.NewRequest(method, u.String(), body) + if c.token != "" { + req.Header.Set("Authorization", fmt.Sprintf("Token %s", c.token)) + } + return req, nil } // NewJSONRequest creates a HTTP request using the input HTTP method, URL diff --git a/netbox/client_test.go b/netbox/client_test.go index 4170a338e1a19b4b25ca7353360e2c6cc3ea42d0..01c150276213f35ccc7025aa9a3d278daccc78f7 100644 --- a/netbox/client_test.go +++ b/netbox/client_test.go @@ -152,7 +152,7 @@ func TestClientQueryParameters(t *testing.T) { Bar: wantBar, }) if err != nil { - t.Fatal("expected an error, but no error returned") + t.Fatalf("unexpected error: %v", err) } q := req.URL.Query() @@ -183,7 +183,7 @@ func TestClientPrependBaseURLPath(t *testing.T) { req, err := c.NewRequest(http.MethodGet, "/api/ipam/vlans", nil) if err != nil { - t.Fatal("expected an error, but no error returned") + t.Fatalf("unexpected error: %v", err) } if want, got := "/netbox/api/ipam/vlans", req.URL.Path; want != got { @@ -192,6 +192,23 @@ func TestClientPrependBaseURLPath(t *testing.T) { } } +func TestAuthenticatingClientAddsHeader(t *testing.T) { + c, err := NewClient("localhost", "auth-token", nil) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + req, err := c.NewRequest(http.MethodGet, "/api/ipam/vlans", nil) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if want, got := "Token auth-token", req.Header.Get("Authorization"); want != got { + t.Fatalf("unexpected Authorization header:\n- want: %q\n- got: %q", + want, got) + } +} + type testValuer struct { Foo string Bar int @@ -214,7 +231,7 @@ func (q testValuer) Values() (url.Values, error) { func testClient(t *testing.T, fn func(w http.ResponseWriter, r *http.Request)) (*Client, func()) { s := httptest.NewServer(http.HandlerFunc(fn)) - c, err := NewClient(s.URL, nil) + c, err := NewClient(s.URL, "", nil) if err != nil { t.Fatalf("error creating Client: %v", err) } diff --git a/netbox/netbox_test.go b/netbox/netbox_test.go index f7e8d5dd6b8aaa33631d2a2af8bd87c152727a01..aa4834a8926c39fca175f73b06d5a5c54f7fda96 100644 --- a/netbox/netbox_test.go +++ b/netbox/netbox_test.go @@ -72,7 +72,7 @@ func ExampleNewClient() { defer done() // Creates a client configured to use the test server - c, err := NewClient(addr, nil) + c, err := NewClient(addr, "", nil) if err != nil { panic(fmt.Sprintf("failed to create netbox.Client: %v", err)) }