github.com/ethersphere/bee/v2@v2.2.0/pkg/jsonhttp/jsonhttp.go (about)

     1  // Copyright 2020 The Swarm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Most of the code is copied from package resenje.org/jsonresponse.
     6  
     7  // Package jsonhttp provides convenience methods to
     8  // provide better JSON HTTP APIs.
     9  package jsonhttp
    10  
    11  import (
    12  	"bytes"
    13  	"encoding/json"
    14  	"fmt"
    15  	"net/http"
    16  )
    17  
    18  var (
    19  	// DefaultContentTypeHeader is the value of if "Content-Type" header
    20  	// in HTTP response.
    21  	DefaultContentTypeHeader = "application/json; charset=utf-8"
    22  	// EscapeHTML specifies whether problematic HTML characters
    23  	// should be escaped inside JSON quoted strings.
    24  	EscapeHTML = false
    25  )
    26  
    27  // Reason represents a reason for an invalid request entry.
    28  type Reason struct {
    29  	Field string `json:"field"`
    30  	Error string `json:"error"`
    31  }
    32  
    33  // StatusResponse is a standardized error format for specific HTTP responses.
    34  // Code field corresponds with HTTP status code, and Message field is a short
    35  // description of that code or provides more context about the reason for such
    36  // response.
    37  //
    38  // If response is string, error or Stringer type the string will be set as
    39  // value to the Message field.
    40  type StatusResponse struct {
    41  	Code    int      `json:"code,omitempty"`
    42  	Message string   `json:"message,omitempty"`
    43  	Reasons []Reason `json:"reasons,omitempty"`
    44  }
    45  
    46  // Respond writes a JSON-encoded body to http.ResponseWriter.
    47  func Respond(w http.ResponseWriter, statusCode int, response interface{}) {
    48  	if statusCode == 0 {
    49  		statusCode = http.StatusOK
    50  	}
    51  	if response == nil {
    52  		response = &StatusResponse{
    53  			Message: http.StatusText(statusCode),
    54  			Code:    statusCode,
    55  		}
    56  	} else {
    57  		switch message := response.(type) {
    58  		case string:
    59  			response = &StatusResponse{
    60  				Message: message,
    61  				Code:    statusCode,
    62  			}
    63  		case error:
    64  			response = &StatusResponse{
    65  				Message: message.Error(),
    66  				Code:    statusCode,
    67  			}
    68  		case interface {
    69  			String() string
    70  		}:
    71  			response = &StatusResponse{
    72  				Message: message.String(),
    73  				Code:    statusCode,
    74  			}
    75  		}
    76  	}
    77  	var b bytes.Buffer
    78  	enc := json.NewEncoder(&b)
    79  	enc.SetEscapeHTML(EscapeHTML)
    80  	if err := enc.Encode(response); err != nil {
    81  		panic(err)
    82  	}
    83  	if DefaultContentTypeHeader != "" {
    84  		w.Header().Set("Content-Type", DefaultContentTypeHeader)
    85  	}
    86  	w.WriteHeader(statusCode)
    87  	fmt.Fprintln(w, b.String())
    88  }
    89  
    90  // Continue writes a response with status code 100.
    91  func Continue(w http.ResponseWriter, response interface{}) {
    92  	Respond(w, http.StatusContinue, response)
    93  }
    94  
    95  // SwitchingProtocols writes a response with status code 101.
    96  func SwitchingProtocols(w http.ResponseWriter, response interface{}) {
    97  	Respond(w, http.StatusSwitchingProtocols, response)
    98  }
    99  
   100  // OK writes a response with status code 200.
   101  func OK(w http.ResponseWriter, response interface{}) {
   102  	Respond(w, http.StatusOK, response)
   103  }
   104  
   105  // Created writes a response with status code 201.
   106  func Created(w http.ResponseWriter, response interface{}) {
   107  	Respond(w, http.StatusCreated, response)
   108  }
   109  
   110  // Accepted writes a response with status code 202.
   111  func Accepted(w http.ResponseWriter, response interface{}) {
   112  	Respond(w, http.StatusAccepted, response)
   113  }
   114  
   115  // NonAuthoritativeInfo writes a response with status code 203.
   116  func NonAuthoritativeInfo(w http.ResponseWriter, response interface{}) {
   117  	Respond(w, http.StatusNonAuthoritativeInfo, response)
   118  }
   119  
   120  // NoContent writes a response with status code 204. It does not
   121  // accept a response value since the HTTP server will not write it
   122  // to the client when returning a NoContent response.
   123  func NoContent(w http.ResponseWriter) {
   124  	Respond(w, http.StatusNoContent, nil)
   125  }
   126  
   127  // ResetContent writes a response with status code 205.
   128  func ResetContent(w http.ResponseWriter, response interface{}) {
   129  	Respond(w, http.StatusResetContent, response)
   130  }
   131  
   132  // PartialContent writes a response with status code 206.
   133  func PartialContent(w http.ResponseWriter, response interface{}) {
   134  	Respond(w, http.StatusPartialContent, response)
   135  }
   136  
   137  // MultipleChoices writes a response with status code 300.
   138  func MultipleChoices(w http.ResponseWriter, response interface{}) {
   139  	Respond(w, http.StatusMultipleChoices, response)
   140  }
   141  
   142  // MovedPermanently writes a response with status code 301.
   143  func MovedPermanently(w http.ResponseWriter, response interface{}) {
   144  	Respond(w, http.StatusMovedPermanently, response)
   145  }
   146  
   147  // Found writes a response with status code 302.
   148  func Found(w http.ResponseWriter, response interface{}) {
   149  	Respond(w, http.StatusFound, response)
   150  }
   151  
   152  // SeeOther writes a response with status code 303.
   153  func SeeOther(w http.ResponseWriter, response interface{}) {
   154  	Respond(w, http.StatusSeeOther, response)
   155  }
   156  
   157  // NotModified writes a response with status code 304.
   158  func NotModified(w http.ResponseWriter, response interface{}) {
   159  	Respond(w, http.StatusNotModified, response)
   160  }
   161  
   162  // UseProxy writes a response with status code 305.
   163  func UseProxy(w http.ResponseWriter, response interface{}) {
   164  	Respond(w, http.StatusUseProxy, response)
   165  }
   166  
   167  // TemporaryRedirect writes a response with status code 307.
   168  func TemporaryRedirect(w http.ResponseWriter, response interface{}) {
   169  	Respond(w, http.StatusTemporaryRedirect, response)
   170  }
   171  
   172  // PermanentRedirect writes a response with status code 308.
   173  func PermanentRedirect(w http.ResponseWriter, response interface{}) {
   174  	Respond(w, http.StatusPermanentRedirect, response)
   175  }
   176  
   177  // BadRequest writes a response with status code 400.
   178  func BadRequest(w http.ResponseWriter, response interface{}) {
   179  	Respond(w, http.StatusBadRequest, response)
   180  }
   181  
   182  // Unauthorized writes a response with status code 401.
   183  func Unauthorized(w http.ResponseWriter, response interface{}) {
   184  	Respond(w, http.StatusUnauthorized, response)
   185  }
   186  
   187  // PaymentRequired writes a response with status code 402.
   188  func PaymentRequired(w http.ResponseWriter, response interface{}) {
   189  	Respond(w, http.StatusPaymentRequired, response)
   190  }
   191  
   192  // Forbidden writes a response with status code 403.
   193  func Forbidden(w http.ResponseWriter, response interface{}) {
   194  	Respond(w, http.StatusForbidden, response)
   195  }
   196  
   197  // NotFound writes a response with status code 404.
   198  func NotFound(w http.ResponseWriter, response interface{}) {
   199  	Respond(w, http.StatusNotFound, response)
   200  }
   201  
   202  // MethodNotAllowed writes a response with status code 405.
   203  func MethodNotAllowed(w http.ResponseWriter, response interface{}) {
   204  	Respond(w, http.StatusMethodNotAllowed, response)
   205  }
   206  
   207  // NotAcceptable writes a response with status code 406.
   208  func NotAcceptable(w http.ResponseWriter, response interface{}) {
   209  	Respond(w, http.StatusNotAcceptable, response)
   210  }
   211  
   212  // ProxyAuthRequired writes a response with status code 407.
   213  func ProxyAuthRequired(w http.ResponseWriter, response interface{}) {
   214  	Respond(w, http.StatusProxyAuthRequired, response)
   215  }
   216  
   217  // RequestTimeout writes a response with status code 408.
   218  func RequestTimeout(w http.ResponseWriter, response interface{}) {
   219  	Respond(w, http.StatusRequestTimeout, response)
   220  }
   221  
   222  // Conflict writes a response with status code 409.
   223  func Conflict(w http.ResponseWriter, response interface{}) {
   224  	Respond(w, http.StatusConflict, response)
   225  }
   226  
   227  // Gone writes a response with status code 410.
   228  func Gone(w http.ResponseWriter, response interface{}) {
   229  	Respond(w, http.StatusGone, response)
   230  }
   231  
   232  // LengthRequired writes a response with status code 411.
   233  func LengthRequired(w http.ResponseWriter, response interface{}) {
   234  	Respond(w, http.StatusLengthRequired, response)
   235  }
   236  
   237  // PreconditionFailed writes a response with status code 412.
   238  func PreconditionFailed(w http.ResponseWriter, response interface{}) {
   239  	Respond(w, http.StatusPreconditionFailed, response)
   240  }
   241  
   242  // RequestEntityTooLarge writes a response with status code 413.
   243  func RequestEntityTooLarge(w http.ResponseWriter, response interface{}) {
   244  	Respond(w, http.StatusRequestEntityTooLarge, response)
   245  }
   246  
   247  // RequestURITooLong writes a response with status code 414.
   248  func RequestURITooLong(w http.ResponseWriter, response interface{}) {
   249  	Respond(w, http.StatusRequestURITooLong, response)
   250  }
   251  
   252  // UnsupportedMediaType writes a response with status code 415.
   253  func UnsupportedMediaType(w http.ResponseWriter, response interface{}) {
   254  	Respond(w, http.StatusUnsupportedMediaType, response)
   255  }
   256  
   257  // RequestedRangeNotSatisfiable writes a response with status code 416.
   258  func RequestedRangeNotSatisfiable(w http.ResponseWriter, response interface{}) {
   259  	Respond(w, http.StatusRequestedRangeNotSatisfiable, response)
   260  }
   261  
   262  // ExpectationFailed writes a response with status code 417.
   263  func ExpectationFailed(w http.ResponseWriter, response interface{}) {
   264  	Respond(w, http.StatusExpectationFailed, response)
   265  }
   266  
   267  // Teapot writes a response with status code 418.
   268  func Teapot(w http.ResponseWriter, response interface{}) {
   269  	Respond(w, http.StatusTeapot, response)
   270  }
   271  
   272  // UnprocessableEntity writes a response with status code 422.
   273  func UnprocessableEntity(w http.ResponseWriter, response interface{}) {
   274  	Respond(w, http.StatusUnprocessableEntity, response)
   275  }
   276  
   277  // UpgradeRequired writes a response with status code 426.
   278  func UpgradeRequired(w http.ResponseWriter, response interface{}) {
   279  	Respond(w, http.StatusUpgradeRequired, response)
   280  }
   281  
   282  // PreconditionRequired writes a response with status code 428.
   283  func PreconditionRequired(w http.ResponseWriter, response interface{}) {
   284  	Respond(w, http.StatusPreconditionRequired, response)
   285  }
   286  
   287  // TooManyRequests writes a response with status code 429.
   288  func TooManyRequests(w http.ResponseWriter, response interface{}) {
   289  	Respond(w, http.StatusTooManyRequests, response)
   290  }
   291  
   292  // RequestHeaderFieldsTooLarge writes a response with status code 431.
   293  func RequestHeaderFieldsTooLarge(w http.ResponseWriter, response interface{}) {
   294  	Respond(w, http.StatusRequestHeaderFieldsTooLarge, response)
   295  }
   296  
   297  // UnavailableForLegalReasons writes a response with status code 451.
   298  func UnavailableForLegalReasons(w http.ResponseWriter, response interface{}) {
   299  	Respond(w, http.StatusUnavailableForLegalReasons, response)
   300  }
   301  
   302  // InternalServerError writes a response with status code 500.
   303  func InternalServerError(w http.ResponseWriter, response interface{}) {
   304  	Respond(w, http.StatusInternalServerError, response)
   305  }
   306  
   307  // NotImplemented writes a response with status code 501.
   308  func NotImplemented(w http.ResponseWriter, response interface{}) {
   309  	Respond(w, http.StatusNotImplemented, response)
   310  }
   311  
   312  // BadGateway writes a response with status code 502.
   313  func BadGateway(w http.ResponseWriter, response interface{}) {
   314  	Respond(w, http.StatusBadGateway, response)
   315  }
   316  
   317  // ServiceUnavailable writes a response with status code 503.
   318  func ServiceUnavailable(w http.ResponseWriter, response interface{}) {
   319  	Respond(w, http.StatusServiceUnavailable, response)
   320  }
   321  
   322  // GatewayTimeout writes a response with status code 504.
   323  func GatewayTimeout(w http.ResponseWriter, response interface{}) {
   324  	Respond(w, http.StatusGatewayTimeout, response)
   325  }
   326  
   327  // HTTPVersionNotSupported writes a response with status code 505.
   328  func HTTPVersionNotSupported(w http.ResponseWriter, response interface{}) {
   329  	Respond(w, http.StatusHTTPVersionNotSupported, response)
   330  }