Пример #1
0
// responseWriter sets the proper headers and status code, and
// writes a JSON-encoded response to the client.
func responseWriter(c siesta.Context, w http.ResponseWriter, r *http.Request,
	quit func()) {
	// Set the request ID header.
	if requestID := c.Get("request-id"); requestID != nil {
		w.Header().Set("X-Request-ID", requestID.(string))
	}

	// Set the content type.
	w.Header().Set("Content-Type", "application/json")

	enc := json.NewEncoder(w)

	// If we have a status code set in the context,
	// send that in the header.
	//
	// Go defaults to 200 OK.
	statusCode := c.Get("status-code")
	if statusCode != nil {
		statusCodeInt := statusCode.(int)
		w.WriteHeader(statusCodeInt)
	}

	// Check to see if we have some sort of response.
	response := c.Get("response")
	if response != nil {
		// We'll encode it as JSON without knowing
		// what it exactly is.
		enc.Encode(response)
	}

	// We're at the end of the middleware chain, so quit.
	quit()
}
Пример #2
0
// responseGenerator converts response and/or error data passed through the
// context into a structured response.
func responseGenerator(c siesta.Context, w http.ResponseWriter, r *http.Request) {
	response := apiResponse{}

	if data := c.Get("data"); data != nil {
		response.Data = data
	}

	if err := c.Get("error"); err != nil {
		response.Error = err.(string)
	}

	c.Set("response", response)
}
Пример #3
0
// getResource is the function that handles the GET /resources/:resourceID route.
func getResource(c siesta.Context, w http.ResponseWriter, r *http.Request) {
	// Context variables
	requestID := c.Get("request-id").(string)
	db := c.Get("db").(*DB)
	user := c.Get("user").(string)

	// Check parameters
	var params siesta.Params
	resourceID := params.Int("resourceID", -1, "Resource identifier")
	err := params.Parse(r.Form)
	if err != nil {
		log.Printf("[Req %s] %v", requestID, err)
		c.Set("error", err.Error())
		c.Set("status-code", http.StatusBadRequest)
		return
	}

	// Make sure we have a valid resource ID.
	if *resourceID == -1 {
		c.Set("error", "invalid or missing resource ID")
		c.Set("status-code", http.StatusBadRequest)
		return
	}

	resource, err := db.resource(user, *resourceID)
	if err != nil {
		c.Set("status-code", http.StatusNotFound)
		c.Set("error", "not found")
		return
	}

	c.Set("data", resource)
}
Пример #4
0
// authenticator reads the username from the HTTP basic authentication header
// and validates the token. It sets the "user" key in the context to the
// user associated with the token.
func authenticator(c siesta.Context, w http.ResponseWriter, r *http.Request,
	quit func()) {
	// Context variables
	requestID := c.Get("request-id").(string)
	db := c.Get("db").(*DB)

	// Check for a token in the HTTP basic authentication username field.
	token, _, ok := r.BasicAuth()
	if ok {
		user, err := db.validateToken(token)
		if err != nil {
			log.Printf("[Req %s] Did not provide a valid token", requestID)
			c.Set("status-code", http.StatusUnauthorized)
			c.Set("error", "invalid token")
			quit()
			return
		}

		log.Printf("[Req %s] Provided a token for: %s", requestID, user)

		// Add the user to the context.
		c.Set("user", user)
	} else {
		log.Printf("[Req %s] Did not provide a token", requestID)

		c.Set("error", "token required")
		c.Set("status-code", http.StatusUnauthorized)

		// Exit the chain here.
		quit()
		return
	}
}
Пример #5
0
// requestIdentifier generates a request ID and sets the "request-id"
// key in the context. It also logs the request ID and the requested URL.
func requestIdentifier(c siesta.Context, w http.ResponseWriter, r *http.Request) {
	requestID := fmt.Sprintf("%x", rand.Int())
	c.Set("request-id", requestID)
	log.Printf("[Req %s] %s %s", requestID, r.Method, r.URL)
}