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  }