diff --git a/api/api.go b/api/api.go index e803b65..aa49528 100644 --- a/api/api.go +++ b/api/api.go @@ -7,6 +7,7 @@ import ( "github.com/robfig/cron/v3" "github.com/teivah/broadcast" + "github.com/tigorlazuardi/redmage/api/bmessage" "github.com/tigorlazuardi/redmage/config" "github.com/tigorlazuardi/redmage/db/queries" "github.com/tigorlazuardi/redmage/pkg/errs" @@ -20,7 +21,7 @@ type API struct { scheduler *cron.Cron scheduleMap map[cron.EntryID]queries.Subreddit - downloadBroadcast *broadcast.Relay[DownloadStatusMessage] + downloadBroadcast *broadcast.Relay[bmessage.DownloadStatusMessage] config *config.Config } @@ -31,7 +32,7 @@ func New(q *queries.Queries, db *sql.DB, cfg *config.Config) *API { db: db, scheduler: cron.New(), scheduleMap: make(map[cron.EntryID]queries.Subreddit, 8), - downloadBroadcast: broadcast.NewRelay[DownloadStatusMessage](), + downloadBroadcast: broadcast.NewRelay[bmessage.DownloadStatusMessage](), config: cfg, } } diff --git a/api/bmessage/bmessage.go b/api/bmessage/bmessage.go new file mode 100644 index 0000000..26deea8 --- /dev/null +++ b/api/bmessage/bmessage.go @@ -0,0 +1,24 @@ +package bmessage + +import ( + "github.com/alecthomas/units" +) + +type ImageMetadata struct { + URL string + Height int + Width int + ThumbnailURL string + ThumbnailHeight int + ThumbnailWidth int +} + +type DownloadStatusMessage struct { + Metadata ImageMetadata + ContantLength units.MetricBytes + Downloaded units.MetricBytes + Subreddit string + PostURL string + PostID string + Error error +} diff --git a/api/download_subreddit_posts.go b/api/download_subreddit_posts.go index a83900f..7ea04be 100644 --- a/api/download_subreddit_posts.go +++ b/api/download_subreddit_posts.go @@ -11,6 +11,6 @@ type DownloadSubredditPostsParams struct { Limit int } -func (api *API) DownloadSubredditPosts(ctx context.Context, subredditName string, params DownloadSubredditParams) (posts []reddit.Post, err error) { +func (api *API) DownloadSubredditPosts(ctx context.Context, subredditName string, params DownloadSubredditParams) (posts []reddit.Listing, err error) { return posts, err } diff --git a/api/reddit/download_images.go b/api/reddit/download_images.go new file mode 100644 index 0000000..21d71a5 --- /dev/null +++ b/api/reddit/download_images.go @@ -0,0 +1,27 @@ +package reddit + +import ( + "context" + "io" + + "github.com/tigorlazuardi/redmage/api/bmessage" +) + +type DownloadStatusBroadcaster interface { + Broadcast(bmessage.DownloadStatusMessage) +} + +type NullDownloadStatusBroadcaster struct{} + +func (NullDownloadStatusBroadcaster) Broadcast(bmessage.DownloadStatusMessage) {} + +type PostImage struct { + ImageURL string + ImageFile io.Reader + ThumbnailURL string + ThumbnailFile io.Reader +} + +func (reddit *Reddit) DownloadImage(ctx context.Context, post Post, broadcaster DownloadStatusBroadcaster) (images PostImage, err error) { + return images, err +} diff --git a/api/reddit/fancy_reader.go b/api/reddit/fancy_reader.go index abb1d89..01a4350 100644 --- a/api/reddit/fancy_reader.go +++ b/api/reddit/fancy_reader.go @@ -1 +1,39 @@ package reddit + +import ( + "io" + "net/http" +) + +type ProgressReader struct { + OnProgress func(downloaded int64, contentLength int64, err error) + OnClose func(closeErr error) + + reader io.ReadCloser + contentLength int64 + downloaded int64 +} + +func (progressReader *ProgressReader) WrapHTTPResponse(resp *http.Response) *http.Response { + progressReader.reader = resp.Body + progressReader.contentLength = resp.ContentLength + resp.Body = progressReader + return resp +} + +func (progressReader *ProgressReader) Read(p []byte) (n int, err error) { + n, err = progressReader.reader.Read(p) + progressReader.downloaded += int64(n) + if progressReader.OnProgress != nil { + progressReader.OnProgress(progressReader.downloaded, progressReader.contentLength, err) + } + return n, err +} + +func (progressReader *ProgressReader) Close() error { + err := progressReader.reader.Close() + if progressReader.OnClose != nil { + progressReader.OnClose(err) + } + return err +} diff --git a/api/reddit/get_posts.go b/api/reddit/get_posts.go index 75c1ee8..ab7bf74 100644 --- a/api/reddit/get_posts.go +++ b/api/reddit/get_posts.go @@ -7,6 +7,7 @@ import ( "io" "log/slog" "net/http" + "strings" "github.com/tigorlazuardi/redmage/pkg/errs" ) @@ -34,7 +35,7 @@ type GetPostsParam struct { SubredditType SubredditType } -func (reddit *Reddit) GetPosts(ctx context.Context, params GetPostsParam) (posts []Post, err error) { +func (reddit *Reddit) GetPosts(ctx context.Context, params GetPostsParam) (posts Listing, err error) { url := fmt.Sprintf("https://reddit.com/%s/%s.json?limit=%d&page=%d", params.SubredditType.Code(), params.Subreddit, params.Limit, params.Page) req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, http.NoBody) if err != nil { @@ -51,7 +52,7 @@ func (reddit *Reddit) GetPosts(ctx context.Context, params GetPostsParam) (posts body, _ := io.ReadAll(res.Body) return posts, errs.Fail("reddit: unexpected status code when executing GetPosts", slog.Group("request", "url", url, "params", params), - slog.Group("response", "status_code", res.StatusCode, "body", json.RawMessage(body)), + slog.Group("response", "status_code", res.StatusCode, "body", formatLogBody(res, body)), ) } @@ -62,3 +63,10 @@ func (reddit *Reddit) GetPosts(ctx context.Context, params GetPostsParam) (posts return posts, nil } + +func formatLogBody(res *http.Response, body []byte) any { + if strings.HasPrefix(res.Header.Get("Content-Type"), "application/json") { + return json.RawMessage(body) + } + return string(body) +} diff --git a/api/reddit/post.go b/api/reddit/post.go index 5366829..b603ca3 100644 --- a/api/reddit/post.go +++ b/api/reddit/post.go @@ -1,10 +1,14 @@ package reddit -type Post struct { +type Listing struct { Kind string `json:"kind"` Data Data `json:"data"` } +func (l *Listing) GetPosts() []Post { + return l.Data.Children +} + type ( MediaEmbed struct{} SecureMediaEmbed struct{} @@ -65,7 +69,7 @@ type AuthorFlairRichtext struct { E string `json:"e"` T string `json:"t"` } -type ChildrenData struct { +type PostData struct { ApprovedAtUtc any `json:"approved_at_utc"` Subreddit string `json:"subreddit"` Selftext string `json:"selftext"` @@ -176,16 +180,44 @@ type ChildrenData struct { NumCrossposts int `json:"num_crossposts"` Media any `json:"media"` IsVideo bool `json:"is_video"` + PostHint string `json:"post_hint"` + Preview Preview `json:"preview"` } -type Children struct { - Kind string `json:"kind"` - Data ChildrenData `json:"data,omitempty"` + +type Post struct { + Kind string `json:"kind"` + Data PostData `json:"data,omitempty"` } + +func (post *Post) IsImagePost() bool { + return post.Data.PostHint == "image" +} + +func (post *Post) GetImageURL() string { + return post.Data.URL +} + +func (post *Post) GetImageSize() (height, width int) { + if len(post.Data.Preview.Images) == 0 { + return 0, 0 + } + source := post.Data.Preview.Images[0].Source + return source.Height, source.Width +} + +func (post *Post) GetThumbnailURL() string { + return post.Data.Thumbnail +} + +func (post *Post) GetThumbnailSize() (height, width int) { + return post.Data.ThumbnailHeight, post.Data.ThumbnailWidth +} + type Data struct { - After string `json:"after"` - Dist int `json:"dist"` - Modhash string `json:"modhash"` - GeoFilter any `json:"geo_filter"` - Children []Children `json:"children"` - Before any `json:"before"` + After string `json:"after"` + Dist int `json:"dist"` + Modhash string `json:"modhash"` + GeoFilter any `json:"geo_filter"` + Children []Post `json:"children"` + Before any `json:"before"` } diff --git a/api/subredditpost/subredditpost.go b/api/subredditpost/subredditpost.go deleted file mode 100644 index 131022c..0000000 --- a/api/subredditpost/subredditpost.go +++ /dev/null @@ -1,191 +0,0 @@ -package subredditpost - -type SubredditPost struct { - Kind string `json:"kind"` - Data Data `json:"data"` -} - -type ( - MediaEmbed struct{} - SecureMediaEmbed struct{} - Gildings struct{} - Source struct { - URL string `json:"url"` - Width int `json:"width"` - Height int `json:"height"` - } -) - -type Resolutions struct { - URL string `json:"url"` - Width int `json:"width"` - Height int `json:"height"` -} -type ( - Variants struct{} - Images struct { - Source Source `json:"source"` - Resolutions []Resolutions `json:"resolutions"` - Variants Variants `json:"variants"` - ID string `json:"id"` - } -) - -type Preview struct { - Images []Images `json:"images"` - Enabled bool `json:"enabled"` -} -type LinkFlairRichtext struct { - E string `json:"e"` - T string `json:"t"` -} -type ThumbnailPreview struct { - Y int `json:"y"` - X int `json:"x"` - U string `json:"u"` -} - -type MediaMetadata struct { - Status string `json:"status"` - Kind string `json:"e"` - Mimetype string `json:"m"` - ExtraThumbnails []ThumbnailPreview `json:"p"` - Thumbnail ThumbnailPreview `json:"s"` - ID string `json:"id"` -} -type Items struct { - OutboundURL string `json:"outbound_url,omitempty"` - MediaID string `json:"media_id"` - ID int `json:"id"` -} -type GalleryData struct { - Items []Items `json:"items"` -} -type AuthorFlairRichtext struct { - E string `json:"e"` - T string `json:"t"` -} -type ChildrenData struct { - ApprovedAtUtc any `json:"approved_at_utc"` - Subreddit string `json:"subreddit"` - Selftext string `json:"selftext"` - AuthorFullname string `json:"author_fullname"` - Saved bool `json:"saved"` - ModReasonTitle any `json:"mod_reason_title"` - Gilded int `json:"gilded"` - Clicked bool `json:"clicked"` - IsGallery bool `json:"is_gallery"` - Title string `json:"title"` - LinkFlairRichtext []LinkFlairRichtext `json:"link_flair_richtext"` - SubredditNamePrefixed string `json:"subreddit_name_prefixed"` - Hidden bool `json:"hidden"` - Pwls int `json:"pwls"` - LinkFlairCSSClass string `json:"link_flair_css_class"` - Downs int `json:"downs"` - ThumbnailHeight int `json:"thumbnail_height"` - TopAwardedType any `json:"top_awarded_type"` - HideScore bool `json:"hide_score"` - MediaMetadata map[string]MediaMetadata `json:"media_metadata"` - Name string `json:"name"` - Quarantine bool `json:"quarantine"` - LinkFlairTextColor any `json:"link_flair_text_color"` - UpvoteRatio float64 `json:"upvote_ratio"` - AuthorFlairBackgroundColor any `json:"author_flair_background_color"` - Ups int `json:"ups"` - Domain string `json:"domain"` - MediaEmbed MediaEmbed `json:"media_embed"` - ThumbnailWidth int `json:"thumbnail_width"` - AuthorFlairTemplateID string `json:"author_flair_template_id"` - IsOriginalContent bool `json:"is_original_content"` - UserReports []any `json:"user_reports"` - SecureMedia any `json:"secure_media"` - IsRedditMediaDomain bool `json:"is_reddit_media_domain"` - IsMeta bool `json:"is_meta"` - Category any `json:"category"` - SecureMediaEmbed SecureMediaEmbed `json:"secure_media_embed"` - GalleryData GalleryData `json:"gallery_data"` - LinkFlairText string `json:"link_flair_text"` - CanModPost bool `json:"can_mod_post"` - Score int `json:"score"` - ApprovedBy any `json:"approved_by"` - IsCreatedFromAdsUI bool `json:"is_created_from_ads_ui"` - AuthorPremium bool `json:"author_premium"` - Thumbnail string `json:"thumbnail"` - Edited bool `json:"edited"` - AuthorFlairCSSClass string `json:"author_flair_css_class"` - AuthorFlairRichtext []AuthorFlairRichtext `json:"author_flair_richtext"` - Gildings Gildings `json:"gildings"` - ContentCategories any `json:"content_categories"` - IsSelf bool `json:"is_self"` - SubredditType string `json:"subreddit_type"` - Created int `json:"created"` - LinkFlairType string `json:"link_flair_type"` - Wls int `json:"wls"` - RemovedByCategory any `json:"removed_by_category"` - BannedBy any `json:"banned_by"` - AuthorFlairType string `json:"author_flair_type"` - TotalAwardsReceived int `json:"total_awards_received"` - AllowLiveComments bool `json:"allow_live_comments"` - SelftextHTML any `json:"selftext_html"` - Likes any `json:"likes"` - SuggestedSort any `json:"suggested_sort"` - BannedAtUtc any `json:"banned_at_utc"` - URLOverriddenByDest string `json:"url_overridden_by_dest"` - ViewCount any `json:"view_count"` - Archived bool `json:"archived"` - NoFollow bool `json:"no_follow"` - IsCrosspostable bool `json:"is_crosspostable"` - Pinned bool `json:"pinned"` - Over18 bool `json:"over_18"` - AllAwardings []any `json:"all_awardings"` - Awarders []any `json:"awarders"` - MediaOnly bool `json:"media_only"` - CanGild bool `json:"can_gild"` - Spoiler bool `json:"spoiler"` - Locked bool `json:"locked"` - AuthorFlairText string `json:"author_flair_text"` - TreatmentTags []any `json:"treatment_tags"` - Visited bool `json:"visited"` - RemovedBy any `json:"removed_by"` - ModNote any `json:"mod_note"` - Distinguished any `json:"distinguished"` - SubredditID string `json:"subreddit_id"` - AuthorIsBlocked bool `json:"author_is_blocked"` - ModReasonBy any `json:"mod_reason_by"` - NumReports any `json:"num_reports"` - RemovalReason any `json:"removal_reason"` - LinkFlairBackgroundColor any `json:"link_flair_background_color"` - ID string `json:"id"` - IsRobotIndexable bool `json:"is_robot_indexable"` - ReportReasons any `json:"report_reasons"` - Author string `json:"author"` - DiscussionType any `json:"discussion_type"` - NumComments int `json:"num_comments"` - SendReplies bool `json:"send_replies"` - WhitelistStatus string `json:"whitelist_status"` - ContestMode bool `json:"contest_mode"` - ModReports []any `json:"mod_reports"` - AuthorPatreonFlair bool `json:"author_patreon_flair"` - AuthorFlairTextColor string `json:"author_flair_text_color"` - Permalink string `json:"permalink"` - ParentWhitelistStatus string `json:"parent_whitelist_status"` - Stickied bool `json:"stickied"` - URL string `json:"url"` - SubredditSubscribers int `json:"subreddit_subscribers"` - CreatedUtc int `json:"created_utc"` - NumCrossposts int `json:"num_crossposts"` - Media any `json:"media"` - IsVideo bool `json:"is_video"` -} -type Children struct { - Kind string `json:"kind"` - Data ChildrenData `json:"data,omitempty"` -} -type Data struct { - After string `json:"after"` - Dist int `json:"dist"` - Modhash string `json:"modhash"` - GeoFilter any `json:"geo_filter"` - Children []Children `json:"children"` - Before any `json:"before"` -} diff --git a/db/migrations/20240409222145_create_images_table.sql b/db/migrations/20240409222145_create_images_table.sql index 41a0f84..899c687 100644 --- a/db/migrations/20240409222145_create_images_table.sql +++ b/db/migrations/20240409222145_create_images_table.sql @@ -7,6 +7,7 @@ CREATE TABLE images( title VARCHAR(255) NOT NULL, post_id VARCHAR(50) NOT NULL, post_url VARCHAR(255) NOT NULL, + post_created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, poster VARCHAR(50) NOT NULL, poster_url VARCHAR(255) NOT NULL, image_relative_path VARCHAR(255) NOT NULL, diff --git a/go.mod b/go.mod index fa7f14e..470bbc6 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.22.1 require ( github.com/a-h/templ v0.2.648 github.com/adrg/xdg v0.4.0 + github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 github.com/fatih/color v1.16.0 github.com/go-chi/chi/v5 v5.0.12 github.com/joho/godotenv v1.5.1 @@ -20,25 +21,23 @@ require ( github.com/mattn/go-isatty v0.0.20 github.com/mattn/go-sqlite3 v1.14.6 github.com/pressly/goose/v3 v3.19.2 + github.com/robfig/cron/v3 v3.0.0 github.com/simukti/sqldb-logger v0.0.0-20230108155151-646c1a075551 github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 + github.com/teivah/broadcast v0.1.0 ) require ( github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/jonboulle/clockwork v0.4.0 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/mfridman/interpolate v0.0.2 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/robfig/cron/v3 v3.0.0 // indirect github.com/sethvargo/go-retry v0.2.4 // indirect - github.com/teivah/broadcast v0.1.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20231219180239-dc181d75b848 // indirect golang.org/x/sync v0.6.0 // indirect diff --git a/go.sum b/go.sum index 0611c78..6435d26 100644 --- a/go.sum +++ b/go.sum @@ -14,6 +14,8 @@ github.com/a-h/templ v0.2.648 h1:A1ggHGIE7AONOHrFaDTM8SrqgqHL6fWgWCijQ21Zy9I= github.com/a-h/templ v0.2.648/go.mod h1:SA7mtYwVEajbIXFRh3vKdYm/4FYyLQAtPH1+KxzGPA8= github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E= +github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 h1:ez/4by2iGztzR4L0zgAOR8lTQK9VlyBVVd7G4omaOQs= +github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI= github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230512164433-5d1fd1a340c9 h1:goHVqTbFX3AIo0tzGr14pgfAW2ZfPChKO21Z9MGf/gk= @@ -47,8 +49,6 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s= github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-co-op/gocron/v2 v2.2.9 h1:aoKosYWSSdXFLecjFWX1i8+R6V7XdZb8sB2ZKAY5Yis= -github.com/go-co-op/gocron/v2 v2.2.9/go.mod h1:mZx3gMSlFnb97k3hRqX3+GdlG3+DUwTh6B8fnsTScXg= github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw= github.com/go-faster/city v1.0.1/go.mod h1:jKcUJId49qdW3L1qKHH/3wPeUstCVpVSXTM6vO3VcTw= github.com/go-faster/errors v0.6.1 h1:nNIPOBkprlKzkThvS/0YaX8Zs9KewLCOSFQS5BU06FI= @@ -158,8 +158,6 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94 github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/robfig/cron/v3 v3.0.0 h1:kQ6Cb7aHOHTSzNVNEhmp8EcWKLb4CbiMW9h9VyIhO4E= github.com/robfig/cron/v3 v3.0.0/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= -github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= @@ -178,6 +176,7 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= @@ -205,8 +204,6 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 h1:mchzmB1XO2pMaKFRqk/+MV3mgGG96aqaPXaMifQU47w= -golang.org/x/exp v0.0.0-20231108232855-2478ac86f678/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= golang.org/x/exp v0.0.0-20231219180239-dc181d75b848 h1:+iq7lrkxmFNBM7xx+Rae2W6uyPfhPeDWD+n+JgppptE= golang.org/x/exp v0.0.0-20231219180239-dc181d75b848/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= @@ -233,6 +230,7 @@ google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/server/routes/middleware/logger.go b/server/routes/middleware/logger.go index 0d29557..c78934d 100644 --- a/server/routes/middleware/logger.go +++ b/server/routes/middleware/logger.go @@ -67,7 +67,7 @@ func flatHeader(header http.Header) map[string]string { m := make(map[string]string, len(header)) for k := range header { - m[k] = strings.Join(header[k], "; ") + m[k] = strings.Join(header[k], ", ") } return m }