Compare commits
No commits in common. "5e77fdd33b3386a172f65a5c574a5ab07852b11b" and "e35bf9af5de062214529e89239ff2db126ed737b" have entirely different histories.
5e77fdd33b
...
e35bf9af5d
5
go.mod
5
go.mod
|
@ -15,12 +15,8 @@ require (
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect
|
|
||||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/go-ap/activitypub v0.0.0-20230719093539-2b6a6f3a25ee // indirect
|
|
||||||
github.com/go-ap/errors v0.0.0-20221205040414-01c1adfc98ea // indirect
|
|
||||||
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73 // indirect
|
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/klauspost/compress v1.16.3 // indirect
|
github.com/klauspost/compress v1.16.3 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
@ -35,7 +31,6 @@ require (
|
||||||
github.com/tinylib/msgp v1.1.8 // indirect
|
github.com/tinylib/msgp v1.1.8 // indirect
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fasthttp v1.47.0 // indirect
|
github.com/valyala/fasthttp v1.47.0 // indirect
|
||||||
github.com/valyala/fastjson v1.6.4 // indirect
|
|
||||||
github.com/valyala/tcplisten v1.0.0 // indirect
|
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||||
golang.org/x/sys v0.10.0 // indirect
|
golang.org/x/sys v0.10.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
|
11
go.sum
11
go.sum
|
@ -1,16 +1,8 @@
|
||||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:cliQ4HHsCo6xi2oWZYKWW4bly/Ory9FuTpFPRxj/mAg=
|
|
||||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
|
|
||||||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||||
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/go-ap/activitypub v0.0.0-20230719093539-2b6a6f3a25ee h1:1OMBlmSzLXftIj5z/D1s1Xr3FanVKtLFZPtdIFslh1A=
|
|
||||||
github.com/go-ap/activitypub v0.0.0-20230719093539-2b6a6f3a25ee/go.mod h1:qw0WNf+PTG69Xu6mVqUluDuKl1VwVYdgntOZQFBZQ48=
|
|
||||||
github.com/go-ap/errors v0.0.0-20221205040414-01c1adfc98ea h1:ywGtLGVjJjMrq4mu35Qmu+NtlhlTk/gTayE6Bb4tQZk=
|
|
||||||
github.com/go-ap/errors v0.0.0-20221205040414-01c1adfc98ea/go.mod h1:SaTNjEEkp0q+w3pUS1ccyEL/lUrHteORlDq/e21mCc8=
|
|
||||||
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73 h1:GMKIYXyXPGIp+hYiWOhfqK4A023HdgisDT4YGgf99mw=
|
|
||||||
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73/go.mod h1:jyveZeGw5LaADntW+UEsMjl3IlIwk+DxlYNsbofQkGA=
|
|
||||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/gofiber/fiber/v2 v2.47.0 h1:EN5lHVCc+Pyqh5OEsk8fzRiifgwpbrP0rulQ4iNf3fs=
|
github.com/gofiber/fiber/v2 v2.47.0 h1:EN5lHVCc+Pyqh5OEsk8fzRiifgwpbrP0rulQ4iNf3fs=
|
||||||
|
@ -61,9 +53,6 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasthttp v1.47.0 h1:y7moDoxYzMooFpT5aHgNgVOQDrS3qlkfiP9mDtGGK9c=
|
github.com/valyala/fasthttp v1.47.0 h1:y7moDoxYzMooFpT5aHgNgVOQDrS3qlkfiP9mDtGGK9c=
|
||||||
github.com/valyala/fasthttp v1.47.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
|
github.com/valyala/fasthttp v1.47.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
|
||||||
github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
|
|
||||||
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
|
|
||||||
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
|
|
||||||
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
|
|
@ -35,22 +35,7 @@
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
<h3>Actions</h3>
|
<a href="/editor/edit/{{.Entry.ID}}/" role="button" class="secondary outline">Edit</a>
|
||||||
<div class="grid">
|
|
||||||
<a href="/editor/edit/{{.Entry.ID}}/" role="button" class="secondary outline">Edit</a>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<hr>
|
|
||||||
<br>
|
|
||||||
<form method="post" action="/editor/delete/{{.Entry.ID}}/" class="grid">
|
|
||||||
<label for="confirm">
|
|
||||||
Confirm deletion
|
|
||||||
<input type="checkbox" name="confirm" id="confirm" required />
|
|
||||||
</label>
|
|
||||||
<input type="submit" class="secondary outline" value="Delete" />
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,17 @@
|
||||||
package web
|
package web
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/url"
|
|
||||||
"owl-blogs/app"
|
|
||||||
"owl-blogs/app/repository"
|
"owl-blogs/app/repository"
|
||||||
"owl-blogs/config"
|
"owl-blogs/config"
|
||||||
"owl-blogs/domain/model"
|
"owl-blogs/domain/model"
|
||||||
|
|
||||||
vocab "github.com/go-ap/activitypub"
|
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ACT_PUB_CONF_NAME = "activity_pub"
|
const ACT_PUB_CONF_NAME = "activity_pub"
|
||||||
|
|
||||||
type ActivityPubServer struct {
|
type ActivityPubServer struct {
|
||||||
configRepo repository.ConfigRepository
|
configRepo repository.ConfigRepository
|
||||||
entryService *app.EntryService
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ActivityPubConfig struct {
|
type ActivityPubConfig struct {
|
||||||
|
@ -26,20 +21,48 @@ type ActivityPubConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebfingerResponse struct {
|
type WebfingerResponse struct {
|
||||||
Subject string `json:"subject"`
|
Subject string `json:"subject"`
|
||||||
Links []WebfingerLink `json:"links"`
|
Links []ActivityPubLink `json:"links"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebfingerLink struct {
|
type ActivityPubLink struct {
|
||||||
Rel string `json:"rel"`
|
Rel string `json:"rel"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Href string `json:"href"`
|
Href string `json:"href"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewActivityPubServer(configRepo repository.ConfigRepository, entryService *app.EntryService) *ActivityPubServer {
|
type ActivityPubActor struct {
|
||||||
|
Context []string `json:"@context"`
|
||||||
|
|
||||||
|
ID string `json:"id"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
PreferredUsername string `json:"preferredUsername"`
|
||||||
|
Inbox string `json:"inbox"`
|
||||||
|
Oubox string `json:"outbox"`
|
||||||
|
Followers string `json:"followers"`
|
||||||
|
|
||||||
|
PublicKey ActivityPubPublicKey `json:"publicKey"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ActivityPubPublicKey struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Owner string `json:"owner"`
|
||||||
|
PublicKeyPem string `json:"publicKeyPem"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ActivityPubOrderedCollection struct {
|
||||||
|
Context []string `json:"@context"`
|
||||||
|
|
||||||
|
ID string `json:"id"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
TotalItems int `json:"totalItems"`
|
||||||
|
First string `json:"first"`
|
||||||
|
Last string `json:"last"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewActivityPubServer(configRepo repository.ConfigRepository) *ActivityPubServer {
|
||||||
return &ActivityPubServer{
|
return &ActivityPubServer{
|
||||||
configRepo: configRepo,
|
configRepo: configRepo,
|
||||||
entryService: entryService,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +75,7 @@ func (s *ActivityPubServer) HandleWebfinger(ctx *fiber.Ctx) error {
|
||||||
webfinger := WebfingerResponse{
|
webfinger := WebfingerResponse{
|
||||||
Subject: ctx.Query("resource"),
|
Subject: ctx.Query("resource"),
|
||||||
|
|
||||||
Links: []WebfingerLink{
|
Links: []ActivityPubLink{
|
||||||
{
|
{
|
||||||
Rel: "self",
|
Rel: "self",
|
||||||
Type: "application/activity+json",
|
Type: "application/activity+json",
|
||||||
|
@ -67,7 +90,6 @@ func (s *ActivityPubServer) HandleWebfinger(ctx *fiber.Ctx) error {
|
||||||
|
|
||||||
func (s *ActivityPubServer) Router(router fiber.Router) {
|
func (s *ActivityPubServer) Router(router fiber.Router) {
|
||||||
router.Get("/actor", s.HandleActor)
|
router.Get("/actor", s.HandleActor)
|
||||||
router.Get("/outbox", s.HandleOutbox)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ActivityPubServer) HandleActor(ctx *fiber.Ctx) error {
|
func (s *ActivityPubServer) HandleActor(ctx *fiber.Ctx) error {
|
||||||
|
@ -76,57 +98,25 @@ func (s *ActivityPubServer) HandleActor(ctx *fiber.Ctx) error {
|
||||||
s.configRepo.Get(ACT_PUB_CONF_NAME, &apConfig)
|
s.configRepo.Get(ACT_PUB_CONF_NAME, &apConfig)
|
||||||
s.configRepo.Get(config.SITE_CONFIG, &siteConfig)
|
s.configRepo.Get(config.SITE_CONFIG, &siteConfig)
|
||||||
|
|
||||||
actor := vocab.PersonNew(vocab.IRI(siteConfig.FullUrl + "/activitypub/actor"))
|
actor := ActivityPubActor{
|
||||||
actor.PreferredUsername = vocab.NaturalLanguageValues{{Value: vocab.Content(apConfig.PreferredUsername)}}
|
Context: []string{
|
||||||
actor.Inbox = vocab.IRI(siteConfig.FullUrl + "/activitypub/inbox")
|
"https://www.w3.org/ns/activitystreams",
|
||||||
actor.Outbox = vocab.IRI(siteConfig.FullUrl + "/activitypub/outbox")
|
"https://w3id.org/security/v1",
|
||||||
actor.Followers = vocab.IRI(siteConfig.FullUrl + "/activitypub/followers")
|
},
|
||||||
actor.PublicKey = vocab.PublicKey{
|
|
||||||
ID: vocab.ID(siteConfig.FullUrl + "/activitypub/actor#main-key"),
|
ID: siteConfig.FullUrl + "/activitypub/actor",
|
||||||
Owner: vocab.IRI(siteConfig.FullUrl + "/activitypub/actor"),
|
Type: "Person",
|
||||||
PublicKeyPem: apConfig.PublicKeyPem,
|
PreferredUsername: apConfig.PreferredUsername,
|
||||||
|
Inbox: siteConfig.FullUrl + "/activitypub/inbox",
|
||||||
|
Oubox: siteConfig.FullUrl + "/activitypub/outbox",
|
||||||
|
Followers: siteConfig.FullUrl + "/activitypub/followers",
|
||||||
|
|
||||||
|
PublicKey: ActivityPubPublicKey{
|
||||||
|
ID: siteConfig.FullUrl + "/activitypub/actor#main-key",
|
||||||
|
Owner: siteConfig.FullUrl + "/activitypub/actor",
|
||||||
|
PublicKeyPem: apConfig.PublicKeyPem,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := actor.MarshalJSON()
|
return ctx.JSON(actor)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
ctx.Set("Content-Type", "application/activity+json")
|
|
||||||
return ctx.Send(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ActivityPubServer) HandleOutbox(ctx *fiber.Ctx) error {
|
|
||||||
siteConfig := model.SiteConfig{}
|
|
||||||
apConfig := ActivityPubConfig{}
|
|
||||||
s.configRepo.Get(ACT_PUB_CONF_NAME, &apConfig)
|
|
||||||
s.configRepo.Get(config.SITE_CONFIG, &siteConfig)
|
|
||||||
|
|
||||||
entries, err := s.entryService.FindAllByType(nil, true, false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
items := make([]vocab.Item, len(entries))
|
|
||||||
for i, entry := range entries {
|
|
||||||
url, _ := url.JoinPath(siteConfig.FullUrl, "/posts/"+entry.ID()+"/")
|
|
||||||
items[i] = *vocab.ActivityNew(vocab.IRI(url), vocab.CreateType, vocab.Object{
|
|
||||||
ID: vocab.ID(url),
|
|
||||||
Type: vocab.ArticleType,
|
|
||||||
Content: vocab.NaturalLanguageValues{
|
|
||||||
{Value: vocab.Content(entry.Content())},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
outbox := vocab.OrderedCollectionNew(vocab.IRI(siteConfig.FullUrl + "/activitypub/outbox"))
|
|
||||||
outbox.TotalItems = uint(len(items))
|
|
||||||
outbox.OrderedItems = items
|
|
||||||
|
|
||||||
data, err := outbox.MarshalJSON()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
ctx.Set("Content-Type", "application/activity+json")
|
|
||||||
return ctx.Send(data)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,6 @@ func NewWebApp(
|
||||||
editor.Post("/new/:editor/", editorHandler.HandlePostNew)
|
editor.Post("/new/:editor/", editorHandler.HandlePostNew)
|
||||||
editor.Get("/edit/:id/", editorHandler.HandleGetEdit)
|
editor.Get("/edit/:id/", editorHandler.HandleGetEdit)
|
||||||
editor.Post("/edit/:id/", editorHandler.HandlePostEdit)
|
editor.Post("/edit/:id/", editorHandler.HandlePostEdit)
|
||||||
editor.Post("/delete/:id/", editorHandler.HandlePostDelete)
|
|
||||||
|
|
||||||
// SiteConfig
|
// SiteConfig
|
||||||
siteConfig := app.Group("/site-config")
|
siteConfig := app.Group("/site-config")
|
||||||
|
@ -118,10 +117,10 @@ func NewWebApp(
|
||||||
app.Get("/sitemap.xml", NewSiteMapHandler(entryService, configRepo).Handle)
|
app.Get("/sitemap.xml", NewSiteMapHandler(entryService, configRepo).Handle)
|
||||||
|
|
||||||
// ActivityPub
|
// ActivityPub
|
||||||
activityPubServer := NewActivityPubServer(configRepo, entryService)
|
// activityPubServer := NewActivityPubServer(configRepo)
|
||||||
configRegister.Register(ACT_PUB_CONF_NAME, &ActivityPubConfig{})
|
configRegister.Register(ACT_PUB_CONF_NAME, &ActivityPubConfig{})
|
||||||
app.Get("/.well-known/webfinger", activityPubServer.HandleWebfinger)
|
// app.Get("/.well-known/webfinger", activityPubServer.HandleWebfinger)
|
||||||
app.Route("/activitypub", activityPubServer.Router)
|
// app.Route("/activitypub", activityPubServer.Router)
|
||||||
|
|
||||||
// Webmention
|
// Webmention
|
||||||
// app.Post("/webmention/", userWebmentionHandler(repo))
|
// app.Post("/webmention/", userWebmentionHandler(repo))
|
||||||
|
|
|
@ -127,24 +127,3 @@ func (h *EditorHandler) HandlePostEdit(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
return c.Redirect("/posts/" + entry.ID() + "/")
|
return c.Redirect("/posts/" + entry.ID() + "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *EditorHandler) HandlePostDelete(c *fiber.Ctx) error {
|
|
||||||
c.Set(fiber.HeaderContentType, fiber.MIMETextHTML)
|
|
||||||
|
|
||||||
id := c.Params("id")
|
|
||||||
entry, err := h.entrySvc.FindById(id)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
confirm := c.FormValue("confirm")
|
|
||||||
if confirm != "on" {
|
|
||||||
return c.Redirect("/posts/" + entry.ID() + "/")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = h.entrySvc.Delete(entry)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return c.Redirect("/")
|
|
||||||
}
|
|
||||||
|
|
|
@ -23,7 +23,6 @@ func (h *MediaHandler) Handle(c *fiber.Ctx) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
binary, err := h.binaryService.FindById(id)
|
binary, err := h.binaryService.FindById(id)
|
||||||
c.Set("Content-Type", binary.Mime())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue