Capstan is a Golang web framework that shares some similarities with others in its segment.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

91 lines
2.5KB

  1. // Private function bindings to Router.
  2. //
  3. // Note: math/rand is imported here and is used for avoiding naming collisions
  4. // on URLFor names generated using route names.
  5. package capstan
  6. import (
  7. "math/rand"
  8. "os"
  9. "path/filepath"
  10. "reflect"
  11. "strconv"
  12. "time"
  13. )
  14. // Housekeeping initialization such as PID file generation (if enabled).
  15. func (r *Router) init() {
  16. pidfile := r.app.Config().PIDFile
  17. if pidfile == "" {
  18. return
  19. }
  20. cwd, err := os.Getwd()
  21. if err != nil {
  22. r.app.Logger().Warning("unable to read current directory:", err)
  23. return
  24. }
  25. pidfile = filepath.Join(cwd, pidfile)
  26. fp, err := os.OpenFile(pidfile, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0644))
  27. if err != nil {
  28. r.app.Logger().Warning("PIDFile specified but cannot be written:", err)
  29. return
  30. }
  31. defer fp.Close()
  32. if _, err = fp.Write([]byte(strconv.Itoa(os.Getpid()))); err != nil {
  33. r.app.Logger().Warning("cannot write PID:", err)
  34. }
  35. }
  36. func (r *Router) toRoute(controller Controller) (*Route, *routeProps) {
  37. props := r.ParseRoute(controller.path())
  38. route := &Route{
  39. router: r,
  40. Prefix: controller.prefix(),
  41. Path: props.route,
  42. CapPath: controller.path(),
  43. BasePath: r.basePath, // TODO: Support CapBasePath.
  44. MandatoryNoSlash: props.mandatoryNoSlash,
  45. MandatorySlash: props.mandatorySlash,
  46. OptionalSlash: props.optionalSlash,
  47. SlashIsDefault: props.slashIsDefault,
  48. ParamTypes: props.params,
  49. Middleware: controller.middleware(),
  50. Controller: controller,
  51. Renderer: controller.renderer(),
  52. AfterResponse: make([]func(Context, error) error, len(r.afterResponse)),
  53. BeforeResponse: make([]func(Context, *Route) error, len(r.beforeResponse)),
  54. }
  55. // Set route name based on either the controller, as provided, or the
  56. // underlying type name (via reflection).
  57. route.Name = controller.name()
  58. if route.Name == "" {
  59. route.Name = reflect.Indirect(reflect.ValueOf(controller)).Type().Name()
  60. }
  61. name := route.Name
  62. for _, ok := r.cnames[route.Name]; ok; _, ok = r.cnames[route.Name] {
  63. d := len(route.Name) - len(name)
  64. if d == 0 {
  65. route.Name = route.Name + "1"
  66. continue
  67. }
  68. if v, err := strconv.Atoi(route.Name[len(route.Name)-d:]); err == nil {
  69. route.Name = name + strconv.Itoa(v+1)
  70. } else {
  71. rand := rand.New(rand.NewSource(time.Now().Unix()))
  72. route.Name = route.Name + strconv.Itoa(rand.Int())
  73. }
  74. }
  75. copy(route.AfterResponse, r.afterResponse)
  76. copy(route.BeforeResponse, r.beforeResponse)
  77. return route, props
  78. }