Skip to content

Commit

Permalink
feat: Defer service URL validation
Browse files Browse the repository at this point in the history
Fixes arf/planning-sdk-squad#1011

Why:
In order to support parameterized URLs, we need to defer the validation of
the service URL value (i.e. myservice.Service.Options.URL) to the point at
which it is first needed, instead of when the BaseService struct is
constructed.

What:
This PR contains changes to support the above, plus the following:
1) Added comments here and there to some public structs and methods.
2) Made certain elements within BaseService private since they're not needed
outside BaseService.
3) Removed the Version field from the ServiceOptions struct.  Instead, the
Go generator will be changed to define Version as a field of the generated
service struct (e.g. AssistantV1) only when the service is detected to
use a "version param".  The Go core has no use for the Version field as it
is only ever referenced by the generated service code, so better to move
the definition of the field there as well.  Plus, we only generate the
Version-related code if we find that the API definition defines a
"version param".
  • Loading branch information
padamstx committed Sep 8, 2019
1 parent 91690a8 commit 6f51c35
Show file tree
Hide file tree
Showing 9 changed files with 245 additions and 133 deletions.
63 changes: 45 additions & 18 deletions core/base_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,44 @@ import (
"time"
)

// common constants for core
const (
USER_AGENT = "User-Agent"
SDK_NAME = "ibm-go-sdk-core"
UNKNOWN_ERROR = "Unknown Error"
header_name_USER_AGENT = "User-Agent"
sdk_name = "ibm-go-sdk-core"
)

// ServiceOptions Service options
// ServiceOptions : This struct contains the options supported by the BaseService methods.
type ServiceOptions struct {
Version string
URL string
// This is the base URL associated with the service instance.
// This value will be combined with the path for each operation to form the request URL.
URL string

// This field holds the authenticator for the service instance.
// The authenticator will "authenticate" each outbound request by adding additional
// information to the request, typically in the form of the "Authorization" http header.
Authenticator Authenticator
}

// BaseService Base Service
// BaseService : This struct defines a common "service" object that is used by each generated service
// to manage requests and responses, perform authentication, etc.
type BaseService struct {
Options *ServiceOptions

// The options related to the base service.
Options *ServiceOptions

// A set of "default" http headers to be included with each outbound request.
// This can be set by the SDK user.
DefaultHeaders http.Header
Client *http.Client
UserAgent string

// The HTTP Client used to send requests and receive responses.
Client *http.Client

// The value to be used for the "User-Agent" HTTP header that is added to each outbound request.
// If this value is not set, then a default value will be used for the header.
UserAgent string
}

// NewBaseService Instantiate a Base Service
// NewBaseService : This function will construct a new instance of the BaseService struct, while
// performing validation on input parameters and service options.
func NewBaseService(options *ServiceOptions, serviceName, displayName string) (*BaseService, error) {
if HasBadFirstOrLastChar(options.URL) {
return nil, fmt.Errorf(ERRORMSG_PROP_INVALID, "URL")
Expand All @@ -71,7 +86,7 @@ func NewBaseService(options *ServiceOptions, serviceName, displayName string) (*
}

// Set a default value for the User-Agent http header.
service.SetUserAgent(service.BuildUserAgent())
service.SetUserAgent(service.buildUserAgent())

// Try to load service properties from external config.
serviceProps, err := getServiceProperties(serviceName)
Expand Down Expand Up @@ -110,7 +125,14 @@ func NewBaseService(options *ServiceOptions, serviceName, displayName string) (*
}

// SetURL sets the service URL
//
// Deprecated: use SetServiceURL instead.
func (service *BaseService) SetURL(url string) error {
return service.SetServiceURL(url)
}

// SetServiceURL sets the service URL
func (service *BaseService) SetServiceURL(url string) error {
if HasBadFirstOrLastChar(url) {
return fmt.Errorf(ERRORMSG_PROP_INVALID, "URL")
}
Expand All @@ -119,6 +141,11 @@ func (service *BaseService) SetURL(url string) error {
return nil
}

// GetServiceURL returns the service URL
func (service *BaseService) GetServiceURL() string {
return service.Options.URL
}

// SetDefaultHeaders sets HTTP headers to be sent in every request.
func (service *BaseService) SetDefaultHeaders(headers http.Header) {
service.DefaultHeaders = headers
Expand All @@ -138,14 +165,14 @@ func (service *BaseService) DisableSSLVerification() {
}

// BuildUserAgent : Builds the user agent string
func (service *BaseService) BuildUserAgent() string {
return fmt.Sprintf("%s-%s %s", SDK_NAME, __VERSION__, SystemInfo())
func (service *BaseService) buildUserAgent() string {
return fmt.Sprintf("%s-%s %s", sdk_name, __VERSION__, SystemInfo())
}

// SetUserAgent : Sets the user agent value
func (service *BaseService) SetUserAgent(userAgentString string) {
if userAgentString == "" {
service.UserAgent = service.BuildUserAgent()
service.UserAgent = service.buildUserAgent()
}
service.UserAgent = userAgentString
}
Expand All @@ -160,9 +187,9 @@ func (service *BaseService) Request(req *http.Request, result interface{}) (deta
}

// Add the default User-Agent header if not already present.
userAgent := req.Header.Get(USER_AGENT)
userAgent := req.Header.Get(header_name_USER_AGENT)
if userAgent == "" {
req.Header.Add(USER_AGENT, service.UserAgent)
req.Header.Add(header_name_USER_AGENT, service.UserAgent)
}

// Add authentication to the outbound request.
Expand Down
Loading

0 comments on commit 6f51c35

Please sign in to comment.