api.go 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // Copyright 2016 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package context
  5. import (
  6. "fmt"
  7. "net/http"
  8. "strings"
  9. "github.com/Unknwon/paginater"
  10. log "gopkg.in/clog.v1"
  11. "gopkg.in/macaron.v1"
  12. "github.com/gogs/gogs/pkg/setting"
  13. )
  14. type APIContext struct {
  15. *Context
  16. Org *APIOrganization
  17. }
  18. // FIXME: move to github.com/gogs/go-gogs-client
  19. const DOC_URL = "https://github.com/gogs/go-gogs-client/wiki"
  20. // Error responses error message to client with given message.
  21. // If status is 500, also it prints error to log.
  22. func (c *APIContext) Error(status int, title string, obj interface{}) {
  23. var message string
  24. if err, ok := obj.(error); ok {
  25. message = err.Error()
  26. } else {
  27. message = obj.(string)
  28. }
  29. if status == http.StatusInternalServerError {
  30. log.Error(3, "%s: %s", title, message)
  31. }
  32. c.JSON(status, map[string]string{
  33. "message": message,
  34. "url": DOC_URL,
  35. })
  36. }
  37. // NotFound renders the 404 response.
  38. func (c *APIContext) NotFound() {
  39. c.Status(http.StatusNotFound)
  40. }
  41. // ServerError renders the 500 response.
  42. func (c *APIContext) ServerError(title string, err error) {
  43. c.Error(http.StatusInternalServerError, title, err)
  44. }
  45. // NotFoundOrServerError use error check function to determine if the error
  46. // is about not found. It responses with 404 status code for not found error,
  47. // or error context description for logging purpose of 500 server error.
  48. func (c *APIContext) NotFoundOrServerError(title string, errck func(error) bool, err error) {
  49. if errck(err) {
  50. c.NotFound()
  51. return
  52. }
  53. c.ServerError(title, err)
  54. }
  55. // SetLinkHeader sets pagination link header by given total number and page size.
  56. func (c *APIContext) SetLinkHeader(total, pageSize int) {
  57. page := paginater.New(total, pageSize, c.QueryInt("page"), 0)
  58. links := make([]string, 0, 4)
  59. if page.HasNext() {
  60. links = append(links, fmt.Sprintf("<%s%s?page=%d>; rel=\"next\"", setting.AppURL, c.Req.URL.Path[1:], page.Next()))
  61. }
  62. if !page.IsLast() {
  63. links = append(links, fmt.Sprintf("<%s%s?page=%d>; rel=\"last\"", setting.AppURL, c.Req.URL.Path[1:], page.TotalPages()))
  64. }
  65. if !page.IsFirst() {
  66. links = append(links, fmt.Sprintf("<%s%s?page=1>; rel=\"first\"", setting.AppURL, c.Req.URL.Path[1:]))
  67. }
  68. if page.HasPrevious() {
  69. links = append(links, fmt.Sprintf("<%s%s?page=%d>; rel=\"prev\"", setting.AppURL, c.Req.URL.Path[1:], page.Previous()))
  70. }
  71. if len(links) > 0 {
  72. c.Header().Set("Link", strings.Join(links, ","))
  73. }
  74. }
  75. func APIContexter() macaron.Handler {
  76. return func(ctx *Context) {
  77. c := &APIContext{
  78. Context: ctx,
  79. }
  80. ctx.Map(c)
  81. }
  82. }