(w http.ResponseWriter, req *http.Request)
| 40 | } |
| 41 | |
| 42 | func (h *HTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { |
| 43 | // validate method |
| 44 | switch req.Method { |
| 45 | case http.MethodGet, http.MethodPost, http.MethodPut, http.MethodDelete: |
| 46 | default: |
| 47 | w.Header().Set("Allow", "GET, POST, PUT, DELETE") |
| 48 | http.Error(w, "unsupported method", http.StatusMethodNotAllowed) |
| 49 | return |
| 50 | } |
| 51 | // parse request |
| 52 | values := httputil.ParseRequest(req) |
| 53 | // require "secret" (any string is valid) |
| 54 | secret, err := values.GetString("secret") |
| 55 | if len(secret) == 0 || err != nil { |
| 56 | switch { |
| 57 | case err == nil: |
| 58 | http.Error(w, "must specify \"secret\"", http.StatusBadRequest) |
| 59 | case errors.Is(err, httputil.ErrAmbiguousValues): |
| 60 | http.Error(w, "multiple values found for \"secret\"", http.StatusBadRequest) |
| 61 | case errors.Is(err, httputil.ErrValueUnexpectedType): |
| 62 | http.Error(w, "\"secret\" must be a string", http.StatusBadRequest) |
| 63 | default: |
| 64 | log.Printf("[error] challenges.HTTPHandler.ServeHTTP: get secret: %v", err) |
| 65 | http.Error(w, "server error", http.StatusInternalServerError) |
| 66 | } |
| 67 | return |
| 68 | } |
| 69 | // get "txt" |
| 70 | txt, err := values.GetString("txt") |
| 71 | if err != nil { |
| 72 | switch { |
| 73 | case errors.Is(err, httputil.ErrAmbiguousValues): |
| 74 | http.Error(w, "multiple values found for \"txt\"", http.StatusBadRequest) |
| 75 | case errors.Is(err, httputil.ErrValueUnexpectedType): |
| 76 | http.Error(w, "\"txt\" must be a string", http.StatusBadRequest) |
| 77 | default: |
| 78 | log.Printf("[error] challenges.HTTPHandler.ServeHTTP: get txt: %v", err) |
| 79 | http.Error(w, "server error", http.StatusInternalServerError) |
| 80 | } |
| 81 | return |
| 82 | } |
| 83 | // make sure "txt" is a valid challenge string |
| 84 | if len(txt) > 0 && !IsValidChallenge(txt) { |
| 85 | http.Error(w, "invalid value for \"txt\"", http.StatusBadRequest) |
| 86 | return |
| 87 | } |
| 88 | // try to use the entire body as the "txt" value if not found |
| 89 | // warning: could contain form values (i.e., "secret=..."), do not allow '=' in "txt" values |
| 90 | if len(txt) == 0 && req.Method != http.MethodGet { |
| 91 | if bodyText, _ := values.BodyText(); IsValidChallenge(bodyText) { |
| 92 | txt = bodyText |
| 93 | } |
| 94 | } |
| 95 | // calculate domain |
| 96 | domain := fmt.Sprintf("%x.%s", sha256.Sum224([]byte(secret)), h.Zone) |
| 97 | switch req.Method { |
| 98 | case http.MethodDelete: |
| 99 | // require "txt" |
nothing calls this directly
no test coverage detected