From 3396f6f24d7624e076469195759fe315134a14fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean=20Fran=C3=A7ois=20CASSAN?= Date: Fri, 9 Aug 2024 10:27:30 -0300 Subject: [PATCH] Program errors out due to no ping API response despite API responding (#431) * Program errors out due to no ping API response despite API responding Fixes #393 * add API trace for ping and validate connection * fix linter --- cmd/shared.go | 29 +++++++++++++++-------------- helpers/fshelper/teereadercloser.go | 26 ++++++++++++++++++++++++++ immich/call.go | 15 +++++++++++++++ immich/client.go | 6 ++++-- 4 files changed, 60 insertions(+), 16 deletions(-) create mode 100644 helpers/fshelper/teereadercloser.go diff --git a/cmd/shared.go b/cmd/shared.go index 46c862e1..14b8fa20 100644 --- a/cmd/shared.go +++ b/cmd/shared.go @@ -173,6 +173,21 @@ func (app *SharedFlags) Start(ctx context.Context) error { app.Immich.SetDeviceUUID(app.DeviceUUID) } + if app.APITrace { + if app.APITraceWriter == nil { + err := configuration.MakeDirForFile(app.LogFile) + if err != nil { + return err + } + app.APITraceWriterName = strings.TrimSuffix(app.LogFile, filepath.Ext(app.LogFile)) + ".trace.log" + app.APITraceWriter, err = os.OpenFile(app.APITraceWriterName, os.O_CREATE|os.O_WRONLY, 0o664) + if err != nil { + return err + } + app.Immich.EnableAppTrace(app.APITraceWriter) + } + } + err = app.Immich.PingServer(ctx) if err != nil { return err @@ -186,20 +201,6 @@ func (app *SharedFlags) Start(ctx context.Context) error { app.Log.Info(fmt.Sprintf("Connected, user: %s", user.Email)) } - if app.APITrace { - if app.APITraceWriter == nil { - err := configuration.MakeDirForFile(app.LogFile) - if err != nil { - return err - } - app.APITraceWriterName = strings.TrimSuffix(app.LogFile, filepath.Ext(app.LogFile)) + ".trace.log" - app.APITraceWriter, err = os.OpenFile(app.APITraceWriterName, os.O_CREATE|os.O_WRONLY, 0o664) - if err != nil { - return err - } - app.Immich.EnableAppTrace(app.APITraceWriter) - } - } return nil } diff --git a/helpers/fshelper/teereadercloser.go b/helpers/fshelper/teereadercloser.go new file mode 100644 index 00000000..7a275e3c --- /dev/null +++ b/helpers/fshelper/teereadercloser.go @@ -0,0 +1,26 @@ +package fshelper + +import "io" + +type teeReadCloser struct { + r io.ReadCloser + w io.Writer +} + +func (t *teeReadCloser) Read(p []byte) (n int, err error) { + n, err = t.r.Read(p) + if n > 0 { + if n, err := t.w.Write(p[:n]); err != nil { + return n, err + } + } + return +} + +func (t *teeReadCloser) Close() error { + return t.r.Close() +} + +func TeeReadCloser(r io.ReadCloser, w io.Writer) io.ReadCloser { + return &teeReadCloser{r: r, w: w} +} diff --git a/immich/call.go b/immich/call.go index 92b0bbd7..ac0ce6b2 100644 --- a/immich/call.go +++ b/immich/call.go @@ -11,6 +11,8 @@ import ( "strings" "sync/atomic" "time" + + "github.com/simulot/immich-go/helpers/fshelper" ) type TooManyInternalError struct { @@ -292,3 +294,16 @@ func responseJSON[T any](object *T) serverResponseOption { return errors.New("can't decode nil response") } } + +func responseCopy(buffer *bytes.Buffer) serverResponseOption { + return func(sc *serverCall, resp *http.Response) error { + if resp != nil { + if resp.Body != nil { + newBody := fshelper.TeeReadCloser(resp.Body, buffer) + resp.Body = newBody + return nil + } + } + return nil + } +} diff --git a/immich/client.go b/immich/client.go index 2c7083e1..e4ee8417 100644 --- a/immich/client.go +++ b/immich/client.go @@ -1,6 +1,7 @@ package immich import ( + "bytes" "context" "crypto/tls" "fmt" @@ -111,9 +112,10 @@ func NewImmichClient(endPoint string, key string, options ...clientOption) (*Imm // Ping server func (ic *ImmichClient) PingServer(ctx context.Context) error { r := PingResponse{} - err := ic.newServerCall(ctx, "PingServer").do(getRequest("/server-info/ping", setAcceptJSON()), responseJSON(&r)) + b := bytes.NewBuffer(nil) + err := ic.newServerCall(ctx, "PingServer").do(getRequest("/server-info/ping", setAcceptJSON()), responseCopy(b), responseJSON(&r)) if err != nil { - return fmt.Errorf("the ping API end point doesn't respond at this address: %s", ic.endPoint+"/server-info/ping") + return fmt.Errorf("unexpected response to the immich's ping API at this address: %s:\n%s", ic.endPoint+"/server-info/ping", b.String()) } if r.Res != "pong" { return fmt.Errorf("incorrect ping response: %s", r.Res)