github.com/gramework/gramework@v1.8.1-0.20231027140105-82555c9057f5/subroute.go (about) 1 // Copyright 2017-present Kirill Danshin and Gramework contributors 2 // Copyright 2019-present Highload LTD (UK CN: 11893420) 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 11 package gramework 12 13 import ( 14 "fmt" 15 ) 16 17 // GET registers a handler for a GET request to the given route 18 func (r *SubRouter) GET(route string, handler interface{}) *SubRouter { 19 route = r.prefixedRoute(route) 20 if r.parent != nil { 21 r.parent.handleReg(MethodGET, route, handler, r.prefixes) 22 } 23 return r 24 } 25 26 func (r *SubRouter) determineHandler(handler interface{}) func(*Context) { 27 return r.parent.determineHandler(handler) 28 } 29 30 // JSON register internal handler that sets json content type 31 // and serves given handler with GET method 32 func (r *SubRouter) JSON(route string, handler interface{}) *SubRouter { 33 route = r.prefixedRoute(route) 34 if r.parent != nil { 35 h := r.parent.determineHandler(handler) 36 r.parent.handleReg(MethodGET, route, jsonHandler(h), r.prefixes) 37 } 38 39 return r 40 } 41 42 // DELETE registers a handler for a DELETE request to the given route 43 func (r *SubRouter) DELETE(route string, handler interface{}) *SubRouter { 44 route = r.prefixedRoute(route) 45 if r.parent != nil { 46 r.parent.handleReg(MethodDELETE, route, handler, r.prefixes) 47 } 48 49 return r 50 } 51 52 // HEAD registers a handler for a HEAD request to the given route 53 func (r *SubRouter) HEAD(route string, handler interface{}) *SubRouter { 54 route = r.prefixedRoute(route) 55 if r.parent != nil { 56 r.parent.handleReg(MethodHEAD, route, handler, r.prefixes) 57 } 58 59 return r 60 } 61 62 // ServeFile serves a file on a given route 63 func (r *SubRouter) ServeFile(route, file string) *SubRouter { 64 route = r.prefixedRoute(route) 65 r.parent.handleReg(MethodGET, route, func(ctx *Context) { 66 ctx.SendFile(file) 67 }, r.prefixes) 68 69 return r 70 } 71 72 // OPTIONS registers a handler for a OPTIONS request to the given route 73 func (r *SubRouter) OPTIONS(route string, handler interface{}) *SubRouter { 74 route = r.prefixedRoute(route) 75 if r.parent != nil { 76 r.parent.handleReg(MethodOPTIONS, route, handler, r.prefixes) 77 } 78 79 return r 80 } 81 82 // PUT registers a handler for a PUT request to the given route 83 func (r *SubRouter) PUT(route string, handler interface{}) *SubRouter { 84 route = r.prefixedRoute(route) 85 if r.parent != nil { 86 r.parent.handleReg(MethodPUT, route, handler, r.prefixes) 87 } 88 89 return r 90 } 91 92 // POST registers a handler for a POST request to the given route 93 func (r *SubRouter) POST(route string, handler interface{}) *SubRouter { 94 route = r.prefixedRoute(route) 95 if r.parent != nil { 96 r.parent.handleReg(MethodPOST, route, handler, r.prefixes) 97 } 98 99 return r 100 } 101 102 // PATCH registers a handler for a PATCH request to the given route 103 func (r *SubRouter) PATCH(route string, handler interface{}) *SubRouter { 104 route = r.prefixedRoute(route) 105 if r.parent != nil { 106 r.parent.handleReg(MethodPATCH, route, handler, r.prefixes) 107 } 108 109 return r 110 } 111 112 // Handle registers a new request handle with the given path and method. 113 // For GET, POST, PUT, PATCH and DELETE requests the respective shortcut functions can be used. 114 // This function is intended for bulk loading and to allow the usage of less frequently used, 115 // non-standardized or custom methods (e.g. for internal communication with a proxy). 116 func (r *SubRouter) Handle(method, route string, handler interface{}) *SubRouter { 117 route = r.prefixedRoute(route) 118 if r.parent != nil { 119 r.parent.handleReg(method, route, handler, r.prefixes) 120 } 121 return r 122 } 123 124 func (r *SubRouter) handleReg(method, route string, handler interface{}, prefixes []string) { 125 r.parent.handleReg(method, route, handler, prefixes) 126 } 127 128 // Sub let you quickly register subroutes with given prefix 129 // like app.Sub("v1").Sub("users").GET("view/:id", "hi").DELETE("delete/:id", "hi"), 130 // that give you /v1/users/view/:id and /v1/users/delete/:id registered 131 func (r *SubRouter) Sub(path string) *SubRouter { 132 return &SubRouter{ 133 parent: r, 134 prefix: r.prefixedRoute(path), 135 prefixes: append(r.prefixes, path), 136 } 137 } 138 139 func (r *SubRouter) prefixedRoute(route string) string { 140 if len(r.prefix) > 0 && r.prefix[len(r.prefix)-1] != '/' && route[0] != '/' { 141 return fmt.Sprintf("%s/%s", r.prefix, route) 142 } 143 144 return fmt.Sprintf("%s%s", r.prefix, route) 145 } 146 147 // HTTP returns SubRouter for http requests with given r.prefix 148 func (r *SubRouter) HTTP() *SubRouter { 149 switch parent := r.parent.(type) { 150 case *SubRouter: 151 return parent.HTTP() 152 case *Router: 153 return &SubRouter{ 154 parent: parent, 155 prefix: r.prefix, 156 } 157 default: 158 Errorf("[HIGH SEVERITY BUG]: unreachable case found! Expected *SubRouter or *Router, got %T! Returning nil!", parent) 159 Errorf("Please report the bug on https://github.com/gramework/gramework ASAP!") 160 return nil 161 } 162 } 163 164 // HTTPS returns SubRouter for https requests with given r.prefix 165 func (r *SubRouter) HTTPS() *SubRouter { 166 switch parent := r.parent.(type) { 167 case *SubRouter: 168 return parent.HTTPS() 169 case *Router: 170 return &SubRouter{ 171 parent: parent, 172 prefix: r.prefix, 173 } 174 default: 175 Errorf("[HIGH SEVERITY BUG]: unreachable case found! Expected *SubRouter or *Router, got %T! Returning nil!", parent) 176 Errorf("Please report the bug on https://github.com/gramework/gramework ASAP!") 177 return nil 178 } 179 } 180 181 // ToTLSHandler returns handler that redirects user to HTTP scheme 182 func (r *SubRouter) ToTLSHandler() func(*Context) { 183 return func(ctx *Context) { 184 ctx.ToTLS() 185 } 186 } 187 188 // Forbidden is a shortcut for ctx.Forbidden 189 func (r *SubRouter) Forbidden(ctx *Context) { 190 ctx.Forbidden() 191 } 192 193 // Redir sends 301 redirect to the given url 194 // 195 // it's equivalent to 196 // 197 // ctx.Redirect(url, 301) 198 func (r *SubRouter) Redir(route, url string) { 199 r.GET(route, func(ctx *Context) { 200 ctx.Redirect(route, redirectCode) 201 }) 202 }