Example #1
0
// NewWebService provides a way to create a new blank WebService
func NewWebService() WebService {
	ws := WebService{}

	// add standard routes
	// Stats controller
	ws.stats = stats.New()
	statsController := NewWebController("/stats")
	statsController.AddMethodHandler(Get, func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json; charset=utf-8")
		w.WriteHeader(http.StatusOK)
		b, _ := json.Marshal(ws.stats.Data())
		w.Write(b)
	})
	ws.AddWebController(statsController)

	// Heartbeat controller (echoes the default version info)
	heartbeatController := NewWebController("/heartbeat")
	heartbeatController.AddMethodHandler(Get, func(w http.ResponseWriter, r *http.Request) {
		v := Version{}
		v.Hydrate()
		render.JSON(w, http.StatusOK, v)
	})
	ws.AddWebController(heartbeatController)

	return ws
}
// Handles POST for /verify
func (validator accountValidator) AccountValidatorPost(w http.ResponseWriter, req *http.Request) {
	var transformedRequest bankAccountRequest

	// Decode the JSON payload
	if err := json.NewDecoder(req.Body).Decode(&transformedRequest); err != nil {
		responses.WriteUnprocessableEntity(w)
		return
	}

	// Check that we got an expected format
	if !transformedRequest.isValid() {
		message := "Expected a 6 digits sort code and an account number between 6 and 10 digits."
		responses.WriteMessage(http.StatusBadRequest, "invalid_bank_account", message, w)
		return
	}

	// Create the required bank account
	b := models.CreateBankAccount(transformedRequest.SortCode, transformedRequest.AccountNumber)

	// Check if the bank account is valid
	isValid := validator.resolver.IsValid(b)

	// Construct and render the final response
	response := ValidityResponse{
		Valid:         isValid,
		SortCode:      b.SortCode,
		AccountNumber: b.AccountNumber,
	}
	render.JSON(w, http.StatusOK, response)
}
// Write a message with a given status code, a status and a message
func WriteMessage(code int, status string, message string, w http.ResponseWriter) {
	response := APIMessage{
		code:    code,
		Status:  status,
		Message: message,
	}
	render.JSON(w, response.code, response)
}
Example #4
0
// NewWebService provides a way to create a new blank WebService
func NewWebService() WebService {
	ws := WebService{}

	// Heartbeat controller (echoes the default version info)
	heartbeatController := NewWebController(HeartbeatRoute)
	heartbeatController.AddMethodHandler(Get,
		func(w http.ResponseWriter, r *http.Request) {
			v := Version{}
			v.Hydrate()
			render.JSON(w, http.StatusOK, v)
		},
	)
	ws.AddWebController(heartbeatController)

	return ws
}
Example #5
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
}