| 170 | } |
| 171 | |
| 172 | func (s *Server) startAPIServer(ctx context.Context) error { |
| 173 | mux := http.NewServeMux() |
| 174 | |
| 175 | mux.HandleFunc("POST /v1/chat/completions", s.handleOpenAI) |
| 176 | mux.HandleFunc("POST /v1/responses", s.handleResponses) |
| 177 | mux.HandleFunc("POST /v1/messages", s.handleAnthropic) |
| 178 | |
| 179 | var handler http.Handler = mux |
| 180 | if s.tracerProvider != nil { |
| 181 | handler = s.tracingMiddleware(handler) |
| 182 | } |
| 183 | |
| 184 | s.httpServer = &http.Server{ |
| 185 | Handler: handler, |
| 186 | ReadHeaderTimeout: 10 * time.Second, |
| 187 | } |
| 188 | |
| 189 | listener, err := net.Listen("tcp", s.address) |
| 190 | if err != nil { |
| 191 | return xerrors.Errorf("listen on %s: %w", s.address, err) |
| 192 | } |
| 193 | s.httpListener = listener |
| 194 | |
| 195 | pproflabel.Go(ctx, pproflabel.Service("llm-mock"), func(ctx context.Context) { |
| 196 | if err := s.httpServer.Serve(listener); err != nil && !errors.Is(err, http.ErrServerClosed) { |
| 197 | s.logger.Error(ctx, "http API server error", slog.Error(err)) |
| 198 | } |
| 199 | }) |
| 200 | |
| 201 | return nil |
| 202 | } |
| 203 | |
| 204 | func (s *Server) handleOpenAI(w http.ResponseWriter, r *http.Request) { |
| 205 | pproflabel.Do(r.Context(), pproflabel.Service("llm-mock"), func(ctx context.Context) { |