code.vegaprotocol.io/vega@v0.79.0/wallet/service/v2/response_writer.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package v2 17 18 import ( 19 "encoding/json" 20 "net/http" 21 22 "code.vegaprotocol.io/vega/libs/jsonrpc" 23 ) 24 25 // responseWriter is a wrapper used to easily track response information written 26 // to the HTTP response writer, without polluting the handler's code. 27 type responseWriter struct { 28 writer http.ResponseWriter 29 // traceID holds a unique identifier of the incoming request. It's used to 30 // trace everything related to that request. It's used on a "technical" 31 // level for tracing the request through multiple components, and services. 32 // It shouldn't be confused with the requestID that is an optional 33 // identifier set by the client. 34 traceID string 35 // statusCode holds the latest status code set on the writer. 36 statusCode int 37 // internalError holds the error that came up during processing of the 38 // request or the response. 39 internalError error 40 // response holds the body of the response. 41 response []byte 42 // requestID is the identifier the client set in the request. It's used by 43 // the client to track its requests. This identifier can be empty. It 44 // shouldn't be confused with the traceID. 45 requestID string 46 } 47 48 func (lw *responseWriter) SetStatusCode(statusCode int) { 49 lw.statusCode = statusCode 50 lw.writer.WriteHeader(statusCode) 51 if lw.statusCode == 401 { 52 lw.writer.Header().Set("WWW-Authenticate", "VWT") 53 } 54 } 55 56 func (lw *responseWriter) SetAuthorization(vwt VWT) { 57 lw.writer.Header().Set("Authorization", vwt.String()) 58 lw.writer.Header().Set("Access-Control-Allow-Headers", "Authorization") 59 lw.writer.Header().Set("Access-Control-Expose-Headers", "Authorization") 60 } 61 62 func (lw *responseWriter) WriteHTTPResponse(response *Response) { 63 lw.writer.Header().Set("Content-Type", "application/json") 64 65 marshaledResponse, err := json.Marshal(response) 66 if err != nil { 67 lw.SetStatusCode(http.StatusInternalServerError) 68 lw.response = nil 69 lw.internalError = err 70 return 71 } 72 73 if _, err = lw.writer.Write(marshaledResponse); err != nil { 74 lw.SetStatusCode(http.StatusInternalServerError) 75 lw.response = nil 76 lw.internalError = err 77 return 78 } 79 } 80 81 func (lw *responseWriter) WriteJSONRPCResponse(response *jsonrpc.Response) { 82 lw.requestID = response.ID 83 84 lw.writer.Header().Set("Content-Type", "application/json-rpc") 85 86 marshaledResponse, err := json.Marshal(response) 87 if err != nil { 88 lw.SetStatusCode(http.StatusInternalServerError) 89 lw.response = nil 90 lw.internalError = err 91 return 92 } 93 94 if _, err = lw.writer.Write(marshaledResponse); err != nil { 95 lw.SetStatusCode(http.StatusInternalServerError) 96 lw.response = nil 97 lw.internalError = err 98 return 99 } 100 } 101 102 func newResponseWriter(writer http.ResponseWriter, traceID string) *responseWriter { 103 writer.Header().Set("Content-Type", "application/json") 104 105 return &responseWriter{ 106 writer: writer, 107 traceID: traceID, 108 } 109 }