http.go 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. // Copyright 2015 CoreOS, Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package v2http
  15. import (
  16. "errors"
  17. "math"
  18. "net/http"
  19. "strings"
  20. "time"
  21. etcdErr "github.com/coreos/etcd/error"
  22. "github.com/coreos/etcd/etcdserver"
  23. "github.com/coreos/etcd/etcdserver/api/v2http/httptypes"
  24. "github.com/coreos/etcd/etcdserver/auth"
  25. "github.com/coreos/etcd/pkg/logutil"
  26. "github.com/coreos/pkg/capnslog"
  27. )
  28. const (
  29. // time to wait for a Watch request
  30. defaultWatchTimeout = time.Duration(math.MaxInt64)
  31. )
  32. var (
  33. plog = capnslog.NewPackageLogger("github.com/coreos/etcd/etcdserver/api", "v2http")
  34. mlog = logutil.NewMergeLogger(plog)
  35. errClosed = errors.New("v2http: client closed connection")
  36. )
  37. // writeError logs and writes the given Error to the ResponseWriter
  38. // If Error is an etcdErr, it is rendered to the ResponseWriter
  39. // Otherwise, it is assumed to be a StatusInternalServerError
  40. func writeError(w http.ResponseWriter, r *http.Request, err error) {
  41. if err == nil {
  42. return
  43. }
  44. switch e := err.(type) {
  45. case *etcdErr.Error:
  46. e.WriteTo(w)
  47. case *httptypes.HTTPError:
  48. if et := e.WriteTo(w); et != nil {
  49. plog.Debugf("error writing HTTPError (%v) to %s", et, r.RemoteAddr)
  50. }
  51. case auth.Error:
  52. herr := httptypes.NewHTTPError(e.HTTPStatus(), e.Error())
  53. if et := herr.WriteTo(w); et != nil {
  54. plog.Debugf("error writing HTTPError (%v) to %s", et, r.RemoteAddr)
  55. }
  56. default:
  57. switch err {
  58. case etcdserver.ErrTimeoutDueToLeaderFail, etcdserver.ErrTimeoutDueToConnectionLost, etcdserver.ErrNotEnoughStartedMembers:
  59. mlog.MergeError(err)
  60. default:
  61. mlog.MergeErrorf("got unexpected response error (%v)", err)
  62. }
  63. herr := httptypes.NewHTTPError(http.StatusInternalServerError, "Internal Server Error")
  64. if et := herr.WriteTo(w); et != nil {
  65. plog.Debugf("error writing HTTPError (%v) to %s", et, r.RemoteAddr)
  66. }
  67. }
  68. }
  69. // allowMethod verifies that the given method is one of the allowed methods,
  70. // and if not, it writes an error to w. A boolean is returned indicating
  71. // whether or not the method is allowed.
  72. func allowMethod(w http.ResponseWriter, m string, ms ...string) bool {
  73. for _, meth := range ms {
  74. if m == meth {
  75. return true
  76. }
  77. }
  78. w.Header().Set("Allow", strings.Join(ms, ","))
  79. http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
  80. return false
  81. }
  82. func requestLogger(handler http.Handler) http.Handler {
  83. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  84. plog.Debugf("[%s] %s remote:%s", r.Method, r.RequestURI, r.RemoteAddr)
  85. handler.ServeHTTP(w, r)
  86. })
  87. }