Skip to content

Commit

Permalink
subdomainでのルーティングを実装
Browse files Browse the repository at this point in the history
  • Loading branch information
studiokaiji committed Oct 19, 2023
1 parent f62723e commit 4de6254
Showing 1 changed file with 106 additions and 80 deletions.
186 changes: 106 additions & 80 deletions hostr/cmd/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ package server

import (
"context"
"encoding/base64"
"net/http"
"strings"

"github.com/gin-gonic/gin"
"github.com/nbd-wtf/go-nostr"
"github.com/nbd-wtf/go-nostr/nip19"
"github.com/studiokaiji/nostr-webhost/hostr/cmd/consts"
"github.com/studiokaiji/nostr-webhost/hostr/cmd/relays"
"github.com/studiokaiji/nostr-webhost/hostr/cmd/tools"
)

func Start(port string) {
func Start(port string, mode string) {
ctx := context.Background()

allRelays, err := relays.GetAllRelays()
Expand All @@ -27,6 +28,19 @@ func Start(port string) {
r.GET("/e/:hex_or_nevent", func(ctx *gin.Context) {
hexOrNevent := ctx.Param("hex_or_nevent")

subdomainPubKey := ""

if mode == "secure" {
// modeがsecureの場合、サブドメインにnpubが含まれていないルーティングは許可しない
host := ctx.Request.Host
subdomain := strings.Split(host, ".")[0]
subdomainPubKey, err = tools.ResolvePubKey(subdomain)
if err != nil {
ctx.String(http.StatusBadRequest, "Routing without npub in the subdomain is not allowed")
return
}
}

ids := []string{}

// neventからIDを取得
Expand All @@ -49,105 +63,117 @@ func Start(port string) {
ids = append(ids, hexOrNevent)
}

// Poolからデータを取得する
ev := pool.QuerySingle(ctx, allRelays, nostr.Filter{
filter := nostr.Filter{
Kinds: []int{consts.KindWebhostHTML, consts.KindWebhostCSS, consts.KindWebhostJS, consts.KindWebhostPicture},
IDs: ids,
})
}
if mode == "secure" {
filter.Authors = []string{subdomainPubKey}
}

// Poolからデータを取得する
ev := pool.QuerySingle(ctx, allRelays, filter)
if ev != nil {
switch ev.Kind {
case consts.KindWebhostHTML:
ctx.Data(http.StatusOK, "text/html; charset=utf-8", []byte(ev.Content))
case consts.KindWebhostCSS:
ctx.Data(http.StatusOK, "text/css; charset=utf-8", []byte(ev.Content))
case consts.KindWebhostJS:
ctx.Data(http.StatusOK, "text/javascript; charset=utf-8", []byte(ev.Content))
case consts.KindWebhostPicture:
{
eTag := ev.Tags.GetFirst([]string{"e"})
mTag := ev.Tags.GetFirst([]string{"m"})

if eTag == nil || mTag == nil {
ctx.String(http.StatusBadRequest, http.StatusText((http.StatusBadRequest)))
return
}

evData := pool.QuerySingle(ctx, allRelays, nostr.Filter{
IDs: []string{eTag.Value()},
})

if evData == nil {
ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound))
return
}

data, err := base64.StdEncoding.DecodeString(evData.Content)
if err != nil {
ctx.String(http.StatusBadRequest, http.StatusText((http.StatusBadRequest)))
return
}

ctx.Data(http.StatusOK, mTag.Value(), data)
}
default:
contentType, err := tools.GetContentType(ev.Kind)
if err != nil {
ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound))
}
ctx.Data(http.StatusOK, contentType, []byte(ev.Content))
} else {
ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound))
}

return
})

// Replaceable Event (NIP-33)
r.GET("/p/:pubKey/d/*dTag", func(ctx *gin.Context) {
// pubKeyを取得しFilterに追加
pubKey := ctx.Param("pubKey")
// npubから始まる場合はデコードする
if pubKey[0:4] == "npub" {
_, v, err := nip19.Decode(pubKey)
if mode != "secure" {
r.GET("/p/:pubKey/d/*dTag", func(ctx *gin.Context) {
// pubKeyを取得しFilterに追加
pubKey := ctx.Param("pubKey")
pubKey, err := tools.ResolvePubKey(pubKey)
if err != nil {
ctx.String(http.StatusBadRequest, "Invalid npub")
ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound))
return
}
pubKey = v.(string)
}
authors := []string{pubKey}

// dTagを取得しFilterに追加
// dTagの最初は`/`ではじまるのでそれをslice
dTag := ctx.Param("dTag")[1:]

tags := nostr.TagMap{}
tags["d"] = []string{dTag}
authors := []string{pubKey}

// dTagを取得しFilterに追加
// dTagの最初は`/`ではじまるのでそれをslice
dTag := ctx.Param("dTag")[1:]

tags := nostr.TagMap{}
tags["d"] = []string{dTag}

// Poolからデータを取得する
ev := pool.QuerySingle(ctx, allRelays, nostr.Filter{
Kinds: []int{
consts.KindWebhostReplaceableHTML,
consts.KindWebhostReplaceableCSS,
consts.KindWebhostReplaceableJS,
},
Authors: authors,
Tags: tags,
})
if ev != nil {
contentType, err := tools.GetContentType(ev.Kind)
if err != nil {
ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound))
}
ctx.Data(http.StatusOK, contentType, []byte(ev.Content))
} else {
ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound))
}

// Poolからデータを取得する
ev := pool.QuerySingle(ctx, allRelays, nostr.Filter{
Kinds: []int{
consts.KindWebhostReplaceableHTML,
consts.KindWebhostReplaceableCSS,
consts.KindWebhostReplaceableJS,
},
Authors: authors,
Tags: tags,
return
})
if ev != nil {
switch ev.Kind {
case consts.KindWebhostReplaceableHTML:
ctx.Data(http.StatusOK, "text/html; charset=utf-8", []byte(ev.Content))
case consts.KindWebhostReplaceableCSS:
ctx.Data(http.StatusOK, "text/css; charset=utf-8", []byte(ev.Content))
case consts.KindWebhostReplaceableJS:
ctx.Data(http.StatusOK, "text/javascript; charset=utf-8", []byte(ev.Content))
default:

}

if mode != "normal" {
r.GET("/d/*dTag", func(ctx *gin.Context) {
host := ctx.Request.Host
subdomain := strings.Split(host, ".")[0]

// subdomainからpubKeyを取得しFilterに追加
pubKey, err := tools.ResolvePubKey(subdomain)
if err != nil {
ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound))
return
}
} else {
ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound))
}

return
})
authors := []string{pubKey}

// dTagを取得しFilterに追加
// dTagの最初は`/`ではじまるのでそれをslice
dTag := ctx.Param("dTag")[1:]

tags := nostr.TagMap{}
tags["d"] = []string{dTag}

// Poolからデータを取得する
ev := pool.QuerySingle(ctx, allRelays, nostr.Filter{
Kinds: []int{
consts.KindWebhostReplaceableHTML,
consts.KindWebhostReplaceableCSS,
consts.KindWebhostReplaceableJS,
},
Authors: authors,
Tags: tags,
})
if ev != nil {
contentType, err := tools.GetContentType(ev.Kind)
if err != nil {
ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound))
}
ctx.Data(http.StatusOK, contentType, []byte(ev.Content))
} else {
ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound))
}

return
})
}

r.Run(":" + port)
}

0 comments on commit 4de6254

Please sign in to comment.