MCPcopy Index your code
hub / github.com/coder/coder / RoundTrip

Method RoundTrip

coderd/aibridged/transport.go:62–154  ·  view source on GitHub ↗
(req *http.Request)

Source from the content-addressed store, hash-verified

60}
61
62func (t *inMemoryRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
63 // The in-process transport requires the caller to have placed the
64 // delegated API key ID on the context. Without it, aibridged has no
65 // identity to act under. Fail fast at the transport boundary so the
66 // handler can assume the invariant.
67 if _, ok := aibridge.DelegatedAPIKeyIDFromContext(req.Context()); !ok {
68 return nil, xerrors.New("aibridged in-memory transport requires WithDelegatedAPIKeyID on the request context")
69 }
70
71 // Adapt the caller's upstream-shaped URL to the daemon's mount layout:
72 // "/api/v2/aibridge/<providerName>/<original-path>". Done here so
73 // callers do not need to encode the mount prefix or the provider
74 // routing key into the requests they hand to the transport.
75 newPath, err := url.JoinPath(aibridgeRootPath, t.providerName, req.URL.Path)
76 if err != nil {
77 return nil, xerrors.Errorf("rewrite request URL for provider %q: %w", t.providerName, err)
78 }
79 req = req.Clone(req.Context())
80 req.URL.Path = newPath
81
82 pr, pw := io.Pipe()
83 rw := &pipeResponseWriter{
84 header: http.Header{},
85 body: pw,
86 gotHeaders: make(chan struct{}),
87 status: http.StatusOK,
88 }
89
90 // Cloning preserves caller-supplied headers and context but lets the
91 // handler operate on its own request value without surprising the caller
92 // if it mutates Headers or stores the request. The Source is attached to
93 // the served context so downstream handlers can log the call site.
94 served := req.Clone(aibridge.WithSource(req.Context(), t.source))
95
96 handlerDone := make(chan struct{})
97 go func() {
98 defer func() {
99 if r := recover(); r != nil {
100 // Mirror net/http.Server behavior: a panicking handler
101 // produces a 500 instead of crashing the process.
102 rw.WriteHeader(http.StatusInternalServerError)
103 _ = pw.CloseWithError(xerrors.Errorf("handler panicked: %v", r))
104 }
105 // Make sure we always unblock RoundTrip even if the handler
106 // returns before writing headers (e.g. handler returns early
107 // without writing).
108 rw.ensureHeaders()
109 // If the request context was canceled, surface that as a
110 // body-read error so the caller sees a network-style failure
111 // rather than EOF. Otherwise close cleanly.
112 if cerr := served.Context().Err(); cerr != nil {
113 _ = pw.CloseWithError(cerr)
114 } else {
115 _ = pw.Close()
116 }
117 close(handlerDone)
118 }()
119 t.handler.ServeHTTP(rw, served)

Calls 12

WriteHeaderMethod · 0.95
ensureHeadersMethod · 0.95
WithSourceFunction · 0.92
ErrMethod · 0.80
ContextMethod · 0.65
NewMethod · 0.65
CloseMethod · 0.65
ErrorfMethod · 0.45
CloneMethod · 0.45
ServeHTTPMethod · 0.45
DoneMethod · 0.45