diff --git a/internal/service/service.go b/internal/service/service.go index 851320e..3c3c4d5 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -211,7 +211,6 @@ func (svc *Service) ServeHTTP(w http.ResponseWriter, r *http.Request) { slog.String("path", r.URL.Path), )) ) - // Log completion time. defer func() { log.InfoContext( @@ -249,6 +248,9 @@ func (svc *Service) ServeHTTP(w http.ResponseWriter, r *http.Request) { log.InfoContext(ctx, "handling") + // Always set request ID header. + w.Header().Set("X-Request-ID", id) + // Pass the request on to the multiplexer. svc.mux.ServeHTTP(w, r) } diff --git a/internal/service/static/main.js b/internal/service/static/main.js index 40053d4..7325f25 100644 --- a/internal/service/static/main.js +++ b/internal/service/static/main.js @@ -657,14 +657,21 @@ class Odidere { body: JSON.stringify(payload), signal: this.currentController.signal, }); + const requestId = res.headers.get('X-Request-ID') || ''; + if (!res.ok) { const err = await res.text(); - throw new Error(`server error ${res.status}: ${err}`); + this.renderer.renderError( + `server error ${res.status}: ${err}`, + requestId, + ); + return; } for await (const { eventType, event } of this._parseSSEStream(res)) { if (event.error) { - throw new Error(event.error); + this.renderer.renderError(event.error, requestId); + return; } if ( diff --git a/internal/service/static/render.js b/internal/service/static/render.js index 955d91b..ebfc6e4 100644 --- a/internal/service/static/render.js +++ b/internal/service/static/render.js @@ -403,11 +403,17 @@ export class Renderer { * renderError renders an error message in the chat. * @param {string} message */ - renderError(message) { + renderError(message, requestId = '') { const $msg = this.$tplErrorMessage.content.cloneNode(true).firstElementChild; - $msg.querySelector('.message__content').textContent = message; - $msg.dataset.copyText = message; + const $content = $msg.querySelector('.message__content'); + if (requestId) { + $content.textContent = `Request: ${requestId}\n${message}`; + $msg.dataset.copyText = `Request: ${requestId}\n${message}`; + } else { + $content.textContent = message; + $msg.dataset.copyText = message; + } this.$chat.insertBefore($msg, this.$chatLoading); this.scrollToBottom(); }