// parse the client address, based on http headers or the actual ip func (r *Request) parseAddr() { // the default is the originating ip. but we try to find better options because this is almost // never the right IP if parts := strings.Split(r.Request.RemoteAddr, ":"); len(parts) == 2 { r.RemoteIP = parts[0] } // If we have a forwarded-for header, take the address from there if xff := strings.Trim(r.Header.Get("X-Forwarded-For"), ","); len(xff) > 0 { addrs := strings.Split(xff, ",") lastFwd := addrs[len(addrs)-1] if ip := net.ParseIP(lastFwd); ip != nil { logging.Debug("Setting IP based on XFF header to %s", ip) r.RemoteIP = ip.String() } } else if xri := r.Header.Get("X-Real-Ip"); len(xri) > 0 { if ip := net.ParseIP(xri); ip != nil { logging.Debug("Setting IP based on XRI header to %s", ip) r.RemoteIP = ip.String() } } logging.Debug("Request ip: %s", r.RemoteIP) }
// FormatUrl returns a fully formatted URL for the context's route, with all path params replaced by // their respective values in the pathParams map func (t *TestContext) FormatUrl(pathParams Params) string { u := fmt.Sprintf("%s%s", t.serverURl, t.api.FullPath(FormatPath(t.routePath, pathParams))) logging.Debug("Formatted url: %s", u) return u }
func (r *Route) parseInfo(path string) error { ri, err := schema.NewRequestInfo(reflect.TypeOf(r.Handler), path, r.Description, r.Returns) if err != nil { return err } // search for custom unmarshallers in the request info for _, param := range ri.Params { if param.Type.Kind() == reflect.Struct { logging.Debug("Checking unmarshaller for %s", param.Type) val := reflect.Zero(param.Type).Interface() if unm, ok := val.(Unmarshaler); ok { logging.Info("Registering unmarshaller for %#v", val) schemaDecoder.RegisterConverter(val, gorilla.Converter(func(s string) reflect.Value { return reflect.ValueOf(unm.UnmarshalRequestData(s)) })) } } } r.requestInfo = ri return nil }
func ReadConfigs() error { if err := autoflag.Load(gofigure.DefaultLoader, &Config); err != nil { logging.Error("Error loading configs: %v", err) return err } logging.Info("Read configs: %#v", &Config) for k, m := range Config.APIConfigs { if conf, found := Config.apiconfs[k]; found && conf != nil { b, err := yaml.Marshal(m) if err == nil { if err := yaml.Unmarshal(b, conf); err != nil { logging.Error("Error reading config for API %s: %s", k, err) } else { logging.Debug("Unmarshaled API config for %s: %#v", k, conf) } } else { logging.Error("Error marshalling config for API %s: %s", k, err) } } else { logging.Warning("API Section %s in config file not registered with server", k) } } return nil }
// FullPath returns the calculated full versioned path inside the API of a request. // // e.g. if my API name is "myapi" and the version is 1.0, FullPath("/foo") returns "/myapi/1.0/foo" func (a *API) FullPath(relpath string) string { relpath = routeRe.ReplaceAllString(relpath, ":$1") ret := path.Join(a.root(), relpath) logging.Debug("FullPath for %s => %s", relpath, ret) return ret }
func (a *API) middlewareHandler(chain *step, security SecurityScheme, renderer Renderer) func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { // allow overriding the API's default renderer with a per-route one if renderer == nil { renderer = a.Renderer } return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { req := NewRequest(r) if !a.AllowInsecure && !req.Secure { // local requests bypass security if req.RemoteIP != "127.0.0.1" { http.Error(w, insecureAccessMessage, http.StatusForbidden) return } } r.ParseForm() // Copy values from the router params to the request params for _, v := range p { r.Form.Set(v.Key, v.Value) } var ret interface{} var err error if security != nil { if err = security.Validate(req); err != nil { logging.Warning("Error validating security scheme: %s", err) if e, ok := err.(*internalError); ok { e.Code = ErrUnauthorized err = e } } } if err == nil { ret, err = chain.handle(w, req) } if err != Hijacked { if err = renderer.Render(ret, err, w, req); err != nil { logging.Error("Error rendering response: %s", err) } } else { logging.Debug("Not rendering hijacked request %s", r.RequestURI) } } }
// parse the locale based on Accept-Language header. If no header found or the values are invalid, // we fall back to en-US func (r *Request) parseLocale() { tags, _, err := language.ParseAcceptLanguage(r.Header.Get("Accept-Language")) if err != nil { logging.Warning("Could not parse accept lang header: %s", err) return } if len(tags) > 0 { logging.Debug("Locale for request: %s", tags[0]) r.Locale = tags[0].String() } }
// Create new request validator for a request handler interface. // This function walks the struct tags of the handler's fields and extracts validation metadata. // // You should give it the reflect type of your request handler struct func NewRequestValidator(ri schema.RequestInfo) *RequestValidator { //if the user passes a pointer we walk the actual struct ret := &RequestValidator{ fieldValidators: make([]validator, 0), } //iterate over the fields and create a validator for each for _, pi := range ri.Params { var vali validator switch pi.Kind { // case reflect.Struct: // //for structs - we add validators recursively // validator := NewRequestValidator(field.Type) // if validator != nil && len(validator.fieldValidators) > 0 { // ret.fieldValidators = append(ret.fieldValidators, validator.fieldValidators...) // } // continue case reflect.String: vali = newStringValidator(pi) case reflect.Int, reflect.Int32, reflect.Int64: vali = newIntValidator(pi) case reflect.Float32, reflect.Float64: vali = newFloatValidator(pi) case reflect.Bool: vali = newBoolValidator(pi) default: logging.Error("I don't know how to validate %s", pi.Kind) continue } if vali != nil { logging.Debug("Adding validator %v to request validator %v", vali, ri) ret.fieldValidators = append(ret.fieldValidators, vali) } } return ret }
func (b BasicAuth) Handle(w http.ResponseWriter, r *vertex.Request, next vertex.HandlerFunc) (interface{}, error) { if !r.IsLocal() || !b.BypassForLocal { user, pass, ok := r.BasicAuth() if !ok { logging.Debug("No auth header, denying") b.requireAuth(w) return nil, vertex.Hijacked } if user != b.User || pass != b.Password { logging.Warning("Unmatching auth: %s/%s", user, pass) b.requireAuth(w) return nil, vertex.Hijacked } } return next(w, r) }
func (m *CacheMiddleware) Handle(w http.ResponseWriter, r *vertex.Request, next vertex.HandlerFunc) (interface{}, error) { // Do not act on request if they have no-cache header if strings.ToLower(r.Header.Get("Cache-Control")) == "no-cache" { return next(w, r) } key := m.requestKey(r) logging.Debug("CACHING KEY: %s", key) entry, err := m.get(key) if err == nil && entry != nil { logging.Info("Fetched cache response: %#v", entry.value) return entry.value, nil } v, err := next(w, r) if err == nil { m.put(key, newEntry(v, m.ttl)) } return v, err }