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 }