Exemplo n.º 1
0
// GetMethodHandler returns the appropriate method handler for the request or a
// Method Not Allowed handler
func (wc *WebController) GetMethodHandler(m int) func(w http.ResponseWriter, req *http.Request) {
	if m == Options {
		return func(w http.ResponseWriter, req *http.Request) {
			w.Header().Set("Allow", wc.GetAllowedMethods())
			w.Header().Set("Content-Length", "0")
			w.WriteHeader(http.StatusOK)
		}
	}

	if m == Head {
		return func(w http.ResponseWriter, req *http.Request) {
			w.Header().Set("Allow", wc.GetAllowedMethods())
			w.Header().Set("Content-Length", "0")
			w.WriteHeader(http.StatusOK)
		}
	}

	if h, ok := wc.handlers[m]; ok {
		return h
	}

	return func(w http.ResponseWriter, req *http.Request) {
		allowed := wc.GetAllowedMethods()
		w.Header().Set("Allow", allowed)

		render.Error(
			w,
			http.StatusMethodNotAllowed,
			fmt.Errorf("405 Method Not Allowed. Allowed: %s", allowed),
		)
	}
}
Exemplo n.º 2
0
// BuildRouter collects all of the controllers, wires up the routes and returns
// the resulting router
func (ws *WebService) BuildRouter() *mux.Router {
	// Router
	//
	// StrictSlash forces the routes to be applied literally...
	// i.e. Route /foo/ with requests /foo will redirect to /foo/
	// and route /bar with requests to /bar/ will redirect to /bar
	r := mux.NewRouter().StrictSlash(true)

	// Controllers
	rootSeen := false
	versionSeen := false
	links := EndPoints{}
	for _, wc := range ws.controllers {
		if !rootSeen && wc.Route == root {
			rootSeen = true
		}

		if !versionSeen && wc.Route == VersionRoute {
			versionSeen = true
		}

		// Add the handler for a route, and rate-limit it using throttle
		r.Handle(
			wc.Route,
			http.HandlerFunc(GetHandler(wc)),
		)

		links = append(links, EndPoint{URL: wc.Route, Methods: wc.GetAllowedMethods()})
	}

	// Profiling handlers
	// XXX: should we add them using the public api too?
	r.HandleFunc("/profiler/info.html", profiler.MemStatsHTMLHandler)
	links = append(links, EndPoint{URL: "/profiler/info.html", Methods: "GET"})
	r.HandleFunc("/profiler/info", profiler.ProfilingInfoJSONHandler)
	r.HandleFunc("/profiler/start", profiler.StartProfilingHandler)
	r.HandleFunc("/profiler/stop", profiler.StopProfilingHandler)

	r.HandleFunc("/debug/pprof/", http.HandlerFunc(gopprof.Index))
	links = append(links, EndPoint{URL: "/debug/pprof", Methods: "GET"})
	r.HandleFunc("/debug/pprof/cmdline", http.HandlerFunc(gopprof.Cmdline))
	r.HandleFunc("/debug/pprof/profile", http.HandlerFunc(gopprof.Profile))
	r.HandleFunc("/debug/pprof/symbol", http.HandlerFunc(gopprof.Symbol))

	if !versionSeen {
		// If detailed version info is not provided, we echo the default
		// This allows services to provide their own extended version info, i.e.
		// database versioning as well as process versioning
		r.HandleFunc(VersionRoute, func(w http.ResponseWriter, r *http.Request) {
			v := Version{}
			v.Hydrate()
			render.JSON(w, http.StatusOK, v)
		})
		links = append(links, EndPoint{URL: VersionRoute, Methods: "GET"})
	}

	// The last routes are the NotFound routes as we want to return JSON.
	//
	// This handles / on it's own, and we should only do this if no other
	// route already registered /
	if !rootSeen {
		sort.Sort(links)
		r.HandleFunc(root, func(w http.ResponseWriter, r *http.Request) {
			render.JSON(w, http.StatusOK, links)
		})
	}

	// This is a wildcard route and will greedily consume all remaining routes
	r.HandleFunc("/{path:.*}", func(w http.ResponseWriter, r *http.Request) {
		render.Error(
			w,
			http.StatusNotFound,
			fmt.Errorf("/%s not found", mux.Vars(r)["path"]),
		)
	})

	return r
}