Compare commits
2 Commits
09c36a87b3
...
6077c54d22
Author | SHA1 | Date |
---|---|---|
|
6077c54d22 | |
|
eaf3e1d5a7 |
|
@ -24,6 +24,7 @@ message HttpRequest { // HttpRequest repre
|
||||||
int64 clientDataLen = 12; // len(body)
|
int64 clientDataLen = 12; // len(body)
|
||||||
bytes serverData = 13; // the server response
|
bytes serverData = 13; // the server response
|
||||||
int64 serverDataLen = 14; // len(data)
|
int64 serverDataLen = 14; // len(data)
|
||||||
|
repeated string log = 15; // use this to store whatever you want while the whole POST happens
|
||||||
}
|
}
|
||||||
|
|
||||||
message HttpRequests { // `autogenpb:marshal` `autogenpb:mutex`
|
message HttpRequests { // `autogenpb:marshal` `autogenpb:mutex`
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
package httppb
|
||||||
|
|
||||||
|
// http middleware example. probably not interesting since we only pass protobufs
|
||||||
|
// middleware concepts might, or might not be useful here
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Define a key type to avoid context key collisions.
|
||||||
|
type contextKey string
|
||||||
|
|
||||||
|
const bufferedBodyKey = contextKey("bufferedBody")
|
||||||
|
|
||||||
|
// bufferBodyMiddleware reads the request body and replaces it with a new reader,
|
||||||
|
// allowing it to be read multiple times. The original body is stored in the request context.
|
||||||
|
func bufferBodyMiddleware(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// Only buffer if there's a body to read.
|
||||||
|
if r.Body == nil || r.ContentLength == 0 {
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyBytes, err := ioutil.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error reading body in middleware: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer r.Body.Close()
|
||||||
|
|
||||||
|
// Store the buffered body in the context for downstream handlers.
|
||||||
|
ctx := context.WithValue(r.Context(), bufferedBodyKey, bodyBytes)
|
||||||
|
|
||||||
|
// Replace the original body with a new reader on the buffered bytes.
|
||||||
|
// This allows subsequent handlers to read the body again.
|
||||||
|
r.Body = ioutil.NopCloser(bytes.NewReader(bodyBytes))
|
||||||
|
|
||||||
|
// Call the next handler in the chain with the modified request.
|
||||||
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// okHandler is the final handler. It can now safely access the body from the context,
|
||||||
|
// knowing that other middleware might have also read it.
|
||||||
|
func okHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// For demonstration, we can try reading the body directly here too.
|
||||||
|
// The middleware ensures this is a fresh stream of the buffered data.
|
||||||
|
bodyFromStream, err := ioutil.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error reading body in handler: %v", err)
|
||||||
|
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Handler read %d bytes from the request body stream.", len(bodyFromStream))
|
||||||
|
|
||||||
|
// We can also retrieve the body from the context if needed.
|
||||||
|
bodyFromContext, ok := r.Context().Value(bufferedBodyKey).([]byte)
|
||||||
|
if !ok {
|
||||||
|
log.Println("Could not retrieve buffered body from context.")
|
||||||
|
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Handler retrieved %d bytes from context.", len(bodyFromContext))
|
||||||
|
|
||||||
|
// Prove they are the same.
|
||||||
|
if !bytes.Equal(bodyFromStream, bodyFromContext) {
|
||||||
|
log.Println("FATAL: Body from stream and context do not match!")
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(w, "Successfully read body of %d bytes.\n", len(bodyFromContext))
|
||||||
|
}
|
||||||
|
*/
|
Loading…
Reference in New Issue