trpc.group/trpc-go/trpc-go@v1.0.3/http/service_desc.go (about)

     1  //
     2  //
     3  // Tencent is pleased to support the open source community by making tRPC available.
     4  //
     5  // Copyright (C) 2023 THL A29 Limited, a Tencent company.
     6  // All rights reserved.
     7  //
     8  // If you have downloaded a copy of the tRPC source code from Tencent,
     9  // please note that tRPC source code is licensed under the  Apache 2.0 License,
    10  // A copy of the Apache 2.0 License is included in this file.
    11  //
    12  //
    13  
    14  package http
    15  
    16  import (
    17  	"context"
    18  	"errors"
    19  	"fmt"
    20  	stdhttp "net/http"
    21  
    22  	"trpc.group/trpc-go/trpc-go/server"
    23  )
    24  
    25  // ServiceDesc is descriptor for server.RegisterService.
    26  var ServiceDesc = server.ServiceDesc{
    27  	HandlerType: nil,
    28  }
    29  
    30  // Handle registers http handler with custom route.
    31  func Handle(pattern string, h stdhttp.Handler) {
    32  	handler := func(w stdhttp.ResponseWriter, r *stdhttp.Request) error {
    33  		h.ServeHTTP(w, r)
    34  		return nil
    35  	}
    36  
    37  	ServiceDesc.Methods = append(ServiceDesc.Methods, generateMethod(pattern, handler))
    38  }
    39  
    40  // HandleFunc registers http handler with custom route.
    41  func HandleFunc(pattern string, handler func(w stdhttp.ResponseWriter, r *stdhttp.Request) error) {
    42  	ServiceDesc.Methods = append(ServiceDesc.Methods, generateMethod(pattern, handler))
    43  }
    44  
    45  // RegisterDefaultService registers service.
    46  // See http/README.md for usage details.
    47  // Deprecated: use RegisterNoProtocolService(s.Service("your.stdhttp.service.name")) instead.
    48  func RegisterDefaultService(s server.Service) {
    49  	DefaultServerCodec.AutoReadBody = false
    50  	RegisterNoProtocolService(s)
    51  }
    52  
    53  // RegisterNoProtocolService registers no protocol service.
    54  // See http/README.md for usage details.
    55  func RegisterNoProtocolService(s server.Service) {
    56  	if err := s.Register(&ServiceDesc, nil); err != nil {
    57  		panic(fmt.Sprintf("register http no protocol service fail, err: %+v", err))
    58  	}
    59  }
    60  
    61  // RegisterServiceMux registers service with http standard mux handler.
    62  // Business registers routing plug-in by himself.
    63  // Deprecated: use RegisterNoProtocolServiceMux(s.Service("your.stdhttp.service.name"), mux) instead.
    64  func RegisterServiceMux(s server.Service, mux stdhttp.Handler) {
    65  	DefaultServerCodec.AutoReadBody = false
    66  	RegisterNoProtocolServiceMux(s, mux)
    67  }
    68  
    69  // RegisterNoProtocolServiceMux registers service with http standard mux handler.
    70  // Business registers routing plug-in by himself.
    71  func RegisterNoProtocolServiceMux(s server.Service, mux stdhttp.Handler) {
    72  	handler := func(w stdhttp.ResponseWriter, r *stdhttp.Request) error {
    73  		mux.ServeHTTP(w, r)
    74  		return nil
    75  	}
    76  	method := generateMethod("*", handler)
    77  	var serviceDesc = server.ServiceDesc{
    78  		HandlerType: nil,
    79  		Methods:     []server.Method{method},
    80  	}
    81  	if err := s.Register(&serviceDesc, nil); err != nil {
    82  		panic(fmt.Sprintf("register http no protocol service mux fail, err: %+v", err))
    83  	}
    84  }
    85  
    86  // generateMethod generates server method.
    87  func generateMethod(pattern string, handler func(w stdhttp.ResponseWriter, r *stdhttp.Request) error) server.Method {
    88  	handlerFunc := func(_ interface{}, ctx context.Context, f server.FilterFunc) (rspBody interface{}, err error) {
    89  		filters, err := f(nil)
    90  		if err != nil {
    91  			return nil, err
    92  		}
    93  		handleFunc := func(ctx context.Context, _ interface{}) (rspBody interface{}, err error) {
    94  			head := Head(ctx)
    95  			if head == nil {
    96  				return nil, errors.New("http Handle missing http header in context")
    97  			}
    98  			req := head.Request.WithContext(ctx)
    99  			rsp := head.Response
   100  			err = handler(rsp, req)
   101  			// Fix issues/778
   102  			// Currently, Request.MultipartForm is nil if Request.ParseMultipartForm() is not called.
   103  			// Then head.Request.WithContext cannot carry the corresponding Request.MultipartForm pointer to the user.
   104  			// If the user parses the multipart form data inside the handler, req will have a valid MultipartForm pointer,
   105  			// but this pointer is not going to be reflected in head.Request.
   106  			// Consequence:
   107  			//   The standard http library is unable to remove the temporary files generated by multipart form data.
   108  			//
   109  			// The code below attempts to pass the pointer req.MultipartForm to head.Request.MultipartForm (which is
   110  			// a pointer the standard library code has access to). Thereafter temporary files generated by parsing
   111  			// multipart form data is guaranteed to be deleted.
   112  			if head.Request.MultipartForm == nil {
   113  				head.Request.MultipartForm = req.MultipartForm
   114  			}
   115  			return nil, err
   116  		}
   117  		return filters.Filter(ctx, nil, handleFunc)
   118  	}
   119  	return server.Method{
   120  		Name: pattern,
   121  		Func: handlerFunc,
   122  	}
   123  }