Skip to content

Commit

Permalink
Merge pull request #35 from sublinks/update-http
Browse files Browse the repository at this point in the history
  • Loading branch information
lazyguru authored Jan 24, 2024
2 parents 80315c2 + 76daff0 commit ba76425
Show file tree
Hide file tree
Showing 12 changed files with 174 additions and 144 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@

# Go workspace file
go.work

# jetbrains editor
.idea
13 changes: 10 additions & 3 deletions cmd/federation.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,24 @@ import (
)

func main() {
// bootstrap logger
logger := log.NewLogger("main")

// Load connection string from .env file
err := godotenv.Load()
if err != nil {
log.Warn(fmt.Sprintf("failed to load env, %v", err))
logger.Warn(fmt.Sprintf("failed to load env, %v", err))
}

conn, err := db.Connect()
if err != nil {
log.Fatal("failed connecting to db", err)
logger.Fatal("failed connecting to db", err)
}
defer conn.Close()
db.RunMigrations(conn)
http.RunServer()

s := http.NewServer(logger)
s.RunServer()

os.Exit(0)
}
11 changes: 6 additions & 5 deletions internal/db/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,19 @@ import (
var migrations embed.FS

func RunMigrations(db *sql.DB) {
log.Debug("Running migrations...")
logger := log.NewLogger("db migrations")
logger.Debug("Running migrations...")
driver, err := mysql.WithInstance(db, &mysql.Config{})
if err != nil {
log.Fatal("Error getting MySQL driver", err)
logger.Fatal("Error getting MySQL driver", err)
}
source, _ := iofs.New(migrations, "migrations")
m, err := migrate.NewWithInstance("iofs", source, "mysql", driver)
if err != nil {
log.Fatal("Error connecting to database", err)
logger.Fatal("Error connecting to database", err)
}
if err := m.Up(); err != nil && fmt.Sprintf("%s", err) != "no change" {
log.Fatal("Error running migrations", err)
logger.Fatal("Error running migrations", err)
}
log.Debug("Done!")
logger.Debug("Done!")
}
20 changes: 9 additions & 11 deletions internal/http/routes/activity.go → internal/http/activity.go
Original file line number Diff line number Diff line change
@@ -1,33 +1,31 @@
package routes
package http

import (
"context"
"encoding/json"
"fmt"
"net/http"
"sublinks/sublinks-federation/internal/activitypub"
"sublinks/sublinks-federation/internal/lemmy"
"sublinks/sublinks-federation/internal/log"

"fmt"

"golang.org/x/text/cases"
"golang.org/x/text/language"

"github.com/gorilla/mux"
)

func SetupActivityRoutes(r *mux.Router) {
r.HandleFunc("/activities/{action}/{id}", getActivityHandler).Methods("GET")
func (server *Server) SetupActivityRoutes() {
server.Router.HandleFunc("/activities/{action}/{id}", server.getActivityHandler).Methods("GET")
}

func getActivityHandler(w http.ResponseWriter, r *http.Request) {
func (server *Server) getActivityHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
var content []byte
switch vars["action"] {
case "create":
obj, err := GetPostActivityObject(vars["id"])
obj, err := server.GetPostActivityObject(vars["id"])
if err != nil {
log.Error("Error reading object", err)
server.Logger.Error("Error reading object", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
Expand All @@ -54,12 +52,12 @@ func getActivityHandler(w http.ResponseWriter, r *http.Request) {
w.Write(content)
}

func GetPostActivityObject(id string) (*activitypub.Post, error) {
func (server *Server) GetPostActivityObject(id string) (*activitypub.Post, error) {
ctx := context.Background()
c := lemmy.GetLemmyClient(ctx)
post, err := c.GetPost(ctx, id)
if err != nil {
log.Error("Error reading post", err)
server.Logger.Error("Error reading post", err)
return nil, err
}
return activitypub.ConvertPostToApub(post), nil
Expand Down
32 changes: 32 additions & 0 deletions internal/http/apub.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package http

import (
"net/http"
)

func (server *Server) SetupApubRoutes() {
server.Router.HandleFunc("/users/{user}/inbox", server.getInboxHandler).Methods("GET")
server.Router.HandleFunc("/users/{user}/inbox", server.postInboxHandler).Methods("POST")
server.Router.HandleFunc("/users/{user}/outbox", server.getOutboxHandler).Methods("GET")
server.Router.HandleFunc("/users/{user}/outbox", server.postOutboxHandler).Methods("POST")
}

func (server *Server) getInboxHandler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Header().Add("content-type", "application/activity+json")
}

func (server *Server) postInboxHandler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Header().Add("content-type", "application/activity+json")
}

func (server *Server) getOutboxHandler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Header().Add("content-type", "application/activity+json")
}

func (server *Server) postOutboxHandler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Header().Add("content-type", "application/activity+json")
}
33 changes: 33 additions & 0 deletions internal/http/middleware.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package http

import (
"encoding/json"
"net/http"
)

type RequestError struct {
Msg string `json:"message"`
}

func (server *Server) logMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
server.Logger.Request("", r)
next.ServeHTTP(w, r)
})
}

func (server *Server) notFound(w http.ResponseWriter, r *http.Request) {
server.Logger.Request("404 Not Found", r)
w.WriteHeader(http.StatusNotFound)
w.Header().Add("content-type", "application/activity+json")
content, _ := json.Marshal(RequestError{Msg: "not found"})
w.Write(content)
}

func (server *Server) notAllowedMethod(w http.ResponseWriter, r *http.Request) {
server.Logger.Request("405 Method Not Allowed", r)
w.WriteHeader(http.StatusNotFound)
w.Header().Add("content-type", "application/activity+json")
content, _ := json.Marshal(RequestError{Msg: "method not allowed"})
w.Write(content)
}
14 changes: 6 additions & 8 deletions internal/http/routes/post.go → internal/http/post.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
package routes
package http

import (
"context"
"encoding/json"
"github.com/gorilla/mux"
"net/http"
"sublinks/sublinks-federation/internal/activitypub"
"sublinks/sublinks-federation/internal/lemmy"
"sublinks/sublinks-federation/internal/log"

"github.com/gorilla/mux"
)

func SetupPostRoutes(r *mux.Router) {
r.HandleFunc("/post/{postId}", getPostHandler).Methods("GET")
func (server *Server) SetupPostRoutes() {
server.Router.HandleFunc("/post/{postId}", server.getPostHandler).Methods("GET")
}

func getPostHandler(w http.ResponseWriter, r *http.Request) {
func (server *Server) getPostHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
ctx := context.Background()
c := lemmy.GetLemmyClient(ctx)
post, err := c.GetPost(ctx, vars["postId"])
if err != nil {
log.Error("Error reading post", err)
server.Logger.Error("Error reading post", err)
return
}
postLd := activitypub.ConvertPostToApub(post)
Expand Down
34 changes: 0 additions & 34 deletions internal/http/routes/apub.go

This file was deleted.

48 changes: 0 additions & 48 deletions internal/http/routes/routes.go

This file was deleted.

35 changes: 28 additions & 7 deletions internal/http/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,56 @@ package http
import (
"context"
"flag"
"github.com/gorilla/mux"
"net/http"
"os"
"os/signal"
"sublinks/sublinks-federation/internal/http/routes"
"sublinks/sublinks-federation/internal/log"
"time"
)

func RunServer() {
type Server struct {
*mux.Router
log.Logger
}

func NewServer(logger log.Logger) *Server {
r := mux.NewRouter()

return &Server{
Router: r,
Logger: logger,
}
}

func (server *Server) RunServer() {
var wait time.Duration
flag.DurationVar(&wait, "graceful-timeout", time.Second*15, "the duration for which the server gracefully wait for existing connections to finish - e.g. 15s or 1m")
flag.Parse()

r := routes.SetupRoutes()
server.SetupUserRoutes()
server.SetupPostRoutes()
server.SetupApubRoutes()
server.SetupActivityRoutes()
server.NotFoundHandler = http.HandlerFunc(server.notFound)
server.MethodNotAllowedHandler = http.HandlerFunc(server.notAllowedMethod)
server.Use(server.logMiddleware)

srv := &http.Server{
Addr: "0.0.0.0:8080",
// Good practice to set timeouts to avoid Slowloris attacks.
WriteTimeout: time.Second * 15,
ReadTimeout: time.Second * 15,
IdleTimeout: time.Second * 60,
Handler: r, // Pass our instance of gorilla/mux in.
// pass embed of Server for *mux
Handler: server,
}

// Run our server in a goroutine so that it doesn't block.
go func() {
log.Info("Starting server")
server.Logger.Info("Starting server")
if err := srv.ListenAndServe(); err != nil {
log.Error("Error starting server", err)
server.Logger.Error("Error starting server", err)
}
}()

Expand All @@ -52,5 +73,5 @@ func RunServer() {
// Optionally, you could run srv.Shutdown in a goroutine and block on
// <-ctx.Done() if your application should wait for other services
// to finalize based on context cancellation.
log.Info("shutting down")
server.Logger.Info("shutting down")
}
Loading

0 comments on commit ba76425

Please sign in to comment.