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  }