diff --git a/.travis.yml b/.travis.yml index 7b652cd25..c9ad822cc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,8 @@ install: - go get github.com/golang/lint/golint - go get github.com/fzipp/gocyclo -script: gb build github.com/matrix-org/dendrite/roomserver/roomserver && ./hooks/pre-commit +script: + - gb build github.com/matrix-org/dendrite/roomserver/roomserver && ./hooks/pre-commit notifications: webhooks: diff --git a/README.md b/README.md index e3fe4e197..636cc49e1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Dendrite +# Dendrite [![Build Status](https://travis-ci.org/matrix-org/dendrite.svg?branch=master)](https://travis-ci.org/matrix-org/dendrite) Dendrite will be a matrix homeserver written in go. diff --git a/src/github.com/matrix-org/dendrite/clientapi/clientapi.go b/src/github.com/matrix-org/dendrite/clientapi/clientapi.go index b646904d9..95055b29e 100644 --- a/src/github.com/matrix-org/dendrite/clientapi/clientapi.go +++ b/src/github.com/matrix-org/dendrite/clientapi/clientapi.go @@ -1,18 +1,40 @@ package main import ( - "github.com/matrix-org/dendrite/clientapi/routing" "net/http" "os" + "path/filepath" + + "github.com/matrix-org/dendrite/clientapi/routing" log "github.com/Sirupsen/logrus" + "github.com/matrix-org/dugong" ) +func setupLogging(logDir string) { + _ = os.Mkdir(logDir, os.ModePerm) + log.AddHook(dugong.NewFSHook( + filepath.Join(logDir, "info.log"), + filepath.Join(logDir, "warn.log"), + filepath.Join(logDir, "error.log"), + &log.TextFormatter{ + TimestampFormat: "2006-01-02 15:04:05.000000", + DisableColors: true, + DisableTimestamp: false, + DisableSorting: false, + }, &dugong.DailyRotationSchedule{GZip: true}, + )) +} + func main() { bindAddr := os.Getenv("BIND_ADDRESS") if bindAddr == "" { log.Panic("No BIND_ADDRESS environment variable found.") } + logDir := os.Getenv("LOG_DIR") + if logDir != "" { + setupLogging(logDir) + } log.Info("Starting clientapi") routing.Setup(http.DefaultServeMux, http.DefaultClient) log.Fatal(http.ListenAndServe(bindAddr, nil)) diff --git a/src/github.com/matrix-org/dendrite/clientapi/jsonerror/jsonerror.go b/src/github.com/matrix-org/dendrite/clientapi/jsonerror/jsonerror.go new file mode 100644 index 000000000..a0111197c --- /dev/null +++ b/src/github.com/matrix-org/dendrite/clientapi/jsonerror/jsonerror.go @@ -0,0 +1,62 @@ +package jsonerror + +import "fmt" + +// MatrixError represents the "standard error response" in Matrix. +// http://matrix.org/docs/spec/client_server/r0.2.0.html#api-standards +type MatrixError struct { + ErrCode string `json:"errcode"` + Err string `json:"error"` +} + +func (e *MatrixError) Error() string { + return fmt.Sprintf("%s: %s", e.ErrCode, e.Err) +} + +// Forbidden is an error when the client tries to access a resource +// they are not allowed to access. +func Forbidden(msg string) *MatrixError { + return &MatrixError{"M_FORBIDDEN", msg} +} + +// BadJSON is an error when the client supplies malformed JSON. +func BadJSON(msg string) *MatrixError { + return &MatrixError{"M_BAD_JSON", msg} +} + +// NotJSON is an error when the client supplies something that is not JSON +// to a JSON endpoint. +func NotJSON(msg string) *MatrixError { + return &MatrixError{"M_NOT_JSON", msg} +} + +// NotFound is an error when the client tries to access an unknown resource. +func NotFound(msg string) *MatrixError { + return &MatrixError{"M_NOT_FOUND", msg} +} + +// MissingToken is an error when the client tries to access a resource which +// requires authentication without supplying credentials. +func MissingToken(msg string) *MatrixError { + return &MatrixError{"M_MISSING_TOKEN", msg} +} + +// UnknownToken is an error when the client tries to access a resource which +// requires authentication and supplies a valid, but out-of-date token. +func UnknownToken(msg string) *MatrixError { + return &MatrixError{"M_UNKNOWN_TOKEN", msg} +} + +// LimitExceededError is a rate-limiting error. +type LimitExceededError struct { + MatrixError + RetryAfterMS int64 `json:"retry_after_ms,omitempty"` +} + +// LimitExceeded is an error when the client tries to send events too quickly. +func LimitExceeded(msg string, retryAfterMS int64) *LimitExceededError { + return &LimitExceededError{ + MatrixError: MatrixError{"M_LIMIT_EXCEEDED", msg}, + RetryAfterMS: retryAfterMS, + } +} diff --git a/src/github.com/matrix-org/dendrite/clientapi/jsonerror/jsonerror_test.go b/src/github.com/matrix-org/dendrite/clientapi/jsonerror/jsonerror_test.go new file mode 100644 index 000000000..33e2ede83 --- /dev/null +++ b/src/github.com/matrix-org/dendrite/clientapi/jsonerror/jsonerror_test.go @@ -0,0 +1,30 @@ +package jsonerror + +import ( + "encoding/json" + "testing" +) + +func TestLimitExceeded(t *testing.T) { + e := LimitExceeded("too fast", 5000) + jsonBytes, err := json.Marshal(&e) + if err != nil { + t.Fatalf("TestLimitExceeded: Failed to marshal LimitExceeded error. %s", err.Error()) + } + want := `{"errcode":"M_LIMIT_EXCEEDED","error":"too fast","retry_after_ms":5000}` + if string(jsonBytes) != want { + t.Errorf("TestLimitExceeded: want %s, got %s", want, string(jsonBytes)) + } +} + +func TestForbidden(t *testing.T) { + e := Forbidden("you shall not pass") + jsonBytes, err := json.Marshal(&e) + if err != nil { + t.Fatalf("TestForbidden: Failed to marshal Forbidden error. %s", err.Error()) + } + want := `{"errcode":"M_FORBIDDEN","error":"you shall not pass"}` + if string(jsonBytes) != want { + t.Errorf("TestForbidden: want %s, got %s", want, string(jsonBytes)) + } +}