mirror of
https://github.com/offen/website.git
synced 2024-11-25 18:20:28 +01:00
Merge pull request #23 from offen/shared-go
Setup code sharing between go apps
This commit is contained in:
commit
e324f39bf7
@ -60,6 +60,17 @@ jobs:
|
|||||||
name: Run tests
|
name: Run tests
|
||||||
command: make test-ci
|
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:
|
vault:
|
||||||
docker:
|
docker:
|
||||||
- image: circleci/node:10-browsers
|
- image: circleci/node:10-browsers
|
||||||
@ -150,3 +161,4 @@ workflows:
|
|||||||
- script
|
- script
|
||||||
- auditorium
|
- auditorium
|
||||||
- packages
|
- packages
|
||||||
|
- shared
|
||||||
|
@ -3,11 +3,11 @@ version: '3'
|
|||||||
services:
|
services:
|
||||||
kms:
|
kms:
|
||||||
image: golang:1.12
|
image: golang:1.12
|
||||||
working_dir: /kms
|
working_dir: /code/kms
|
||||||
volumes:
|
volumes:
|
||||||
- ./kms:/kms
|
- .:/code
|
||||||
- ./local.offen.dev.pem:/kms/local.offen.dev.pem
|
- ./local.offen.dev.pem:/code/kms/local.offen.dev.pem
|
||||||
- ./local.offen.dev-key.pem:/kms/local.offen.dev-key.pem
|
- ./local.offen.dev-key.pem:/code/kms/local.offen.dev-key.pem
|
||||||
- $GOPATH/pkg/mod:/go/pkg/mod
|
- $GOPATH/pkg/mod:/go/pkg/mod
|
||||||
environment:
|
environment:
|
||||||
- GOPATH=/go
|
- GOPATH=/go
|
||||||
@ -18,11 +18,11 @@ services:
|
|||||||
|
|
||||||
server:
|
server:
|
||||||
image: golang:1.12
|
image: golang:1.12
|
||||||
working_dir: /server
|
working_dir: /code/server
|
||||||
volumes:
|
volumes:
|
||||||
- ./server:/server
|
- .:/code
|
||||||
- ./local.offen.dev.pem:/server/local.offen.dev.pem
|
- ./local.offen.dev.pem:/code/server/local.offen.dev.pem
|
||||||
- ./local.offen.dev-key.pem:/server/local.offen.dev-key.pem
|
- ./local.offen.dev-key.pem:/code/server/local.offen.dev-key.pem
|
||||||
- $GOPATH/pkg/mod:/go/pkg/mod
|
- $GOPATH/pkg/mod:/go/pkg/mod
|
||||||
environment:
|
environment:
|
||||||
- GOPATH=/go
|
- 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