mirror of
https://github.com/offen/website.git
synced 2024-11-22 09:00:28 +01:00
setup code sharing between go apps
This commit is contained in:
parent
c9bbb00e80
commit
abbf3407a6
@ -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
|
||||
|
@ -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
2
shared/Makefile
Normal file
@ -0,0 +1,2 @@
|
||||
test:
|
||||
@go test -race -cover ./...
|
15
shared/README.md
Normal file
15
shared/README.md
Normal 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
22
shared/http/errors.go
Normal 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))
|
||||
}
|
19
shared/http/errors_test.go
Normal file
19
shared/http/errors_test.go
Normal 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
29
shared/http/middleware.go
Normal 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)
|
||||
})
|
||||
}
|
82
shared/http/middleware_test.go
Normal file
82
shared/http/middleware_test.go
Normal 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())
|
||||
}
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user