internal/server/mcphttp/inproc.go
Ref: Size: 1.6 KiB History
package mcphttp
import (
"bytes"
"io"
"net/http"
)
// inproc dispatches a client request into the server's own handler. The caller's
// PAT rides the Authorization header exactly as a remote client's would, so the
// request re-authenticates through the same middleware and lands on the same
// Principal — there is no second authorization path to keep in step with the
// first, and no socket in between.
type inproc struct{ h http.Handler }
func (t inproc) RoundTrip(r *http.Request) (*http.Response, error) {
rec := &recorder{header: http.Header{}, status: http.StatusOK}
t.h.ServeHTTP(rec, r)
resp := &http.Response{
StatusCode: rec.status,
Status: http.StatusText(rec.status),
Header: rec.header,
Body: io.NopCloser(bytes.NewReader(rec.body.Bytes())),
ContentLength: int64(rec.body.Len()),
Request: r,
Proto: "HTTP/1.1",
ProtoMajor: 1,
ProtoMinor: 1,
}
return resp, nil
}
// recorder is the minimal http.ResponseWriter the in-process round trip needs.
// It is written out by hand rather than importing net/http/httptest, which is a
// testing package and has no business in a serving path.
type recorder struct {
header http.Header
body bytes.Buffer
status int
wroteHeader bool
}
func (r *recorder) Header() http.Header { return r.header }
func (r *recorder) Write(p []byte) (int, error) {
if !r.wroteHeader {
r.WriteHeader(http.StatusOK)
}
return r.body.Write(p)
}
func (r *recorder) WriteHeader(status int) {
if r.wroteHeader {
return
}
r.wroteHeader = true
r.status = status
}