Compare commits

...

6 Commits

Author SHA1 Message Date
fiatjaf
850497956c include checkid length check from @pippellia-btc 2025-03-24 15:57:20 -03:00
andrewheadricke
28ce6cfb7a ensure suspected blossom request hash does not have slashes in it 2025-03-24 15:23:00 -03:00
fiatjaf
f47282c745 get rid of base64x temporarily since it doesn't work on arm64. 2025-03-19 15:02:56 -03:00
fiatjaf
f72dea346f rename menu item on docs to say "blossom". 2025-03-17 13:38:35 -03:00
fiatjaf
51632dcc9f update blossom example to use a different database.
closes https://github.com/fiatjaf/khatru/issues/36
2025-03-17 13:36:41 -03:00
andrewheadricke
6cc2477e89 fix blossom upload < 50bytes 2025-03-15 01:58:07 -03:00
9 changed files with 20 additions and 16 deletions

View File

@@ -1,12 +1,12 @@
package blossom
import (
"encoding/base64"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/cloudwego/base64x"
"github.com/mailru/easyjson"
"github.com/nbd-wtf/go-nostr"
)
@@ -17,7 +17,7 @@ func readAuthorization(r *http.Request) (*nostr.Event, error) {
return nil, nil
}
eventj, err := base64x.StdEncoding.DecodeString(token[6:])
eventj, err := base64.StdEncoding.DecodeString(token[6:])
if err != nil {
return nil, fmt.Errorf("invalid base64 token")
}
@@ -25,7 +25,7 @@ func readAuthorization(r *http.Request) (*nostr.Event, error) {
if err := easyjson.Unmarshal(eventj, &evt); err != nil {
return nil, fmt.Errorf("broken event")
}
if evt.Kind != 24242 || len(evt.ID) != 64 || !evt.CheckID() {
if evt.Kind != 24242 || !evt.CheckID() {
return nil, fmt.Errorf("invalid event")
}
if ok, _ := evt.CheckSignature(); !ok {

View File

@@ -73,7 +73,7 @@ func (bs BlossomServer) handleUpload(w http.ResponseWriter, r *http.Request) {
// read first bytes of upload so we can find out the filetype
b := make([]byte, min(50, size), size)
if _, err = r.Body.Read(b); err != nil {
if n, err := r.Body.Read(b); err != nil && n != size {
blossomError(w, "failed to read initial bytes of upload body: "+err.Error(), 400)
return
}

View File

@@ -49,7 +49,7 @@ func New(rl *khatru.Relay, serviceURL string) *BlossomServer {
return
}
if len(strings.SplitN(r.URL.Path, ".", 2)[0]) == 65 {
if (len(r.URL.Path) == 65 || strings.Index(r.URL.Path, ".") == 65) && strings.Index(r.URL.Path[1:], "/") == -1 {
if r.Method == "HEAD" {
bs.handleHasBlob(w, r)
return

View File

@@ -19,7 +19,7 @@ export default {
{ text: 'HTTP Integration', link: '/core/embed' },
{ text: 'Request Routing', link: '/core/routing' },
{ text: 'Management API', link: '/core/management' },
{ text: 'Media Storage', link: '/core/blossom' },
{ text: 'Media Storage (Blossom)', link: '/core/blossom' },
]
},
{

View File

@@ -18,7 +18,8 @@ func main() {
bl := blossom.New(relay, "http://localhost:3334")
// create a database for keeping track of blob metadata
bl.Store = blossom.EventStoreBlobIndexWrapper{Store: db, ServiceURL: bl.ServiceURL}
// (do not use the same database used for the relay events)
bl.Store = blossom.EventStoreBlobIndexWrapper{Store: blobdb, ServiceURL: bl.ServiceURL}
// implement the required storage functions
bl.StoreBlob = append(bl.StoreBlob, func(ctx context.Context, sha256 string, body []byte) error {

View File

@@ -15,19 +15,22 @@ import (
func main() {
relay := khatru.NewRelay()
db := &badger.BadgerBackend{Path: "/tmp/khatru-badger-blossom-tmp"}
db := &badger.BadgerBackend{Path: "/tmp/khatru-badger-tmp"}
if err := db.Init(); err != nil {
panic(err)
}
relay.StoreEvent = append(relay.StoreEvent, db.SaveEvent)
relay.QueryEvents = append(relay.QueryEvents, db.QueryEvents)
relay.CountEvents = append(relay.CountEvents, db.CountEvents)
relay.DeleteEvent = append(relay.DeleteEvent, db.DeleteEvent)
relay.ReplaceEvent = append(relay.ReplaceEvent, db.ReplaceEvent)
bdb := &badger.BadgerBackend{Path: "/tmp/khatru-badger-blossom-tmp"}
if err := bdb.Init(); err != nil {
panic(err)
}
bl := blossom.New(relay, "http://localhost:3334")
bl.Store = blossom.EventStoreBlobIndexWrapper{Store: db, ServiceURL: bl.ServiceURL}
bl.Store = blossom.EventStoreBlobIndexWrapper{Store: bdb, ServiceURL: bl.ServiceURL}
bl.StoreBlob = append(bl.StoreBlob, func(ctx context.Context, sha256 string, body []byte) error {
fmt.Println("storing", sha256, len(body))
return nil

4
go.mod
View File

@@ -4,12 +4,11 @@ go 1.24.1
require (
github.com/bep/debounce v1.2.1
github.com/cloudwego/base64x v0.1.5
github.com/fasthttp/websocket v1.5.12
github.com/fiatjaf/eventstore v0.16.2
github.com/liamg/magic v0.0.1
github.com/mailru/easyjson v0.9.0
github.com/nbd-wtf/go-nostr v0.51.4
github.com/nbd-wtf/go-nostr v0.51.7
github.com/puzpuzpuz/xsync/v3 v3.5.1
github.com/rs/cors v1.11.1
github.com/stretchr/testify v1.10.0
@@ -26,6 +25,7 @@ require (
github.com/bytedance/sonic v1.13.1 // indirect
github.com/bytedance/sonic/loader v0.2.4 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudwego/base64x v0.1.5 // indirect
github.com/coder/websocket v1.8.12 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/crypto/blake256 v1.1.0 // indirect

4
go.sum
View File

@@ -129,8 +129,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/nbd-wtf/go-nostr v0.51.4 h1:L4kteLUu/U9P1v1i1CP9wXR+n7D7V4aSCWs4hPFdwp0=
github.com/nbd-wtf/go-nostr v0.51.4/go.mod h1:raIUNOilCdhiVIqgwe+9enCtdXu1iuPjbLh1hO7wTqI=
github.com/nbd-wtf/go-nostr v0.51.7 h1:dGjtaaFQ1kA3H+vF8wt9a9WYl54K8C0JmVDf4cp+a4A=
github.com/nbd-wtf/go-nostr v0.51.7/go.mod h1:d6+DfvMWYG5pA3dmNMBJd6WCHVDDhkXbHqvfljf0Gzg=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=

View File

@@ -3,6 +3,7 @@ package khatru
import (
"context"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
@@ -12,7 +13,6 @@ import (
"reflect"
"strings"
"github.com/cloudwego/base64x"
"github.com/nbd-wtf/go-nostr"
"github.com/nbd-wtf/go-nostr/nip86"
)
@@ -72,7 +72,7 @@ func (rl *Relay) HandleNIP86(w http.ResponseWriter, r *http.Request) {
goto respond
}
evtj, err := base64x.StdEncoding.DecodeString(spl[1])
evtj, err := base64.StdEncoding.DecodeString(spl[1])
if err != nil {
resp.Error = "invalid base64 auth"
goto respond