Example #1
2
// PlainText sets the content-type of responses to text/plain.
func Json(h http.Handler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/json")
		h.ServeHTTP(w, r)
	}
	return http.HandlerFunc(fn)
}
Example #2
1
func debugMiddleware(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		t0 := time.Now()
		h.ServeHTTP(w, r)

		if shouldDebugHTTP() {
			ms := 1000 * time.Since(t0).Seconds()

			// The variable `w` is most likely a *http.response, which we can't do
			// much with since it's a non exported type. We can however peek into
			// it with reflection to get at the status code and number of bytes
			// written.
			var status, written int64
			if rw := reflect.Indirect(reflect.ValueOf(w)); rw.IsValid() && rw.Kind() == reflect.Struct {
				if rf := rw.FieldByName("status"); rf.IsValid() && rf.Kind() == reflect.Int {
					status = rf.Int()
				}
				if rf := rw.FieldByName("written"); rf.IsValid() && rf.Kind() == reflect.Int64 {
					written = rf.Int()
				}
			}
			httpl.Debugf("http: %s %q: status %d, %d bytes in %.02f ms", r.Method, r.URL.String(), status, written, ms)
		}
	})
}
Example #3
1
func withDetailsMiddleware(id protocol.DeviceID, h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("X-Syncthing-Version", Version)
		w.Header().Set("X-Syncthing-ID", id.String())
		h.ServeHTTP(w, r)
	})
}
Example #4
1
func wrapBasicAuth(handler http.Handler, credential string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		token := strings.SplitN(r.Header.Get("Authorization"), " ", 2)

		if len(token) != 2 || strings.ToLower(token[0]) != "basic" {
			w.Header().Set("WWW-Authenticate", `Basic realm="GoTTY"`)
			http.Error(w, "Bad Request", http.StatusUnauthorized)
			return
		}

		payload, err := base64.StdEncoding.DecodeString(token[1])
		if err != nil {
			http.Error(w, "Internal Server Error", http.StatusInternalServerError)
			return
		}

		if credential != string(payload) {
			w.Header().Set("WWW-Authenticate", `Basic realm="GoTTY"`)
			http.Error(w, "authorization failed", http.StatusUnauthorized)
			return
		}

		log.Printf("Basic Authentication Succeeded: %s", r.RemoteAddr)
		handler.ServeHTTP(w, r)
	})
}
Example #5
1
func Green(next http.Handler) http.Handler {
	return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
		rw.Header().Set("X-Favorite-Color", "green")
		next.ServeHTTP(rw, req)
		fmt.Fprint(rw, " who likes green")
	})
}
Example #6
1
func Logger(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		//startTime := time.Now()
		h.ServeHTTP(w, r)
		//log.Printf("[vertigo] %s %s (%v)\n", r.Method, r.URL.Path, time.Since(startTime))
	})
}
Example #7
1
// ServeHTTP dispatches the handler registered in the matched route.
//
// When there is a match, the route variables can be retrieved calling
// mux.Vars(request).
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	// Clean path to canonical form and redirect.
	if p := cleanPath(req.URL.Path); p != req.URL.Path {

		// Added 3 lines (Philip Schlump) - It was dropping the query string and #whatever from query.
		// This matches with fix in go 1.2 r.c. 4 for same problem.  Go Issue:
		// http://code.google.com/p/go/issues/detail?id=5252
		url := *req.URL
		url.Path = p
		p = url.String()

		w.Header().Set("Location", p)
		w.WriteHeader(http.StatusMovedPermanently)
		return
	}
	var match RouteMatch
	var handler http.Handler
	if r.Match(req, &match) {
		handler = match.Handler
		setVars(req, match.Vars)
		setCurrentRoute(req, match.Route)
	}
	if handler == nil {
		handler = r.NotFoundHandler
		if handler == nil {
			handler = http.NotFoundHandler()
		}
	}
	if !r.KeepContext {
		defer context.Clear(req)
	}
	handler.ServeHTTP(w, req)
}
Example #8
0
// cors responds to incoming requests and adds the appropriate cors headers
// TODO: corylanou: add the ability to configure this in our config
func cors(inner http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if origin := r.Header.Get("Origin"); origin != "" {
			w.Header().Set(`Access-Control-Allow-Origin`, origin)
			w.Header().Set(`Access-Control-Allow-Methods`, strings.Join([]string{
				`DELETE`,
				`GET`,
				`OPTIONS`,
				`POST`,
				`PUT`,
			}, ", "))

			w.Header().Set(`Access-Control-Allow-Headers`, strings.Join([]string{
				`Accept`,
				`Accept-Encoding`,
				`Authorization`,
				`Content-Length`,
				`Content-Type`,
				`X-CSRF-Token`,
				`X-HTTP-Method-Override`,
			}, ", "))
		}

		if r.Method == "OPTIONS" {
			return
		}

		inner.ServeHTTP(w, r)
	})
}
Example #9
0
// Handle regiester a standard http.Handler request handler with the given
// path and method. With this adapter, your handler won't have access to the
// context and thus won't work with URL parameters.
func (mux *Mux) Handle(method, path string, handler http.Handler) {
	mux.HandleC(method, path,
		xhandler.HandlerFuncC(func(_ context.Context, w http.ResponseWriter, r *http.Request) {
			handler.ServeHTTP(w, r)
		}),
	)
}
Example #10
0
func Log(handler http.Handler) http.Handler {
	log.Println(handler)
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Printf("%s %s %s &s", r.RemoteAddr, r.Method, r.URL)
		handler.ServeHTTP(w, r)
	})
}
Example #11
0
func auth(config *Config, next http.Handler) http.Handler {
	unauthorized := func(w http.ResponseWriter) {
		send(w, http.StatusUnauthorized, Json{"error": "Unauthorized"})
	}

	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		if config.Auth != "" {
			s := strings.SplitN(req.Header.Get("Authorization"), " ", 2)
			if len(s) != 2 || s[0] != "Basic" {
				unauthorized(w)
				return
			}

			base, err := base64.StdEncoding.DecodeString(s[1])
			if err != nil {
				unauthorized(w)
				return
			}

			pair := strings.SplitN(string(base), ":", 2)
			if len(pair) != 2 {
				unauthorized(w)
				return
			}

			password := pair[1]
			if config.Auth != password {
				unauthorized(w)
				return
			}
		}

		next.ServeHTTP(w, req)
	})
}
Example #12
0
func Wrap(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		m := New(w, r)
		next.ServeHTTP(m, r)
		m.Log()
	})
}
Example #13
0
func (c *MasterConfig) authorizationFilter(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		attributes, err := c.AuthorizationAttributeBuilder.GetAttributes(req)
		if err != nil {
			forbidden(err.Error(), attributes, w, req)
			return
		}
		if attributes == nil {
			forbidden("No attributes", attributes, w, req)
			return
		}

		ctx, exists := c.RequestContextMapper.Get(req)
		if !exists {
			forbidden("context not found", attributes, w, req)
			return
		}

		allowed, reason, err := c.Authorizer.Authorize(ctx, attributes)
		if err != nil {
			forbidden(err.Error(), attributes, w, req)
			return
		}
		if !allowed {
			forbidden(reason, attributes, w, req)
			return
		}

		handler.ServeHTTP(w, req)
	})
}
Example #14
0
// namespacingFilter adds a filter that adds the namespace of the request to the context.  Not all requests will have namespaces,
// but any that do will have the appropriate value added.
func namespacingFilter(handler http.Handler, contextMapper kapi.RequestContextMapper) http.Handler {
	infoResolver := &apiserver.RequestInfoResolver{APIPrefixes: sets.NewString("api", "osapi", "oapi", "apis"), GrouplessAPIPrefixes: sets.NewString("api", "osapi", "oapi")}

	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		ctx, ok := contextMapper.Get(req)
		if !ok {
			http.Error(w, "Unable to find request context", http.StatusInternalServerError)
			return
		}

		if _, exists := kapi.NamespaceFrom(ctx); !exists {
			if requestInfo, err := infoResolver.GetRequestInfo(req); err == nil {
				// only set the namespace if the apiRequestInfo was resolved
				// keep in mind that GetAPIRequestInfo will fail on non-api requests, so don't fail the entire http request on that
				// kind of failure.

				// TODO reconsider special casing this.  Having the special case hereallow us to fully share the kube
				// APIRequestInfoResolver without any modification or customization.
				namespace := requestInfo.Namespace
				if (requestInfo.Resource == "projects") && (len(requestInfo.Name) > 0) {
					namespace = requestInfo.Name
				}

				ctx = kapi.WithNamespace(ctx, namespace)
				contextMapper.Update(req, ctx)
			}
		}

		handler.ServeHTTP(w, req)
	})
}
Example #15
0
func Logger(inner http.Handler, name string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		start := time.Now()
		w.Header().Add("Access-Control-Allow-Origin", "http://ayeke.me:3000")
		var err error
		defer func() {
			r := recover()
			if r != nil {
				switch t := r.(type) {
				case string:
					err = errors.New(t)
				case error:
					err = t
				default:
					err = errors.New("Unknown error")
				}
				http.Error(w, err.Error(), http.StatusInternalServerError)
			}
		}()
		inner.ServeHTTP(w, r)

		log.Printf(
			"%s\t%s\t%s\t%s",
			r.Method,
			r.RequestURI,
			name,
			time.Since(start),
		)
	})
}
Example #16
0
// Handler is an adapter which allows the usage of an http.Handler as a
// request handle.
func (r *Router) Handler(method, path string, handler http.Handler) {
	r.Handle(method, path,
		func(w http.ResponseWriter, req *http.Request, _ Params) {
			handler.ServeHTTP(w, req)
		},
	)
}
Example #17
0
// LogrusLogger is a middleware that will log each request recieved, along with
// some useful information, to the given logger.
func LogrusLogger(logger *logrus.Logger, h http.Handler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		start := time.Now()
		entry := logger.WithFields(logrus.Fields{
			"request": r.RequestURI,
			"method":  r.Method,
			"remote":  r.RemoteAddr,
		})

		if id := r.Header.Get(RequestIDKey); id != "" {
			entry = entry.WithField("request_id", id)
		}

		// Wrap the writer so we can track data information.
		neww := WrapWriter(w)

		// Dispatch to the underlying handler.
		entry.Info("started handling request")
		h.ServeHTTP(neww, r)

		// Log final information.
		entry.WithFields(logrus.Fields{
			"bytes_written": neww.BytesWritten(),
			"status":        neww.Status(),
			"text_status":   http.StatusText(neww.Status()),
			"took":          time.Since(start),
		}).Info("completed handling request")
	}

	return http.HandlerFunc(fn)
}
Example #18
0
func WrapBefore(handler http.Handler) HandlerFunc {
	return func(ctx *Context) {
		handler.ServeHTTP(ctx.ResponseWriter, ctx.Req())

		ctx.Next()
	}
}
Example #19
0
// Log adds Generic request logging as a handler, cause thats probably a good idea
func Log(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ff := r.Header.Get("X-Forwarded-For")
		log.Printf("client='%s' forward-for='%s' method='%s' request='%s' agent='%s'", r.RemoteAddr, ff, r.Method, r.URL, r.UserAgent())
		handler.ServeHTTP(w, r)
	})
}
Example #20
0
func WrapAfter(handler http.Handler) HandlerFunc {
	return func(ctx *Context) {
		ctx.Next()

		handler.ServeHTTP(ctx.ResponseWriter, ctx.Req())
	}
}
Example #21
0
func secretHandler(secret string, next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		if secret != "" {
			s := req.Header.Get("X-Hub-Signature")

			if s == "" {
				w.WriteHeader(http.StatusForbidden)
				fmt.Fprintf(w, "X-Hub-Signature required for HMAC verification")
				return
			}

			body, _ := ioutil.ReadAll(req.Body)

			hash := hmac.New(sha1.New, []byte(secret))
			hash.Write(body)
			expected := "sha1=" + hex.EncodeToString(hash.Sum(nil))

			if !hmac.Equal([]byte(expected), []byte(s)) {
				w.WriteHeader(http.StatusForbidden)
				fmt.Fprintf(w, "HMAC verification failed")
				return
			}
			req.Body = ioutil.NopCloser(bytes.NewBuffer(body))
		}

		next.ServeHTTP(w, req)
	})
}
Example #22
0
// trackRequests wraps a http.Handler, incrementing and decrementing
// the apiserver's WaitGroup and blocking request when the apiserver
// is shutting down.
//
// Note: It is only safe to use trackRequests with API handlers which
// are interruptible (i.e. they pay attention to the apiserver tomb)
// or are guaranteed to be short-lived. If it's used with long running
// API handlers which don't watch the apiserver's tomb, apiserver
// shutdown will be blocked until the API handler returns.
func (srv *Server) trackRequests(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Care must be taken to not increment the waitgroup count
		// after the listener has closed.
		//
		// First we check to see if the tomb has not yet been killed
		// because the closure of the listener depends on the tomb being
		// killed to trigger the defer block in srv.run.
		select {
		case <-srv.tomb.Dying():
			// This request was accepted before the listener was closed
			// but after the tomb was killed. As we're in the process of
			// shutting down, do not consider this request as in progress,
			// just send a 503 and return.
			http.Error(w, "apiserver shutdown in progress", 503)
		default:
			// If we get here then the tomb was not killed therefore the
			// listener is still open. It is safe to increment the
			// wg counter as wg.Wait in srv.run has not yet been called.
			srv.wg.Add(1)
			defer srv.wg.Done()
			handler.ServeHTTP(w, r)
		}
	})
}
Example #23
0
func SetUser(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		token := r.Header.Get("X-Auth-Token")

		if token == "" {
			ctx.SetCurrentUser(r, nil)
		} else {
			user, found, err := model.FindUserByToken(token, ctx.M(r))

			if err != nil {
				log.Println(err)
				w.WriteHeader(http.StatusInternalServerError)
				return
			}

			if found {
				ctx.SetCurrentUser(r, &user)
			} else {
				ctx.SetCurrentUser(r, nil)
			}
		}

		h.ServeHTTP(w, r)
	})
}
Example #24
0
func (c *appContext) authHandler(next http.Handler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {

		// Get a session. We're ignoring the error resulted from decoding an
		// existing session: Get() always returns a session, even if empty.
		session, err := cookieStore.Get(r, "mt_logged_in")
		if err != nil {
			http.Error(w, http.StatusText(401), 401)
			return
		}

		var u models.User

		u.UserId = session.Values["user_id"].(int)
		u.Steam64 = session.Values["steam64"].(int)
		u.Steam32 = session.Values["steam32"].(int)
		u.Email = session.Values["email"].(string)
		u.Name = session.Values["name"].(string)

		context.Set(r, "user", u)
		next.ServeHTTP(w, r)

	}

	return http.HandlerFunc(fn)
}
Example #25
0
func NewRequestLogger(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		rw := w.(*ResponseWriter)

		reqID, _ := ctxhelper.RequestIDFromContext(rw.Context())
		componentName, _ := ctxhelper.ComponentNameFromContext(rw.Context())
		logger := log.New(log.Ctx{"component": componentName, "req_id": reqID})
		rw.ctx = ctxhelper.NewContextLogger(rw.Context(), logger)

		start := time.Now()
		var clientIP string
		clientIPs := strings.Split(req.Header.Get("X-Forwarded-For"), ",")
		if len(clientIPs) > 0 {
			clientIP = strings.TrimSpace(clientIPs[len(clientIPs)-1])
		}
		var err error
		if clientIP == "" {
			clientIP, _, err = net.SplitHostPort(req.RemoteAddr)
			if err != nil {
				Error(w, err)
				return
			}
		}

		logger.Info("request started", "method", req.Method, "path", req.URL.Path, "client_ip", clientIP)

		handler.ServeHTTP(rw, req)

		logger.Info("request completed", "status", rw.Status(), "duration", time.Since(start))
	})
}
Example #26
0
// Efficient favicon handler, mostly a port of node's Connect library implementation
// of the favicon middleware.
// https://github.com/senchalabs/connect
func FaviconHandler(h http.Handler, path string, maxAge time.Duration) http.HandlerFunc {
	var buf []byte
	var hash string

	return func(w http.ResponseWriter, r *http.Request) {
		var err error
		if r.URL.Path == "/favicon.ico" {
			if buf == nil {
				// Read from file and cache
				ghost.LogFn("ghost.favicon : serving from %s", path)
				buf, err = ioutil.ReadFile(path)
				if err != nil {
					ghost.LogFn("ghost.favicon : error reading file : %s", err)
					http.NotFound(w, r)
					return
				}
				hash = hashContent(buf)
			}
			writeHeaders(w.Header(), buf, maxAge, hash)
			writeBody(w, r, buf)
		} else {
			h.ServeHTTP(w, r)
		}
	}
}
Example #27
0
func corsMiddleware(next http.Handler) http.Handler {
	// Handle CORS headers and CORS OPTIONS request.
	// CORS OPTIONS request are typically sent by browser during AJAX preflight
	// when the browser initiate a POST request.
	//
	// As the OPTIONS request is unauthorized, this handler must be the first
	// of the chain (hence added at the end).
	//
	// See https://www.w3.org/TR/cors/ for details.
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Process OPTIONS requests
		if r.Method == "OPTIONS" {
			// Only GET/POST Methods are supported
			w.Header().Set("Access-Control-Allow-Methods", "GET, POST")
			// Only this custom header can be set
			w.Header().Set("Access-Control-Allow-Headers", "X-API-Key")
			// The request is meant to be cached 10 minutes
			w.Header().Set("Access-Control-Max-Age", "600")

			// Indicate that no content will be returned
			w.WriteHeader(204)

			return
		}

		// For everything else, pass to the next handler
		next.ServeHTTP(w, r)
		return
	})
}
func handlerAccessLog(handler http.Handler) http.Handler {
	logHandler := func(w http.ResponseWriter, r *http.Request) {
		log.Printf("%s \"%s %s\"", r.RemoteAddr, r.Method, r.URL)
		handler.ServeHTTP(w, r)
	}
	return http.HandlerFunc(logHandler)
}
Example #29
0
func logRequests(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		//do stuff with the request here
		log.Println("Request logged")
		h.ServeHTTP(w, r)
	})
}
Example #30
0
func metrics(op string, next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		var (
			start = time.Now()
			rd    = &readerDelegator{ReadCloser: r.Body}
			rc    = &responseRecorder{ResponseWriter: w}
		)

		r.Body = rd

		next.ServeHTTP(rc, r)

		d := time.Since(start)
		labels := map[string]string{
			"bucket":    r.URL.Query().Get(ent.KeyBucket),
			"method":    strings.ToLower(r.Method),
			"operation": op,
			"status":    strconv.Itoa(rc.status),
		}

		requestBytes.With(labels).Add(float64(rd.BytesRead))
		requestDurations.With(labels).Observe(float64(d))
		responseBytes.With(labels).Add(float64(rc.size))
	})
}