WIP receiving webmentionsi. #7
This commit is contained in:
parent
179559250a
commit
691158cd0e
|
@ -26,6 +26,9 @@ Each directory in the `/users/` directory of a repository is considered a user.
|
|||
\- media/
|
||||
-- Contains all media files used in the blog post.
|
||||
-- All files in this folder will be publicly available
|
||||
\- webmention/
|
||||
\- <hash>.yml
|
||||
-- Contains data for a received webmention
|
||||
\- meta/
|
||||
\- base.html
|
||||
-- The template used to render all sites
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/julienschmidt/httprouter"
|
||||
)
|
||||
|
@ -56,6 +57,59 @@ func userIndexHandler(repo *owl.Repository) func(http.ResponseWriter, *http.Requ
|
|||
}
|
||||
}
|
||||
|
||||
func userWebmentionHandler(repo *owl.Repository) func(http.ResponseWriter, *http.Request, httprouter.Params) {
|
||||
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||
user, err := getUserFromRepo(repo, ps)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte("User not found"))
|
||||
return
|
||||
}
|
||||
err = r.ParseForm()
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte("Unable to parse form data"))
|
||||
return
|
||||
}
|
||||
params := r.PostForm
|
||||
target := params["target"]
|
||||
source := params["source"]
|
||||
if len(target) == 0 {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte("No target provided"))
|
||||
return
|
||||
}
|
||||
if len(source) == 0 {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte("No source provided"))
|
||||
return
|
||||
}
|
||||
|
||||
parts := strings.Split(target[0], "/")
|
||||
if len(parts) < 2 {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte("Not found"))
|
||||
return
|
||||
}
|
||||
postId := parts[len(parts)-2]
|
||||
post, err := user.GetPost(postId)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte("Post not found"))
|
||||
return
|
||||
}
|
||||
err = post.AddWebmention(source[0])
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte("Unable to process webmention"))
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
w.Write([]byte(""))
|
||||
}
|
||||
}
|
||||
|
||||
func userRSSHandler(repo *owl.Repository) func(http.ResponseWriter, *http.Request, httprouter.Params) {
|
||||
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||
user, err := getUserFromRepo(repo, ps)
|
||||
|
|
|
@ -14,6 +14,7 @@ func Router(repo *owl.Repository) http.Handler {
|
|||
router.ServeFiles("/static/*filepath", http.Dir(repo.StaticDir()))
|
||||
router.GET("/", repoIndexHandler(repo))
|
||||
router.GET("/user/:user/", userIndexHandler(repo))
|
||||
router.POST("/user/:user/webmention/", userWebmentionHandler(repo))
|
||||
router.GET("/user/:user/index.xml", userRSSHandler(repo))
|
||||
router.GET("/user/:user/posts/:post/", postHandler(repo))
|
||||
router.GET("/user/:user/posts/:post/media/*filepath", postMediaHandler(repo))
|
||||
|
@ -25,6 +26,7 @@ func SingleUserRouter(repo *owl.Repository) http.Handler {
|
|||
router := httprouter.New()
|
||||
router.ServeFiles("/static/*filepath", http.Dir(repo.StaticDir()))
|
||||
router.GET("/", userIndexHandler(repo))
|
||||
router.POST("/webmention/", userWebmentionHandler(repo))
|
||||
router.GET("/index.xml", userRSSHandler(repo))
|
||||
router.GET("/posts/:post/", postHandler(repo))
|
||||
router.GET("/posts/:post/media/*filepath", postMediaHandler(repo))
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
package main_test
|
||||
|
||||
import (
|
||||
main "h4kor/owl-blogs/cmd/owl-web"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestWebmentionHandleAccepts(t *testing.T) {
|
||||
repo := getTestRepo()
|
||||
user, _ := repo.CreateUser("test-1")
|
||||
post, _ := user.CreateNewPost("post-1")
|
||||
|
||||
target := post.FullUrl()
|
||||
source := "https://example.com"
|
||||
data := url.Values{}
|
||||
data.Set("target", target)
|
||||
data.Set("source", source)
|
||||
|
||||
// Create Request and Response
|
||||
req, err := http.NewRequest("POST", user.UrlPath()+"webmention/", strings.NewReader(data.Encode()))
|
||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
rr := httptest.NewRecorder()
|
||||
router := main.Router(&repo)
|
||||
router.ServeHTTP(rr, req)
|
||||
|
||||
// Check the status code is what we expect.
|
||||
if status := rr.Code; status != http.StatusAccepted {
|
||||
t.Errorf("handler returned wrong status code: got %v want %v",
|
||||
status, http.StatusAccepted)
|
||||
t.Errorf("Body: %v", rr.Body)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestWebmentionWrittenToPost(t *testing.T) {
|
||||
repo := getTestRepo()
|
||||
user, _ := repo.CreateUser("test-1")
|
||||
post, _ := user.CreateNewPost("post-1")
|
||||
|
||||
target := post.FullUrl()
|
||||
source := "https://example.com"
|
||||
data := url.Values{}
|
||||
data.Set("target", target)
|
||||
data.Set("source", source)
|
||||
|
||||
// Create Request and Response
|
||||
req, err := http.NewRequest("POST", user.UrlPath()+"webmention/", strings.NewReader(data.Encode()))
|
||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
rr := httptest.NewRecorder()
|
||||
router := main.Router(&repo)
|
||||
router.ServeHTTP(rr, req)
|
||||
|
||||
// Check the status code is what we expect.
|
||||
if status := rr.Code; status != http.StatusAccepted {
|
||||
t.Errorf("handler returned wrong status code: got %v want %v",
|
||||
status, http.StatusAccepted)
|
||||
return
|
||||
}
|
||||
|
||||
if len(post.Webmentions()) != 1 {
|
||||
t.Errorf("no webmention written to post")
|
||||
}
|
||||
|
||||
}
|
18
post.go
18
post.go
|
@ -2,7 +2,10 @@ package owl
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/yuin/goldmark"
|
||||
|
@ -39,6 +42,10 @@ func (post Post) MediaDir() string {
|
|||
return path.Join(post.Dir(), "media")
|
||||
}
|
||||
|
||||
func (post Post) WebmentionDir() string {
|
||||
return path.Join(post.Dir(), "webmention")
|
||||
}
|
||||
|
||||
func (post Post) UrlPath() string {
|
||||
return post.user.UrlPath() + "posts/" + post.id + "/"
|
||||
}
|
||||
|
@ -139,3 +146,14 @@ func (post *Post) LoadMeta() error {
|
|||
post.meta = meta
|
||||
return nil
|
||||
}
|
||||
|
||||
func (post *Post) AddWebmention(source string) error {
|
||||
hash := sha256.Sum256([]byte(source))
|
||||
hashStr := base64.URLEncoding.EncodeToString(hash[:])
|
||||
data := "source: " + source
|
||||
return os.WriteFile(path.Join(post.WebmentionDir(), hashStr+".yml"), []byte(data), 0644)
|
||||
}
|
||||
|
||||
func (post *Post) Webmentions() []string {
|
||||
return listDir(post.WebmentionDir())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue