84 lines
1.9 KiB
Go
84 lines
1.9 KiB
Go
package reddit
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"net/http"
|
|
)
|
|
|
|
// tokenURL is the url of reddit's oauth2 authorization service.
|
|
const tokenURL = "https://www.reddit.com/api/v1/access_token"
|
|
|
|
// clientConfig holds all the information needed to define Client behavior, such
|
|
// as who the client will identify as externally and where to authorize.
|
|
type clientConfig struct {
|
|
// Agent is the user agent set in all requests made by the Client.
|
|
agent string
|
|
|
|
// If all fields in App are set, this client will attempt to identify as
|
|
// a registered Reddit app using the credentials.
|
|
app App
|
|
|
|
// Custom http client, if nil default should be used
|
|
client *http.Client
|
|
}
|
|
|
|
// client executes http Requests and invisibly handles OAuth2 authorization.
|
|
type client interface {
|
|
Do(*http.Request) ([]byte, error)
|
|
}
|
|
|
|
type baseClient struct {
|
|
cli *http.Client
|
|
}
|
|
|
|
func (b *baseClient) Do(req *http.Request) ([]byte, error) {
|
|
resp, err := b.cli.Do(req)
|
|
if resp != nil && resp.Body != nil {
|
|
defer resp.Body.Close()
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
switch resp.StatusCode {
|
|
case http.StatusOK:
|
|
case http.StatusForbidden:
|
|
return nil, PermissionDeniedErr
|
|
case http.StatusServiceUnavailable:
|
|
return nil, BusyErr
|
|
case http.StatusTooManyRequests:
|
|
return nil, RateLimitErr
|
|
case http.StatusBadGateway:
|
|
return nil, GatewayErr
|
|
case http.StatusGatewayTimeout:
|
|
return nil, GatewayTimeoutErr
|
|
default:
|
|
return nil, fmt.Errorf("bad response code: %d", resp.StatusCode)
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
if _, err := buf.ReadFrom(resp.Body); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
// newClient returns a new client using the given user to make requests.
|
|
func newClient(c clientConfig) (client, error) {
|
|
if c.app.tokenURL == "" {
|
|
c.app.tokenURL = tokenURL
|
|
}
|
|
|
|
if c.app.unauthenticated() {
|
|
return &baseClient{clientWithAgent(c.agent)}, nil
|
|
}
|
|
|
|
if err := c.app.validateAuth(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return newAppClient(c)
|
|
}
|