2
0
mirror of https://github.com/offen/website.git synced 2024-12-26 22:50:20 +01:00

Merge pull request #23 from offen/shared-go

Setup code sharing between go apps
This commit is contained in:
Frederik Ring 2019-06-06 13:10:20 +02:00 committed by GitHub
commit e324f39bf7
8 changed files with 189 additions and 8 deletions

View File

@ -60,6 +60,17 @@ jobs:
name: Run tests
command: make test-ci
shared:
docker:
- image: circleci/golang:1.12
working_directory: ~/offen/shared
steps:
- checkout:
path: ~/offen
- run:
name: Run tests
command: make test
vault:
docker:
- image: circleci/node:10-browsers
@ -150,3 +161,4 @@ workflows:
- script
- auditorium
- packages
- shared

View File

@ -3,11 +3,11 @@ version: '3'
services:
kms:
image: golang:1.12
working_dir: /kms
working_dir: /code/kms
volumes:
- ./kms:/kms
- ./local.offen.dev.pem:/kms/local.offen.dev.pem
- ./local.offen.dev-key.pem:/kms/local.offen.dev-key.pem
- .:/code
- ./local.offen.dev.pem:/code/kms/local.offen.dev.pem
- ./local.offen.dev-key.pem:/code/kms/local.offen.dev-key.pem
- $GOPATH/pkg/mod:/go/pkg/mod
environment:
- GOPATH=/go
@ -18,11 +18,11 @@ services:
server:
image: golang:1.12
working_dir: /server
working_dir: /code/server
volumes:
- ./server:/server
- ./local.offen.dev.pem:/server/local.offen.dev.pem
- ./local.offen.dev-key.pem:/server/local.offen.dev-key.pem
- .:/code
- ./local.offen.dev.pem:/code/server/local.offen.dev.pem
- ./local.offen.dev-key.pem:/code/server/local.offen.dev-key.pem
- $GOPATH/pkg/mod:/go/pkg/mod
environment:
- GOPATH=/go

2
shared/Makefile Normal file
View File

@ -0,0 +1,2 @@
test:
@go test -race -cover ./...

15
shared/README.md Normal file
View File

@ -0,0 +1,15 @@
# shared
`shared` contains Go packages shared across applications. Consumers need to symlink the folder into their app directory.
---
## Development
### Commands
#### Run the tests
```
make test
```

22
shared/http/errors.go Normal file
View File

@ -0,0 +1,22 @@
package http
import (
"encoding/json"
"net/http"
)
type errorResponse struct {
Error string `json:"error"`
Status int `json:"status"`
}
func jsonError(err error, status int) []byte {
r := errorResponse{err.Error(), status}
b, _ := json.Marshal(r)
return b
}
func RespondWithJSONError(w http.ResponseWriter, err error, status int) {
w.WriteHeader(status)
w.Write(jsonError(err, status))
}

View File

@ -0,0 +1,19 @@
package http
import (
"errors"
"net/http"
"net/http/httptest"
"testing"
)
func TestRespondWithJSONError(t *testing.T) {
w := httptest.NewRecorder()
RespondWithJSONError(w, errors.New("does not work"), http.StatusInternalServerError)
if w.Code != http.StatusInternalServerError {
t.Errorf("Unexpected status code %d", w.Code)
}
if w.Body.String() != `{"error":"does not work","status":500}` {
t.Errorf("Unexpected response body %s", w.Body.String())
}
}

29
shared/http/middleware.go Normal file
View File

@ -0,0 +1,29 @@
package http
import "net/http"
func CorsMiddleware(next http.Handler, origin string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Credentials", "true")
w.Header().Set("Access-Control-Allow-Methods", "POST,GET")
w.Header().Set("Access-Control-Allow-Origin", origin)
next.ServeHTTP(w, r)
})
}
func ContentTypeMiddleware(next http.Handler, contentType string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Content-Type", contentType)
next.ServeHTTP(w, r)
})
}
func DoNotTrackMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if dnt := r.Header.Get("DNT"); dnt == "1" {
w.WriteHeader(http.StatusNoContent)
return
}
next.ServeHTTP(w, r)
})
}

View File

@ -0,0 +1,82 @@
package http
import (
"net/http"
"net/http/httptest"
"testing"
)
func TestCorsMiddleware(t *testing.T) {
t.Run("default", func(t *testing.T) {
wrapped := CorsMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK"))
}), "https://www.example.net")
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/", nil)
wrapped.ServeHTTP(w, r)
if h := w.Header().Get("Access-Control-Allow-Origin"); h != "https://www.example.net" {
t.Errorf("Unexpected header value %v", h)
}
})
}
func TestContentTypeMiddleware(t *testing.T) {
t.Run("default", func(t *testing.T) {
wrapped := ContentTypeMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK"))
}), "application/json")
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/", nil)
wrapped.ServeHTTP(w, r)
if h := w.Header().Get("Content-Type"); h != "application/json" {
t.Errorf("Unexpected header value %v", h)
}
})
}
func TestDoNotTrackMiddleware(t *testing.T) {
wrapped := DoNotTrackMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hey there"))
}))
t.Run("with header", func(t *testing.T) {
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/", nil)
r.Header.Set("DNT", "1")
wrapped.ServeHTTP(w, r)
if w.Code != http.StatusNoContent {
t.Errorf("Unexpected status code %d", w.Code)
}
if w.Body.String() != "" {
t.Errorf("Unexpected response body %s", w.Body.String())
}
})
t.Run("without header", func(t *testing.T) {
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/", nil)
wrapped.ServeHTTP(w, r)
if w.Code != http.StatusOK {
t.Errorf("Unexpected status code %d", w.Code)
}
if w.Body.String() != "hey there" {
t.Errorf("Unexpected response body %s", w.Body.String())
}
})
t.Run("with header allowing", func(t *testing.T) {
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/", nil)
r.Header.Set("DNT", "0")
wrapped.ServeHTTP(w, r)
if w.Code != http.StatusOK {
t.Errorf("Unexpected status code %d", w.Code)
}
if w.Body.String() != "hey there" {
t.Errorf("Unexpected response body %s", w.Body.String())
}
})
}