github.com/waltonchain/waltonchain_gwtc_src@v1.1.4-0.20201225072101-8a298c95a819/swarm/api/http/error.go (about)

     1  // Copyright 2017 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-wtc library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-wtc library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  /*
    18  Show nicely (but simple) formatted HTML error pages (or respond with JSON
    19  if the appropriate `Accept` header is set)) for the http package.
    20  */
    21  package http
    22  
    23  import (
    24  	"encoding/json"
    25  	"fmt"
    26  	"html/template"
    27  	"net/http"
    28  	"time"
    29  
    30  	"github.com/wtc/go-wtc/log"
    31  )
    32  
    33  //templateMap holds a mapping of an HTTP error code to a template
    34  var templateMap map[int]*template.Template
    35  
    36  //parameters needed for formatting the correct HTML page
    37  type ErrorParams struct {
    38  	Msg       string
    39  	Code      int
    40  	Timestamp string
    41  	template  *template.Template
    42  	Details   template.HTML
    43  }
    44  
    45  //we init the error handling right on boot time, so lookup and http response is fast
    46  func init() {
    47  	initErrHandling()
    48  }
    49  
    50  func initErrHandling() {
    51  	//pages are saved as strings - get these strings
    52  	genErrPage := GetGenericErrorPage()
    53  	notFoundPage := GetNotFoundErrorPage()
    54  	//map the codes to the available pages
    55  	tnames := map[int]string{
    56  		0:   genErrPage, //default
    57  		400: genErrPage,
    58  		404: notFoundPage,
    59  		500: genErrPage,
    60  	}
    61  	templateMap = make(map[int]*template.Template)
    62  	for code, tname := range tnames {
    63  		//assign formatted HTML to the code
    64  		templateMap[code] = template.Must(template.New(fmt.Sprintf("%d", code)).Parse(tname))
    65  	}
    66  }
    67  
    68  //ShowError is used to show an HTML error page to a client.
    69  //If there is an `Accept` header of `application/json`, JSON will be returned instead
    70  //The function just takes a string message which will be displayed in the error page.
    71  //The code is used to evaluate which template will be displayed
    72  //(and return the correct HTTP status code)
    73  func ShowError(w http.ResponseWriter, r *http.Request, msg string, code int) {
    74  	if code == http.StatusInternalServerError {
    75  		log.Error(msg)
    76  	}
    77  	respond(w, r, &ErrorParams{
    78  		Code:      code,
    79  		Msg:       msg,
    80  		Timestamp: time.Now().Format(time.RFC1123),
    81  		template:  getTemplate(code),
    82  	})
    83  }
    84  
    85  //evaluate if client accepts html or json response
    86  func respond(w http.ResponseWriter, r *http.Request, params *ErrorParams) {
    87  	w.WriteHeader(params.Code)
    88  	if r.Header.Get("Accept") == "application/json" {
    89  		respondJson(w, params)
    90  	} else {
    91  		respondHtml(w, params)
    92  	}
    93  }
    94  
    95  //return a HTML page
    96  func respondHtml(w http.ResponseWriter, params *ErrorParams) {
    97  	err := params.template.Execute(w, params)
    98  	if err != nil {
    99  		log.Error(err.Error())
   100  	}
   101  }
   102  
   103  //return JSON
   104  func respondJson(w http.ResponseWriter, params *ErrorParams) {
   105  	w.Header().Set("Content-Type", "application/json")
   106  	json.NewEncoder(w).Encode(params)
   107  }
   108  
   109  //get the HTML template for a given code
   110  func getTemplate(code int) *template.Template {
   111  	if val, tmpl := templateMap[code]; tmpl {
   112  		return val
   113  	} else {
   114  		return templateMap[0]
   115  	}
   116  }