// Get uses the cookie value with the given name to // populate the out argument. If the types don't match // (e.g. the cookie was set to a string and you try // to get an int), an error will be returned. func (c *Cookies) Get(name string, out interface{}) error { cookie, err := c.GetCookie(name) if err != nil { return err } data, err := base64.Decode(cookie.Value) if err != nil { return err } return c.c.Decode(data, out) }
// Unsign takes a string, previously returned from Sign, checks // that its signature is valid and, in that case, returns the initial // data. If the signature is not valid, an error is returned. func (s *Signer) Unsign(signed string) ([]byte, error) { parts := strings.Split(signed, ":") if len(parts) != 2 { return nil, ErrNotSigned } data, err := base64.Decode(parts[0]) if err != nil { return nil, err } signature, err := base64.Decode(parts[1]) if err != nil { return nil, err } sign, err := s.sign(data) if err != nil { return nil, err } if len(sign) != len(signature) || subtle.ConstantTimeCompare(sign, signature) != 1 { return nil, ErrTampered } return data, nil }
func (c *Cookies) decode(data string, arg interface{}, t transformer) error { b, err := base64.Decode(data) if err != nil { return err } if t != nil { b, err = t(b) if err != nil { return err } } return c.c.Decode(b, arg) }
func requestProfile(u string, method string, values url.Values, secret string) (*profileInfo, error) { var req *http.Request var err error if method == "POST" { if len(values) > 0 { req, err = http.NewRequest(method, u, strings.NewReader(values.Encode())) if req != nil { req.Header.Add("Content-Type", "application/x-www-form-urlencoded") } } else { req, err = http.NewRequest(method, u, nil) } } else { reqURL := u if len(values) > 0 { reqURL += "?" + values.Encode() } req, err = http.NewRequest(method, reqURL, nil) } if err != nil { return nil, err } if secret != "" { ts := time.Now().Unix() nonce := stringutil.Random(32) signer := cryptoutil.Signer{Salt: []byte(profile.Salt), Key: []byte(secret)} signed, err := signer.Sign([]byte(fmt.Sprintf("%d:%s", ts, nonce))) if err != nil { return nil, err } req.Header.Add(profile.HeaderName, signed) } else { req.Header.Add(profile.HeaderName, "true") } dump, err := httputil.DumpRequestOut(req, true) if err != nil { return nil, err } log.Debugf("Request: \n%s", string(dump)) client := &http.Client{} resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() value := resp.Header.Get(profile.HeaderName) switch value { case "": return nil, fmt.Errorf("no profiling info on %s - is profiling enabled?", u) case "auth": return nil, errAuthRequired case "denied": return nil, errAuthFailed } decoded, err := base64.Decode(value) if err != nil { return nil, err } r := flate.NewReader(bytes.NewReader(decoded)) defer r.Close() dec := json.NewDecoder(r) var info *profileInfo if err := dec.Decode(&info); err != nil { return nil, err } return info, nil }