Skip to content
Snippets Groups Projects
Commit 8bc2717e authored by Matt Layher's avatar Matt Layher Committed by GitHub
Browse files

Merge pull request #19 from davcamer/authentication-header

Allow user to specify their API token
parents 2b01b034 d6c53a94
No related branches found
No related tags found
No related merge requests found
...@@ -38,16 +38,20 @@ type Client struct { ...@@ -38,16 +38,20 @@ type Client struct {
// Tenancy provides access to methods in NetBox's Tenancy API. // Tenancy provides access to methods in NetBox's Tenancy API.
Tenancy *TenancyService Tenancy *TenancyService
token string
u *url.URL u *url.URL
client *http.Client client *http.Client
} }
// NewClient returns a new instance of a NetBox client. addr specifies the address // 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 // of the NetBox server, token specifies the api key to use,
// for requests. // 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. // 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 { if client == nil {
client = &http.Client{} client = &http.Client{}
} }
...@@ -65,6 +69,7 @@ func NewClient(addr string, client *http.Client) (*Client, error) { ...@@ -65,6 +69,7 @@ func NewClient(addr string, client *http.Client) (*Client, error) {
} }
c := &Client{ c := &Client{
token: token,
u: u, u: u,
client: client, client: client,
} }
...@@ -116,18 +121,23 @@ func (c *Client) NewDataRequest(method string, endpoint string, options Valuer, ...@@ -116,18 +121,23 @@ func (c *Client) NewDataRequest(method string, endpoint string, options Valuer,
u := c.u.ResolveReference(rel) u := c.u.ResolveReference(rel)
// If no valuer specified, create a request with no query parameters // If a valuer is specified, add the values as the query string
if options == nil { if options != nil {
return http.NewRequest(method, u.String(), body) 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 { if err != nil {
return nil, err return nil, err
} }
u.RawQuery = values.Encode() if c.token != "" {
req.Header.Set("Authorization", fmt.Sprintf("Token %s", c.token))
return http.NewRequest(method, u.String(), body) }
return req, nil
} }
// NewJSONRequest creates a HTTP request using the input HTTP method, URL // NewJSONRequest creates a HTTP request using the input HTTP method, URL
......
...@@ -152,7 +152,7 @@ func TestClientQueryParameters(t *testing.T) { ...@@ -152,7 +152,7 @@ func TestClientQueryParameters(t *testing.T) {
Bar: wantBar, Bar: wantBar,
}) })
if err != nil { if err != nil {
t.Fatal("expected an error, but no error returned") t.Fatalf("unexpected error: %v", err)
} }
q := req.URL.Query() q := req.URL.Query()
...@@ -183,7 +183,7 @@ func TestClientPrependBaseURLPath(t *testing.T) { ...@@ -183,7 +183,7 @@ func TestClientPrependBaseURLPath(t *testing.T) {
req, err := c.NewRequest(http.MethodGet, "/api/ipam/vlans", nil) req, err := c.NewRequest(http.MethodGet, "/api/ipam/vlans", nil)
if err != 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 { if want, got := "/netbox/api/ipam/vlans", req.URL.Path; want != got {
...@@ -192,6 +192,23 @@ func TestClientPrependBaseURLPath(t *testing.T) { ...@@ -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 { type testValuer struct {
Foo string Foo string
Bar int Bar int
...@@ -214,7 +231,7 @@ func (q testValuer) Values() (url.Values, error) { ...@@ -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()) { func testClient(t *testing.T, fn func(w http.ResponseWriter, r *http.Request)) (*Client, func()) {
s := httptest.NewServer(http.HandlerFunc(fn)) s := httptest.NewServer(http.HandlerFunc(fn))
c, err := NewClient(s.URL, nil) c, err := NewClient(s.URL, "", nil)
if err != nil { if err != nil {
t.Fatalf("error creating Client: %v", err) t.Fatalf("error creating Client: %v", err)
} }
......
...@@ -72,7 +72,7 @@ func ExampleNewClient() { ...@@ -72,7 +72,7 @@ func ExampleNewClient() {
defer done() defer done()
// Creates a client configured to use the test server // Creates a client configured to use the test server
c, err := NewClient(addr, nil) c, err := NewClient(addr, "", nil)
if err != nil { if err != nil {
panic(fmt.Sprintf("failed to create netbox.Client: %v", err)) panic(fmt.Sprintf("failed to create netbox.Client: %v", err))
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment