Created
July 4, 2016 21:45
-
-
Save a-h/1e808eff8bf795130bb656cbeb9a4db0 to your computer and use it in GitHub Desktop.
Middleware to Hash a HTTP Request
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package sign | |
| import ( | |
| "bytes" | |
| "crypto/sha256" | |
| "encoding/hex" | |
| "io/ioutil" | |
| "net/http" | |
| "net/http/httptest" | |
| ) | |
| // Handler is the http.Handler implementation for the Signature Handler. | |
| type Handler struct { | |
| next http.Handler | |
| saltExtractor func(body string) (salt string) | |
| } | |
| // NewHandler creates a HTTP handler which receives the request and wraps the next handler. | |
| // The output is modified to include a signature header. | |
| func NewHandler(extraData string, next http.Handler) *Handler { | |
| return &Handler{ | |
| next: next, | |
| saltExtractor: defaultSaltExtractor, | |
| } | |
| } | |
| func defaultSaltExtractor(body string) string { | |
| return body | |
| } | |
| func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) { | |
| // Read the body in. | |
| buf, _ := ioutil.ReadAll(req.Body) | |
| body := string(buf) | |
| salt := h.saltExtractor(body) | |
| // Set the body again for the next handler. | |
| req.Body = ioutil.NopCloser(bytes.NewBuffer(buf)) | |
| //TODO: Read the request and pull out the signature source id from the header or JSON body. | |
| // Record the response. | |
| // Based on https://justinas.org/writing-http-middleware-in-go/ | |
| rec := httptest.NewRecorder() | |
| h.next.ServeHTTP(rec, req) | |
| // Copy the response from the recording, with the modifications. | |
| for k, v := range rec.Header() { | |
| w.Header()[k] = v | |
| } | |
| // Add the hash of the response body. | |
| //TODO: Turn this into a signature of the salt + body. | |
| hash := calculateHash(rec.Body.Bytes(), []byte(salt)) | |
| w.Header().Set("X-Hash", hash) | |
| // Then the status code, as this call writes out the headers | |
| w.WriteHeader(rec.Code) | |
| // Write out the original body. | |
| w.Write(rec.Body.Bytes()) | |
| } | |
| func calculateHash(body []byte, salt []byte) string { | |
| combined := append(body, salt...) | |
| hash := sha256.Sum256(combined) | |
| return hex.EncodeToString(hash[:]) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "net/http" | |
| "github.com/a-h/gosign/sign" | |
| "github.com/gorilla/mux" | |
| ) | |
| func main() { | |
| r := mux.NewRouter() | |
| handler := &testHandler{} | |
| signer := sign.NewHandler("test", handler) | |
| r.Handle("/", signer) | |
| http.ListenAndServe(":8080", r) | |
| } | |
| type testHandler struct { | |
| } | |
| func (th *testHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { | |
| w.Write([]byte("This is a catch-all route")) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment