github.com/aacfactory/fns@v1.2.86-0.20240310083819-80d667fc0a17/transports/standard/adaptor.go (about) 1 /* 2 * Copyright 2023 Wang Min Xiang 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 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 18 package standard 19 20 import ( 21 "github.com/aacfactory/fns/commons/bytex" 22 "github.com/aacfactory/fns/context" 23 "github.com/aacfactory/fns/transports" 24 "net/http" 25 "sync" 26 "time" 27 ) 28 29 var ( 30 requestPool = sync.Pool{} 31 responsePool = sync.Pool{} 32 ) 33 34 func HttpTransportHandlerAdaptor(h transports.Handler, maxRequestBody int, writeTimeout time.Duration) http.Handler { 35 return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { 36 ctx := context.Acquire(request.Context()) 37 38 var r *Request 39 cr := requestPool.Get() 40 if cr == nil { 41 r = new(Request) 42 } else { 43 r = cr.(*Request) 44 } 45 r.Context = ctx 46 r.maxBodySize = maxRequestBody 47 r.request = request 48 49 var w *ResponseWriter 50 cw := responsePool.Get() 51 if cw == nil { 52 w = new(ResponseWriter) 53 } else { 54 w = cw.(*ResponseWriter) 55 } 56 w.Context = ctx 57 w.writer = writer 58 w.header = WrapHttpHeader(writer.Header()) 59 w.result = transports.AcquireResultResponseWriter(writeTimeout, r.Header().Get(transports.ContentTypeHeaderName)) 60 61 h.Handle(w, r) 62 w.result.Header().Foreach(func(key []byte, values [][]byte) { 63 for _, value := range values { 64 writer.Header().Add(bytex.ToString(key), bytex.ToString(value)) 65 } 66 }) 67 writer.WriteHeader(w.Status()) 68 if bodyLen := w.BodyLen(); bodyLen > 0 { 69 body := w.Body() 70 n := 0 71 for n < bodyLen { 72 nn, writeErr := writer.Write(body[n:]) 73 if writeErr != nil { 74 break 75 } 76 n += nn 77 } 78 } 79 80 if !w.Hijacked() { 81 transports.ReleaseResultResponseWriter(w.result) 82 w.Context = nil 83 w.writer = nil 84 w.header = nil 85 w.result = nil 86 w.hijacked = false 87 responsePool.Put(w) 88 89 r.Context = nil 90 r.maxBodySize = 0 91 r.request = nil 92 requestPool.Put(r) 93 94 context.Release(ctx) 95 } 96 97 }) 98 }