Beispiel #1
0
// url generates the absolute URL that will be used to make
// this request.
func (r *Request) url() (*url.URL, error) {

	urlString := stewstrings.MergeStrings(r.session.host(), common.PathSeparator, r.path)

	theURL, urlErr := url.Parse(urlString)

	if urlErr != nil {
		return nil, urlErr
	}

	// set the query values
	theURL.RawQuery = r.queryValues.Encode()

	urlString = theURL.String()

	if strings.Contains(urlString, "?") {
		urlString = stewstrings.MergeStrings(urlString, "&", common.ParameterAPIKey, "=", r.session.apiKey)
	} else {
		urlString = stewstrings.MergeStrings(urlString, "?", common.ParameterAPIKey, "=", r.session.apiKey)
	}

	theURL, urlErr = url.Parse(urlString)

	if urlErr != nil {
		return nil, urlErr
	}

	return theURL, nil

}
Beispiel #2
0
// GetSignedURL gets the URL with the sign parameter added based on the given parameters.
func GetSignedURLWithTrace(method, requestUrl, body, privateKey string, tracer *tracer.Tracer) (string, error) {

	trace(tracer, "GetSignedURL: method=%s", method)
	trace(tracer, "GetSignedURL: requestUrl=%s", requestUrl)
	trace(tracer, "GetSignedURL: body=%s", body)
	trace(tracer, "GetSignedURL: privateKey=%s", privateKey)

	hash, hashErr := GetSignatureWithTrace(method, requestUrl, body, privateKey, tracer)

	if hashErr != nil {
		trace(tracer, "GetSignedURL: FAILED to get the signature: %s", hashErr)
		return FailedSignature, hashErr
	}

	var signedUrl string
	if strings.Contains(requestUrl, "?") {
		signedUrl = stewstrings.MergeStrings(requestUrl, "&", url.QueryEscape(SignatureKey), "=", url.QueryEscape(hash))
	} else {
		signedUrl = stewstrings.MergeStrings(requestUrl, "?", url.QueryEscape(SignatureKey), "=", url.QueryEscape(hash))
	}

	trace(tracer, "GetSignedURL: Output: %s", signedUrl)

	return signedUrl, nil

}
Beispiel #3
0
// Marshal converts an object to JSONP.
func (c *JsonPCodec) Marshal(object interface{}, options map[string]interface{}) ([]byte, error) {

	if len(options) == 0 {
		return nil, ErrorMissingCallback
	}

	json, err := jsonEncoding.Marshal(object)

	if err != nil {
		return nil, err
	}

	// #codec-context-options
	// the assumption is options[0] is the callback parameter,
	// and options[1] is the client-context (NB: not *Context) string.

	var callbackFunctionName string
	var callbackString string
	var clientContextString string
	var ok bool

	if callbackFunctionName, ok = options[constants.OptionKeyClientCallback].(string); !ok {
		panic("stretchrcom/codecs: JSONP requires the options to contain the constants.OptionKeyClientCallback value.")
	}

	clientContextString, hasClientContext := options[constants.OptionKeyClientContext].(string)

	if !hasClientContext {
		callbackString = stewstrings.MergeStrings(callbackFunctionName, "(", string(json), ");")
	} else {
		callbackString = stewstrings.MergeStrings(options[constants.OptionKeyClientCallback].(string), "(", string(json), `,"`, clientContextString, `"`, ");")
	}

	return []byte(callbackString), nil
}
Beispiel #4
0
// OrderParams gets the parameters ordered by key, then by values as a URL string.
func OrderParams(values url.Values) string {

	// get the keys
	var keys []string
	for k, _ := range values {
		keys = append(keys, k)
	}

	// sort the keys
	sort.Strings(keys)

	// ordered items
	var ordered []string

	// sort the values
	for _, key := range keys {
		sort.Strings(values[key])
		for _, val := range values[key] {
			ordered = append(ordered, stewstrings.MergeStrings(key, "=", val))
		}
	}

	joined := stewstrings.JoinStrings("&", ordered...)
	return joined

}
Beispiel #5
0
// host gets the host to make requests to.
func (s *Session) host() string {

	// get the protocol
	var protocol string
	if s.UseSSL {
		protocol = common.HTTPProtocolSecure
	} else {
		protocol = common.HTTPProtocol
	}

	host := stewstrings.MergeStrings(protocol,
		common.ProtocolSeparator,
		s.account,
		common.HostSeparator,
		common.TopLevelHostName,
		common.APIVersionPathPrefix,
		s.apiVersion,
		common.PathSeparator,
		s.project,
	)

	Tracer.TraceInfo("Host string: %s", host)

	return host

}
Beispiel #6
0
// String gets a nicely formatted string of the trace data.
func (t *Tracer) String() string {

	if t == nil {
		return ""
	}

	t.Process()

	return strings.MergeStrings("\n", strings.JoinStrings("\n", t.StringData()...))
}
Beispiel #7
0
// GetSignatureWithTrace gets the signature of a request based on the given parameters.
func GetSignatureWithTrace(method, requestUrl, body, privateKey string, tracer *tracer.Tracer) (string, error) {

	trace(tracer, "GetSignature: method=%s", method)
	trace(tracer, "GetSignature: requestUrl=%s", requestUrl)
	trace(tracer, "GetSignature: body=%s", body)
	trace(tracer, "GetSignature: privateKey=%s", privateKey)

	// parse the URL
	u, parseErr := url.ParseRequestURI(requestUrl)

	if parseErr != nil {
		trace(tracer, "GetSignature: FAILED to parse the URL: %s", parseErr)
		return FailedSignature, parseErr
	}

	trace(tracer, "GetSignature: Parsed the URL as: %s", u.String())

	// get the query values
	values := u.Query()

	// add the private key parameter
	values.Set(PrivateKeyKey, privateKey)

	trace(tracer, "GetSignature: Set the private key (%s): %s", PrivateKeyKey, privateKey)

	if len(body) > 0 {
		bodyHash := Hash(body)
		trace(tracer, "GetSignature: Set the body hash (%s): %s", BodyHashKey, bodyHash)
		values.Set(BodyHashKey, bodyHash)
	} else {
		trace(tracer, "GetSignature: Skipping body hash as there's no body (%s).", BodyHashKey)
	}

	// get the ordered params
	orderedParams := OrderParams(values)

	trace(tracer, "GetSignature: Ordered parameters: %s", orderedParams)

	base := strings.Split(u.String(), "?")[0]
	combined := stewstrings.MergeStrings(strings.ToUpper(method), "&", base, "?", orderedParams)

	trace(tracer, "GetSignature: Base    : %s", base)
	trace(tracer, "GetSignature: Combined: %s", combined)

	theHash := Hash(combined)

	trace(tracer, "GetSignature: Output: %s", theHash)

	return theHash, nil

}
Beispiel #8
0
// trace writes some trace (if there is a Tracer set).
func trace(t *tracer.Tracer, format string, args ...interface{}) {

	if t.Should(tracer.LevelDebug) {

		// add the 'signature' prefix to trace
		if len(format) > 0 {
			format = stewstrings.MergeStrings("signature: ", format)
		}

		// trace this
		t.Trace(tracer.LevelDebug, format, args...)
	}

}
Beispiel #9
0
func (p *PathPattern) String() string {
	return stewstrings.MergeStrings("{PathPattern:\"", p.RawPath, "\"}")
}
Beispiel #10
0
// MapController maps a controller to a specified path prefix.
//
// For more information, see goweb.MapController.
func (h *HttpHandler) MapController(options ...interface{}) error {

	var matcherFuncStartPos int = -1
	var path string
	var controller interface{}

	if len(options) == 0 {
		// no arguments is an error
		panic("goweb: Cannot call MapController with no arguments")
	}

	switch options[0].(type) {
	case string: // (path, controller)
		if len(options) == 1 {
			// we need more than just a string
			panic("goweb: Cannot call MapController without a Controller")
		}
		path = options[0].(string)
		controller = options[1]
		matcherFuncStartPos = 2
	default: // (controller)
		if restfulController, ok := options[0].(controllers.RestfulController); ok {
			controller = restfulController
			path = restfulController.Path()
		} else {
			// use the default path
			controller = options[0]
			path = paths.PathPrefixForClass(options[0])
		}
		matcherFuncStartPos = 1
	}

	// store the matcher function slice
	var matcherFuncs []MatcherFunc = findMatcherFuncs(options[matcherFuncStartPos:]...)

	// get the specialised paths that we might need
	pathWithID := stewstrings.MergeStrings(path, "/{", RestfulIDParameterName, "}")         // e.g.  people/123
	pathWithOptionalID := stewstrings.MergeStrings(path, "/[", RestfulIDParameterName, "]") // e.g.  people/[123]

	// get the HTTP methods that we will end up mapping
	collectiveMethods := controllers.OptionsListForResourceCollection(controller)
	singularMethods := controllers.OptionsListForSingleResource(controller)

	// BeforeHandler
	if beforeController, ok := controller.(controllers.BeforeHandler); ok {

		// map the collective before handler
		h.MapBefore(collectiveMethods, path, beforeController.Before, matcherFuncs)

		// map the singular before handler
		h.MapBefore(singularMethods, pathWithID, beforeController.Before, matcherFuncs)

	}

	// AfterHandler
	if afterController, ok := controller.(controllers.AfterHandler); ok {

		// map the collective after handler
		h.MapAfter(collectiveMethods, path, afterController.After, matcherFuncs)

		// map the singular after handler
		h.MapAfter(singularMethods, pathWithID, afterController.After, matcherFuncs)

	}

	// POST /resource  -  Create
	if restfulController, ok := controller.(controllers.RestfulCreator); ok {
		h.Map(http.MethodPost, path, restfulController.Create, matcherFuncs)
	}

	// GET /resource/{id}  -  Read
	if restfulController, ok := controller.(controllers.RestfulReader); ok {
		h.Map(http.MethodGet, pathWithID, func(ctx context.Context) error {
			return restfulController.Read(ctx.PathParams().Get(RestfulIDParameterName).Str(), ctx)
		}, matcherFuncs)
	}

	// GET /resource  -  ReadMany
	if restfulController, ok := controller.(controllers.RestfulManyReader); ok {
		h.Map(http.MethodGet, path, restfulController.ReadMany, matcherFuncs)
	}

	// DELETE /resource/{id}  -  Delete
	if restfulController, ok := controller.(controllers.RestfulDeletor); ok {
		h.Map(http.MethodDelete, pathWithID, func(ctx context.Context) error {
			return restfulController.Delete(ctx.PathParams().Get(RestfulIDParameterName).Str(), ctx)
		}, matcherFuncs)
	}

	// DELETE /resource  -  DeleteMany
	if restfulController, ok := controller.(controllers.RestfulManyDeleter); ok {
		h.Map(http.MethodDelete, path, restfulController.DeleteMany, matcherFuncs)
	}

	// PUT /resource/{id}  -  Update
	if restfulController, ok := controller.(controllers.RestfulUpdater); ok {
		h.Map(http.MethodPut, pathWithID, func(ctx context.Context) error {
			return restfulController.Update(ctx.PathParams().Get(RestfulIDParameterName).Str(), ctx)
		}, matcherFuncs)
	}

	// PUT /resource  -  UpdateMany
	if restfulController, ok := controller.(controllers.RestfulManyUpdater); ok {
		h.Map(http.MethodPut, path, restfulController.UpdateMany, matcherFuncs)
	}

	// POST /resource/{id}  -  Replace
	if restfulController, ok := controller.(controllers.RestfulReplacer); ok {
		h.Map(http.MethodPost, pathWithID, func(ctx context.Context) error {
			return restfulController.Replace(ctx.PathParams().Get(RestfulIDParameterName).Str(), ctx)
		}, matcherFuncs)
	}

	// HEAD /resource/[id]  -  Head
	if restfulController, ok := controller.(controllers.RestfulHead); ok {
		h.Map(http.MethodHead, pathWithOptionalID, restfulController.Head, matcherFuncs)
	}

	// OPTIONS /resource/[id]  -  Options
	if restfulController, ok := controller.(controllers.RestfulOptions); ok {

		h.Map(http.MethodOptions, pathWithOptionalID, restfulController.Options, matcherFuncs)

	} else {

		// use the default options implementation

		h.Map(http.MethodOptions, path, func(ctx context.Context) error {
			ctx.HttpResponseWriter().Header().Set("Allow", strings.Join(collectiveMethods, ","))
			ctx.HttpResponseWriter().WriteHeader(200)
			return nil
		}, matcherFuncs)

		h.Map(http.MethodOptions, pathWithID, func(ctx context.Context) error {
			ctx.HttpResponseWriter().Header().Set("Allow", strings.Join(singularMethods, ","))
			ctx.HttpResponseWriter().WriteHeader(200)
			return nil
		}, matcherFuncs)

	}

	// everything ok
	return nil

}
Beispiel #11
0
// Where adds a filter to the request.
func (r *Request) Where(field, match string) *Request {
	return r.WithParam(stewstrings.MergeStrings(common.FilterFieldPrefix, field), match)
}