forked from wgroeneveld/go-jamming
implement gofmt and add a filewatcher in Goland
This commit is contained in:
parent
3933e4d43b
commit
d4c854ef81
|
@ -0,0 +1,29 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectTasksOptions">
|
||||||
|
<TaskOptions isEnabled="true">
|
||||||
|
<option name="arguments" value="fmt $FilePath$" />
|
||||||
|
<option name="checkSyntaxErrors" value="true" />
|
||||||
|
<option name="description" />
|
||||||
|
<option name="exitCodeBehavior" value="ERROR" />
|
||||||
|
<option name="fileExtension" value="go" />
|
||||||
|
<option name="immediateSync" value="false" />
|
||||||
|
<option name="name" value="go fmt" />
|
||||||
|
<option name="output" value="$FilePath$" />
|
||||||
|
<option name="outputFilters">
|
||||||
|
<array />
|
||||||
|
</option>
|
||||||
|
<option name="outputFromStdout" value="false" />
|
||||||
|
<option name="program" value="$GoExecPath$" />
|
||||||
|
<option name="runOnExternalChanges" value="false" />
|
||||||
|
<option name="scopeName" value="Project Files" />
|
||||||
|
<option name="trackOnlyRoot" value="true" />
|
||||||
|
<option name="workingDir" value="$ProjectFileDir$" />
|
||||||
|
<envs>
|
||||||
|
<env name="GOROOT" value="$GOROOT$" />
|
||||||
|
<env name="GOPATH" value="$GOPATH$" />
|
||||||
|
<env name="PATH" value="$GoBinDirs$" />
|
||||||
|
</envs>
|
||||||
|
</TaskOptions>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -1,17 +1,15 @@
|
||||||
|
|
||||||
package index
|
package index
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"brainbaking.com/go-jamming/common"
|
"brainbaking.com/go-jamming/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Handle(conf *common.Config) http.HandlerFunc {
|
func Handle(conf *common.Config) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
fmt.Fprintf(w, "This is a Jamstack microservice endpoint.\nWanna start jammin' too? Go to https://github.com/wgroeneveld/go-jamming !")
|
fmt.Fprintf(w, "This is a Jamstack microservice endpoint.\nWanna start jammin' too? Go to https://github.com/wgroeneveld/go-jamming !")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -8,24 +7,24 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type loggingResponseWriter struct {
|
type loggingResponseWriter struct {
|
||||||
http.ResponseWriter
|
http.ResponseWriter
|
||||||
statusCode int
|
statusCode int
|
||||||
}
|
}
|
||||||
|
|
||||||
// mimic ResponseWriter's WriteHeader to capture the code
|
// mimic ResponseWriter's WriteHeader to capture the code
|
||||||
func (lrw *loggingResponseWriter) WriteHeader(code int) {
|
func (lrw *loggingResponseWriter) WriteHeader(code int) {
|
||||||
lrw.statusCode = code
|
lrw.statusCode = code
|
||||||
lrw.ResponseWriter.WriteHeader(code)
|
lrw.ResponseWriter.WriteHeader(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loggingMiddleware(next http.Handler) http.Handler {
|
func loggingMiddleware(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
logWriter := &loggingResponseWriter{w, http.StatusOK}
|
logWriter := &loggingResponseWriter{w, http.StatusOK}
|
||||||
next.ServeHTTP(logWriter, r)
|
next.ServeHTTP(logWriter, r)
|
||||||
log.Info().
|
log.Info().
|
||||||
Str("url", r.RequestURI).
|
Str("url", r.RequestURI).
|
||||||
Str("method", r.Method).
|
Str("method", r.Method).
|
||||||
Int("status", logWriter.statusCode).
|
Int("status", logWriter.statusCode).
|
||||||
Msg("handled")
|
Msg("handled")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package mf
|
package mf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"brainbaking.com/go-jamming/common"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"fmt"
|
"fmt"
|
||||||
"brainbaking.com/go-jamming/common"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ func (wm *Mention) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wm *Mention) AsPath(conf *common.Config) string {
|
func (wm *Mention) AsPath(conf *common.Config) string {
|
||||||
filename := fmt.Sprintf("%x", md5.Sum([]byte("source=" + wm.Source+ ",target=" + wm.Target)))
|
filename := fmt.Sprintf("%x", md5.Sum([]byte("source="+wm.Source+",target="+wm.Target)))
|
||||||
domain, _ := conf.FetchDomain(wm.Target)
|
domain, _ := conf.FetchDomain(wm.Target)
|
||||||
return conf.DataPath + "/" + domain + "/" + filename + ".json"
|
return conf.DataPath + "/" + domain + "/" + filename + ".json"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package mf
|
package mf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"brainbaking.com/go-jamming/common"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"willnorris.com/go/microformats"
|
"willnorris.com/go/microformats"
|
||||||
"brainbaking.com/go-jamming/common"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -12,19 +12,19 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type IndiewebAuthor struct {
|
type IndiewebAuthor struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Picture string `json:"picture"`
|
Picture string `json:"picture"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type IndiewebData struct {
|
type IndiewebData struct {
|
||||||
Author IndiewebAuthor `json:"author"`
|
Author IndiewebAuthor `json:"author"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
Published string `json:"published"`
|
Published string `json:"published"`
|
||||||
Url string `json:"url"`
|
Url string `json:"url"`
|
||||||
IndiewebType string `json:"type"`
|
IndiewebType string `json:"type"`
|
||||||
Source string `json:"source"`
|
Source string `json:"source"`
|
||||||
Target string `json:"target"`
|
Target string `json:"target"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func PublishedNow(utcOffset int) string {
|
func PublishedNow(utcOffset int) string {
|
||||||
|
@ -134,4 +134,4 @@ func DetermineContent(hEntry *microformats.Microformat) string {
|
||||||
}
|
}
|
||||||
contentEntry := Map(hEntry, "content")["value"]
|
contentEntry := Map(hEntry, "content")["value"]
|
||||||
return shorten(contentEntry)
|
return shorten(contentEntry)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
|
|
||||||
package pingback
|
package pingback
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/xml"
|
|
||||||
"github.com/rs/zerolog/log"
|
|
||||||
"brainbaking.com/go-jamming/app/mf"
|
"brainbaking.com/go-jamming/app/mf"
|
||||||
"brainbaking.com/go-jamming/app/webmention/recv"
|
"brainbaking.com/go-jamming/app/webmention/recv"
|
||||||
"brainbaking.com/go-jamming/common"
|
"brainbaking.com/go-jamming/common"
|
||||||
"brainbaking.com/go-jamming/rest"
|
"brainbaking.com/go-jamming/rest"
|
||||||
|
"encoding/xml"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandlePost(conf *common.Config) http.HandlerFunc {
|
func HandlePost(conf *common.Config) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
body, err := ioutil.ReadAll(r.Body)
|
body, err := ioutil.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pingbackError(w, "Unable to read request body")
|
pingbackError(w, "Unable to read request body")
|
||||||
|
@ -94,5 +93,3 @@ func pingbackError(w http.ResponseWriter, msg string) {
|
||||||
w.WriteHeader(200)
|
w.WriteHeader(200)
|
||||||
w.Write([]byte(xml))
|
w.Write([]byte(xml))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package send
|
package send
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/rs/zerolog/log"
|
|
||||||
"brainbaking.com/go-jamming/app/mf"
|
"brainbaking.com/go-jamming/app/mf"
|
||||||
"brainbaking.com/go-jamming/rest"
|
"brainbaking.com/go-jamming/rest"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package send
|
package send
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"brainbaking.com/go-jamming/app/mf"
|
"brainbaking.com/go-jamming/app/mf"
|
||||||
"brainbaking.com/go-jamming/mocks"
|
"brainbaking.com/go-jamming/mocks"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -35,4 +35,4 @@ func TestSendPingbackToEndpoint(t *testing.T) {
|
||||||
Target: "target",
|
Target: "target",
|
||||||
})
|
})
|
||||||
assert.Equal(t, expectedXml, capturedBody)
|
assert.Equal(t, expectedXml, capturedBody)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package pingback
|
package pingback
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"brainbaking.com/go-jamming/common"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"brainbaking.com/go-jamming/common"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,8 +16,8 @@ var conf *common.Config = &common.Config{
|
||||||
|
|
||||||
func TestValidate(t *testing.T) {
|
func TestValidate(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
label string
|
label string
|
||||||
xml string
|
xml string
|
||||||
expected bool
|
expected bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
@ -175,4 +175,4 @@ func TestValidate(t *testing.T) {
|
||||||
assert.Equal(t, tc.expected, result)
|
assert.Equal(t, tc.expected, result)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,11 @@ import "encoding/xml"
|
||||||
</param>
|
</param>
|
||||||
</params>
|
</params>
|
||||||
</methodCall>
|
</methodCall>
|
||||||
*/
|
*/
|
||||||
type XmlRPCMethodCall struct {
|
type XmlRPCMethodCall struct {
|
||||||
XMLName xml.Name `xml:"methodCall"`
|
XMLName xml.Name `xml:"methodCall"`
|
||||||
MethodName string `xml:"methodName"`
|
MethodName string `xml:"methodName"`
|
||||||
Params XmlRPCParams `xml:"params"`
|
Params XmlRPCParams `xml:"params"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rpc *XmlRPCMethodCall) Source() string {
|
func (rpc *XmlRPCMethodCall) Source() string {
|
||||||
|
@ -31,15 +31,15 @@ func (rpc *XmlRPCMethodCall) Target() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
type XmlRPCParams struct {
|
type XmlRPCParams struct {
|
||||||
XMLName xml.Name `xml:"params"`
|
XMLName xml.Name `xml:"params"`
|
||||||
Parameters []XmlRPCParam `xml:"param"`
|
Parameters []XmlRPCParam `xml:"param"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type XmlRPCParam struct {
|
type XmlRPCParam struct {
|
||||||
XMLName xml.Name `xml:"param"`
|
XMLName xml.Name `xml:"param"`
|
||||||
Value XmlRPCValue `xml:"value"`
|
Value XmlRPCValue `xml:"value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type XmlRPCValue struct {
|
type XmlRPCValue struct {
|
||||||
String string `xml:"string"`
|
String string `xml:"string"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,4 +27,4 @@ func TestMarshallValidXMLRPC(t *testing.T) {
|
||||||
assert.Equal(t, "pingback.ping", rpc.MethodName)
|
assert.Equal(t, "pingback.ping", rpc.MethodName)
|
||||||
assert.Equal(t, "https://brainbaking.com/kristien.html", rpc.Params.Parameters[0].Value.String)
|
assert.Equal(t, "https://brainbaking.com/kristien.html", rpc.Params.Parameters[0].Value.String)
|
||||||
assert.Equal(t, "https://kristienthoelen.be/2021/03/22/de-stadia-van-een-burn-out-in-welk-stadium-zit-jij/", rpc.Params.Parameters[1].Value.String)
|
assert.Equal(t, "https://kristienthoelen.be/2021/03/22/de-stadia-van-een-burn-out-in-welk-stadium-zit-jij/", rpc.Params.Parameters[1].Value.String)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -19,4 +18,3 @@ func (s *server) routes() {
|
||||||
s.router.HandleFunc("/webmention/{domain}/{token}", s.authorizedOnly(webmention.HandleGet(cnf))).Methods("GET")
|
s.router.HandleFunc("/webmention/{domain}/{token}", s.authorizedOnly(webmention.HandleGet(cnf))).Methods("GET")
|
||||||
s.router.HandleFunc("/webmention/{domain}/{token}", s.authorizedOnly(webmention.HandlePut(cnf))).Methods("PUT")
|
s.router.HandleFunc("/webmention/{domain}/{token}", s.authorizedOnly(webmention.HandlePut(cnf))).Methods("PUT")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -13,33 +12,35 @@ import (
|
||||||
|
|
||||||
type server struct {
|
type server struct {
|
||||||
router *mux.Router
|
router *mux.Router
|
||||||
conf *common.Config
|
conf *common.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
// mimicing NotFound: https://golang.org/src/net/http/server.go?s=64787:64830#L2076
|
// mimicing NotFound: https://golang.org/src/net/http/server.go?s=64787:64830#L2076
|
||||||
func unauthorized(w http.ResponseWriter, r *http.Request) { http.Error(w, "401 unauthorized", http.StatusUnauthorized) }
|
func unauthorized(w http.ResponseWriter, r *http.Request) {
|
||||||
|
http.Error(w, "401 unauthorized", http.StatusUnauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *server) authorizedOnly(h http.HandlerFunc) http.HandlerFunc {
|
func (s *server) authorizedOnly(h http.HandlerFunc) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
if vars["token"] != s.conf.Token || !s.conf.IsAnAllowedDomain(vars["domain"]) {
|
if vars["token"] != s.conf.Token || !s.conf.IsAnAllowedDomain(vars["domain"]) {
|
||||||
unauthorized(w, r)
|
unauthorized(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h(w, r)
|
h(w, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start() {
|
func Start() {
|
||||||
r := mux.NewRouter()
|
r := mux.NewRouter()
|
||||||
config := common.Configure()
|
config := common.Configure()
|
||||||
config.SetupDataDirs()
|
config.SetupDataDirs()
|
||||||
server := &server{router: r, conf: config}
|
server := &server{router: r, conf: config}
|
||||||
|
|
||||||
server.routes()
|
server.routes()
|
||||||
http.Handle("/", r)
|
http.Handle("/", r)
|
||||||
r.Use(loggingMiddleware)
|
r.Use(loggingMiddleware)
|
||||||
|
|
||||||
log.Info().Int("port", server.conf.Port).Msg("Serving...")
|
log.Info().Int("port", server.conf.Port).Msg("Serving...")
|
||||||
http.ListenAndServe(":" + strconv.Itoa(server.conf.Port), nil)
|
http.ListenAndServe(":"+strconv.Itoa(server.conf.Port), nil)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"brainbaking.com/go-jamming/common"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"brainbaking.com/go-jamming/common"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var conf = &common.Config{
|
var conf = &common.Config{
|
||||||
Token: "boemsjakkalakka",
|
Token: "boemsjakkalakka",
|
||||||
AllowedWebmentionSources: []string{ "http://ewelja.be" },
|
AllowedWebmentionSources: []string{"http://ewelja.be"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAuthorizedOnlyUnauthorizedWithWrongToken(t *testing.T) {
|
func TestAuthorizedOnlyUnauthorizedWithWrongToken(t *testing.T) {
|
||||||
|
@ -26,7 +26,7 @@ func TestAuthorizedOnlyUnauthorizedWithWrongToken(t *testing.T) {
|
||||||
r, _ := http.NewRequest("PUT", "/whatever", nil)
|
r, _ := http.NewRequest("PUT", "/whatever", nil)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
r = mux.SetURLVars(r, map[string]string{
|
r = mux.SetURLVars(r, map[string]string{
|
||||||
"token": "invalid",
|
"token": "invalid",
|
||||||
"domain": conf.AllowedWebmentionSources[0],
|
"domain": conf.AllowedWebmentionSources[0],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ func TestAuthorizedOnlyUnauthorizedWithWrongDomain(t *testing.T) {
|
||||||
r, _ := http.NewRequest("PUT", "/whatever", nil)
|
r, _ := http.NewRequest("PUT", "/whatever", nil)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
r = mux.SetURLVars(r, map[string]string{
|
r = mux.SetURLVars(r, map[string]string{
|
||||||
"token": conf.Token,
|
"token": conf.Token,
|
||||||
"domain": "https://sexymoddafokkas.be",
|
"domain": "https://sexymoddafokkas.be",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ func TestAuthorizedOnlyOkIfTokenAndDomainMatch(t *testing.T) {
|
||||||
r, _ := http.NewRequest("PUT", "/whatever", nil)
|
r, _ := http.NewRequest("PUT", "/whatever", nil)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
r = mux.SetURLVars(r, map[string]string{
|
r = mux.SetURLVars(r, map[string]string{
|
||||||
"token": conf.Token,
|
"token": conf.Token,
|
||||||
"domain": conf.AllowedWebmentionSources[0],
|
"domain": conf.AllowedWebmentionSources[0],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
|
|
||||||
package webmention
|
package webmention
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"brainbaking.com/go-jamming/app/mf"
|
"brainbaking.com/go-jamming/app/mf"
|
||||||
"brainbaking.com/go-jamming/app/webmention/recv"
|
"brainbaking.com/go-jamming/app/webmention/recv"
|
||||||
"brainbaking.com/go-jamming/app/webmention/send"
|
"brainbaking.com/go-jamming/app/webmention/send"
|
||||||
|
"fmt"
|
||||||
|
"github.com/gorilla/mux"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"brainbaking.com/go-jamming/common"
|
"brainbaking.com/go-jamming/common"
|
||||||
|
@ -16,13 +15,13 @@ import (
|
||||||
var httpClient = &rest.HttpClient{}
|
var httpClient = &rest.HttpClient{}
|
||||||
|
|
||||||
func HandleGet(conf *common.Config) http.HandlerFunc {
|
func HandleGet(conf *common.Config) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
fmt.Println("handling get")
|
fmt.Println("handling get")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandlePut(conf *common.Config) http.HandlerFunc {
|
func HandlePut(conf *common.Config) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
since := getSinceQueryParam(r)
|
since := getSinceQueryParam(r)
|
||||||
domain := mux.Vars(r)["domain"]
|
domain := mux.Vars(r)["domain"]
|
||||||
|
|
||||||
|
@ -45,30 +44,29 @@ func getSinceQueryParam(r *http.Request) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandlePost(conf *common.Config) http.HandlerFunc {
|
func HandlePost(conf *common.Config) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
r.ParseForm()
|
r.ParseForm()
|
||||||
if !validate(r, r.Header, conf) {
|
if !validate(r, r.Header, conf) {
|
||||||
rest.BadRequest(w)
|
rest.BadRequest(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
target := r.FormValue("target")
|
|
||||||
if !isValidTargetUrl(target, httpClient) {
|
|
||||||
rest.BadRequest(w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
wm := mf.Mention{
|
target := r.FormValue("target")
|
||||||
Source: r.FormValue("source"),
|
if !isValidTargetUrl(target, httpClient) {
|
||||||
Target: target,
|
rest.BadRequest(w)
|
||||||
}
|
return
|
||||||
recv := &recv.Receiver{
|
}
|
||||||
RestClient: httpClient,
|
|
||||||
Conf: conf,
|
|
||||||
}
|
|
||||||
|
|
||||||
go recv.Receive(wm)
|
wm := mf.Mention{
|
||||||
rest.Accept(w)
|
Source: r.FormValue("source"),
|
||||||
}
|
Target: target,
|
||||||
|
}
|
||||||
|
recv := &recv.Receiver{
|
||||||
|
RestClient: httpClient,
|
||||||
|
Conf: conf,
|
||||||
|
}
|
||||||
|
|
||||||
|
go recv.Receive(wm)
|
||||||
|
rest.Accept(w)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
|
|
||||||
package recv
|
package recv
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"brainbaking.com/go-jamming/app/mf"
|
"brainbaking.com/go-jamming/app/mf"
|
||||||
"brainbaking.com/go-jamming/common"
|
"brainbaking.com/go-jamming/common"
|
||||||
"brainbaking.com/go-jamming/rest"
|
"brainbaking.com/go-jamming/rest"
|
||||||
|
"encoding/json"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
@ -16,9 +15,8 @@ import (
|
||||||
"willnorris.com/go/microformats"
|
"willnorris.com/go/microformats"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// used as a "class" to iject dependencies, just to be able to test. Do NOT like htis.
|
||||||
// used as a "class" to iject dependencies, just to be able to test. Do NOT like htis.
|
// Is there a better way? e.g. in validate, I just pass rest.Client as an arg. Not great either.
|
||||||
// Is there a better way? e.g. in validate, I just pass rest.Client as an arg. Not great either.
|
|
||||||
type Receiver struct {
|
type Receiver struct {
|
||||||
RestClient rest.Client
|
RestClient rest.Client
|
||||||
Conf *common.Config
|
Conf *common.Config
|
||||||
|
@ -29,7 +27,7 @@ func (recv *Receiver) Receive(wm mf.Mention) {
|
||||||
body, geterr := recv.RestClient.GetBody(wm.Source)
|
body, geterr := recv.RestClient.GetBody(wm.Source)
|
||||||
|
|
||||||
if geterr != nil {
|
if geterr != nil {
|
||||||
log.Warn().Str("source", wm.Source).Msg(" ABORT: invalid url")
|
log.Warn().Str("source", wm.Source).Msg(" ABORT: invalid url")
|
||||||
recv.deletePossibleOlderWebmention(wm)
|
recv.deletePossibleOlderWebmention(wm)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -50,7 +48,6 @@ func getHEntry(data *microformats.Data) *microformats.Microformat {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (recv *Receiver) processSourceBody(body string, wm mf.Mention) {
|
func (recv *Receiver) processSourceBody(body string, wm mf.Mention) {
|
||||||
if !strings.Contains(body, wm.Target) {
|
if !strings.Contains(body, wm.Target) {
|
||||||
log.Warn().Str("target", wm.Target).Msg("ABORT: no mention of target found in html src of source!")
|
log.Warn().Str("target", wm.Target).Msg("ABORT: no mention of target found in html src of source!")
|
||||||
|
@ -92,14 +89,14 @@ func (recv *Receiver) parseBodyAsIndiewebSite(hEntry *microformats.Microformat,
|
||||||
return &mf.IndiewebData{
|
return &mf.IndiewebData{
|
||||||
Name: name,
|
Name: name,
|
||||||
Author: mf.IndiewebAuthor{
|
Author: mf.IndiewebAuthor{
|
||||||
Name: mf.DetermineAuthorName(hEntry),
|
Name: mf.DetermineAuthorName(hEntry),
|
||||||
Picture: pic,
|
Picture: pic,
|
||||||
},
|
},
|
||||||
Content: mf.DetermineContent(hEntry),
|
Content: mf.DetermineContent(hEntry),
|
||||||
Url: mf.DetermineUrl(hEntry, wm.Source),
|
Url: mf.DetermineUrl(hEntry, wm.Source),
|
||||||
Published: mf.DeterminePublishedDate(hEntry, recv.Conf.UtcOffset),
|
Published: mf.DeterminePublishedDate(hEntry, recv.Conf.UtcOffset),
|
||||||
Source: wm.Source,
|
Source: wm.Source,
|
||||||
Target: wm.Target,
|
Target: wm.Target,
|
||||||
IndiewebType: mfType,
|
IndiewebType: mfType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,12 +112,12 @@ func (recv *Receiver) parseBodyAsNonIndiewebSite(body string, wm mf.Mention) *mf
|
||||||
Author: mf.IndiewebAuthor{
|
Author: mf.IndiewebAuthor{
|
||||||
Name: wm.Source,
|
Name: wm.Source,
|
||||||
},
|
},
|
||||||
Name: title,
|
Name: title,
|
||||||
Content: title,
|
Content: title,
|
||||||
Published: mf.PublishedNow(recv.Conf.UtcOffset),
|
Published: mf.PublishedNow(recv.Conf.UtcOffset),
|
||||||
Url: wm.Source,
|
Url: wm.Source,
|
||||||
IndiewebType: "mention",
|
IndiewebType: "mention",
|
||||||
Source: wm.Source,
|
Source: wm.Source,
|
||||||
Target: wm.Target,
|
Target: wm.Target,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
|
|
||||||
package recv
|
package recv
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"brainbaking.com/go-jamming/app/mf"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"brainbaking.com/go-jamming/app/mf"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -15,13 +14,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var conf = &common.Config{
|
var conf = &common.Config{
|
||||||
AllowedWebmentionSources: []string {
|
AllowedWebmentionSources: []string{
|
||||||
"jefklakscodex.com",
|
"jefklakscodex.com",
|
||||||
},
|
},
|
||||||
DataPath: "testdata",
|
DataPath: "testdata",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func TestConvertWebmentionToPath(t *testing.T) {
|
func TestConvertWebmentionToPath(t *testing.T) {
|
||||||
wm := mf.Mention{
|
wm := mf.Mention{
|
||||||
Source: "https://brainbaking.com",
|
Source: "https://brainbaking.com",
|
||||||
|
@ -37,7 +35,7 @@ func TestConvertWebmentionToPath(t *testing.T) {
|
||||||
func writeSomethingTo(filename string) {
|
func writeSomethingTo(filename string) {
|
||||||
file, _ := os.Create(filename)
|
file, _ := os.Create(filename)
|
||||||
file.WriteString("lolz")
|
file.WriteString("lolz")
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReceive(t *testing.T) {
|
func TestReceive(t *testing.T) {
|
||||||
|
@ -45,7 +43,7 @@ func TestReceive(t *testing.T) {
|
||||||
label string
|
label string
|
||||||
wm mf.Mention
|
wm mf.Mention
|
||||||
json string
|
json string
|
||||||
} {
|
}{
|
||||||
{
|
{
|
||||||
label: "receive a Webmention bookmark via twitter",
|
label: "receive a Webmention bookmark via twitter",
|
||||||
wm: mf.Mention{
|
wm: mf.Mention{
|
||||||
|
@ -137,7 +135,7 @@ func TestReceiveTargetDoesNotExistAnymoreDeletesPossiblyOlderWebmention(t *testi
|
||||||
GetBodyFunc: func(url string) (string, error) {
|
GetBodyFunc: func(url string) (string, error) {
|
||||||
return "", errors.New("whoops")
|
return "", errors.New("whoops")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
receiver := &Receiver{
|
receiver := &Receiver{
|
||||||
Conf: conf,
|
Conf: conf,
|
||||||
RestClient: client,
|
RestClient: client,
|
||||||
|
@ -181,4 +179,3 @@ func TestProcessSourceBodyAbortsIfNoMentionOfTargetFoundInSourceHtml(t *testing.
|
||||||
receiver.processSourceBody("<html>my nice body</html>", wm)
|
receiver.processSourceBody("<html>my nice body</html>", wm)
|
||||||
assert.NoFileExists(t, wm.AsPath(conf))
|
assert.NoFileExists(t, wm.AsPath(conf))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package send
|
package send
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/rs/zerolog/log"
|
|
||||||
"brainbaking.com/go-jamming/app/mf"
|
"brainbaking.com/go-jamming/app/mf"
|
||||||
"brainbaking.com/go-jamming/app/pingback/send"
|
"brainbaking.com/go-jamming/app/pingback/send"
|
||||||
"brainbaking.com/go-jamming/common"
|
"brainbaking.com/go-jamming/common"
|
||||||
"brainbaking.com/go-jamming/rest"
|
"brainbaking.com/go-jamming/rest"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Sender struct {
|
type Sender struct {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package webmention
|
package webmention
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
|
|
||||||
package webmention
|
package webmention
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
"brainbaking.com/go-jamming/common"
|
"brainbaking.com/go-jamming/common"
|
||||||
"brainbaking.com/go-jamming/mocks"
|
"brainbaking.com/go-jamming/mocks"
|
||||||
|
@ -17,14 +16,18 @@ type httpReqMock struct {
|
||||||
type httpHeaderMock struct {
|
type httpHeaderMock struct {
|
||||||
contentType string
|
contentType string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mock *httpHeaderMock) Get(key string) string {
|
func (mock *httpHeaderMock) Get(key string) string {
|
||||||
return mock.contentType
|
return mock.contentType
|
||||||
}
|
}
|
||||||
func (mock *httpReqMock) FormValue(key string) string {
|
func (mock *httpReqMock) FormValue(key string) string {
|
||||||
switch key {
|
switch key {
|
||||||
case "source": return mock.source
|
case "source":
|
||||||
case "target": return mock.target
|
return mock.source
|
||||||
default: return ""
|
case "target":
|
||||||
|
return mock.target
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func buildHttpReq(source string, target string) *httpReqMock {
|
func buildHttpReq(source string, target string) *httpReqMock {
|
||||||
|
@ -38,12 +41,12 @@ var config = common.Configure()
|
||||||
|
|
||||||
func TestValidate(t *testing.T) {
|
func TestValidate(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
label string
|
label string
|
||||||
source string
|
source string
|
||||||
target string
|
target string
|
||||||
contentType string
|
contentType string
|
||||||
expected bool
|
expected bool
|
||||||
} {
|
}{
|
||||||
{
|
{
|
||||||
"is valid if source and target https urls",
|
"is valid if source and target https urls",
|
||||||
"http://brainbaking.com/bla1",
|
"http://brainbaking.com/bla1",
|
||||||
|
@ -105,14 +108,14 @@ func TestValidate(t *testing.T) {
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
t.Run(tc.label, func(t *testing.T) {
|
t.Run(tc.label, func(t *testing.T) {
|
||||||
httpReq := buildHttpReq(tc.source, tc.target)
|
httpReq := buildHttpReq(tc.source, tc.target)
|
||||||
httpHeader := &httpHeaderMock{ contentType: tc.contentType }
|
httpHeader := &httpHeaderMock{contentType: tc.contentType}
|
||||||
|
|
||||||
actual := validate(httpReq, httpHeader, config)
|
actual := validate(httpReq, httpHeader, config)
|
||||||
if actual != tc.expected {
|
if actual != tc.expected {
|
||||||
t.Fatalf("got %v, want %v", actual, tc.expected)
|
t.Fatalf("got %v, want %v", actual, tc.expected)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIsValidTargetUrlFalseIfGetFails(t *testing.T) {
|
func TestIsValidTargetUrlFalseIfGetFails(t *testing.T) {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -11,11 +10,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Port int
|
Port int
|
||||||
Token string
|
Token string
|
||||||
UtcOffset int
|
UtcOffset int
|
||||||
DataPath string
|
DataPath string
|
||||||
AllowedWebmentionSources []string
|
AllowedWebmentionSources []string
|
||||||
DisallowedWebmentionDomains []string
|
DisallowedWebmentionDomains []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,15 +38,15 @@ func (c *Config) FetchDomain(url string) (string, error) {
|
||||||
|
|
||||||
func (c *Config) SetupDataDirs() {
|
func (c *Config) SetupDataDirs() {
|
||||||
for _, domain := range c.AllowedWebmentionSources {
|
for _, domain := range c.AllowedWebmentionSources {
|
||||||
os.MkdirAll(c.DataPath + "/" + domain, os.ModePerm)
|
os.MkdirAll(c.DataPath+"/"+domain, os.ModePerm)
|
||||||
log.Info().Str("allowedDomain", domain).Msg("Configured")
|
log.Info().Str("allowedDomain", domain).Msg("Configured")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Configure() (c *Config) {
|
func Configure() (c *Config) {
|
||||||
portstr := os.Getenv("PORT")
|
portstr := os.Getenv("PORT")
|
||||||
port, err := strconv.Atoi(portstr)
|
port, err := strconv.Atoi(portstr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
port = 1337
|
port = 1337
|
||||||
}
|
}
|
||||||
token := os.Getenv("TOKEN")
|
token := os.Getenv("TOKEN")
|
||||||
|
@ -56,12 +55,12 @@ func Configure() (c *Config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
c = &Config{
|
c = &Config{
|
||||||
Port: port,
|
Port: port,
|
||||||
Token: token,
|
Token: token,
|
||||||
UtcOffset: 60,
|
UtcOffset: 60,
|
||||||
DataPath: "data",
|
DataPath: "data",
|
||||||
AllowedWebmentionSources: []string{ "brainbaking.com", "jefklakscodex.com" },
|
AllowedWebmentionSources: []string{"brainbaking.com", "jefklakscodex.com"},
|
||||||
DisallowedWebmentionDomains: []string{ "youtube.com" },
|
DisallowedWebmentionDomains: []string{"youtube.com"},
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package common
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
func TestIncludesElemInArrayTrue(t *testing.T) {
|
func TestIncludesElemInArrayTrue(t *testing.T) {
|
||||||
arr := []string{ "one", "two"}
|
arr := []string{"one", "two"}
|
||||||
|
|
||||||
result := Includes(arr, "two")
|
result := Includes(arr, "two")
|
||||||
if result != true {
|
if result != true {
|
||||||
|
@ -12,7 +12,7 @@ func TestIncludesElemInArrayTrue(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIncludesElemNotInArrayFalse(t *testing.T) {
|
func TestIncludesElemNotInArrayFalse(t *testing.T) {
|
||||||
arr := []string{ "one", "two"}
|
arr := []string{"one", "two"}
|
||||||
|
|
||||||
result := Includes(arr, "three")
|
result := Includes(arr, "three")
|
||||||
if result != false {
|
if result != false {
|
||||||
|
|
13
main.go
13
main.go
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -6,15 +5,15 @@ import (
|
||||||
|
|
||||||
"brainbaking.com/go-jamming/app"
|
"brainbaking.com/go-jamming/app"
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
|
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
|
||||||
// TODO this should only be enabled in local mode. Fix with config?
|
// TODO this should only be enabled in local mode. Fix with config?
|
||||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
||||||
|
|
||||||
log.Debug().Msg("Let's a go!")
|
log.Debug().Msg("Let's a go!")
|
||||||
app.Start()
|
app.Start()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,20 @@
|
||||||
|
|
||||||
package mocks
|
package mocks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// neat trick! https://medium.com/@matryer/meet-moq-easily-mock-interfaces-in-go-476444187d10
|
// neat trick! https://medium.com/@matryer/meet-moq-easily-mock-interfaces-in-go-476444187d10
|
||||||
type RestClientMock struct {
|
type RestClientMock struct {
|
||||||
GetFunc func(string) (*http.Response, error)
|
GetFunc func(string) (*http.Response, error)
|
||||||
GetBodyFunc func(string) (string, error)
|
GetBodyFunc func(string) (string, error)
|
||||||
PostFunc func(string, string, string) error
|
PostFunc func(string, string, string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// although these are still requied to match the rest.Client interface.
|
// although these are still requied to match the rest.Client interface.
|
||||||
func (m *RestClientMock) Get(url string) (*http.Response, error) {
|
func (m *RestClientMock) Get(url string) (*http.Response, error) {
|
||||||
return m.GetFunc(url)
|
return m.GetFunc(url)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func mainz() {
|
func mainz() {
|
||||||
|
@ -14,11 +14,11 @@ func mainz() {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err2 := ioutil.ReadAll(resp.Body)
|
body, err2 := ioutil.ReadAll(resp.Body)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("tis ditte")
|
fmt.Printf("tis ditte")
|
||||||
fmt.Printf("%s", body)
|
fmt.Printf("%s", body)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package rest
|
package rest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -32,9 +31,9 @@ func (client *HttpClient) GetBody(url string) (string, error) {
|
||||||
return "", geterr
|
return "", geterr
|
||||||
}
|
}
|
||||||
|
|
||||||
if resp.StatusCode < 200 || resp.StatusCode > 299 {
|
if resp.StatusCode < 200 || resp.StatusCode > 299 {
|
||||||
return "", fmt.Errorf("Status code for %s is not OK (%d)", url, resp.StatusCode)
|
return "", fmt.Errorf("Status code for %s is not OK (%d)", url, resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
body, readerr := ioutil.ReadAll(resp.Body)
|
body, readerr := ioutil.ReadAll(resp.Body)
|
||||||
|
@ -45,7 +44,6 @@ func (client *HttpClient) GetBody(url string) (string, error) {
|
||||||
return string(body), nil
|
return string(body), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (client *HttpClient) Get(url string) (*http.Response, error) {
|
func (client *HttpClient) Get(url string) (*http.Response, error) {
|
||||||
return http.Get(url)
|
return http.Get(url)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package rest
|
package rest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package rest
|
package rest
|
||||||
|
|
||||||
// great, these are needed to do the structural typing for the tests...
|
// great, these are needed to do the structural typing for the tests...
|
||||||
|
|
Loading…
Reference in New Issue