web server running in container
This commit is contained in:
Родитель
0ab71c9f71
Коммит
20438986c8
12
Dockerfile
12
Dockerfile
|
@ -2,5 +2,15 @@ FROM golang:alpine
|
|||
|
||||
MAINTAINER Divyansh Manchanda <divyanshm@gmail.com>
|
||||
|
||||
RUN apk add --no-cache git mercurial \
|
||||
&& go get github.com/garyburd/redigo/redis \
|
||||
&& go get github.com/gorilla/handlers \
|
||||
&& apk del git mercurial
|
||||
|
||||
RUN mkdir /app
|
||||
ADD . /app/
|
||||
WORKDIR /app
|
||||
RUN go build -o main .
|
||||
|
||||
EXPOSE 8082
|
||||
ENTRYPOINT ["app"]
|
||||
CMD ["/app/main"]
|
||||
|
|
30
main.go
30
main.go
|
@ -13,9 +13,9 @@ import (
|
|||
|
||||
const (
|
||||
// Name of the application
|
||||
Name = "simple webserver"
|
||||
Name = "divman's GoServer"
|
||||
// Version of the application
|
||||
Version = "1.1.1"
|
||||
Version = "1.0.0"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -32,7 +32,6 @@ func main() {
|
|||
s := http.NewServeMux()
|
||||
s.HandleFunc("/", RootHandler)
|
||||
s.HandleFunc("/ping", PingHandler(r))
|
||||
s.HandleFunc("/kill", KillHandler)
|
||||
s.HandleFunc("/version", VersionHandler)
|
||||
s.HandleFunc("/payload", PayloadHandler)
|
||||
|
||||
|
@ -68,31 +67,6 @@ func PingHandler(s Storage) http.HandlerFunc {
|
|||
}
|
||||
}
|
||||
|
||||
// KillHandler handles request to the "/kill" endpoint.
|
||||
// Will shut down the webserver immediately (via exit code 1).
|
||||
// Only DELETE requests are accepted.
|
||||
// Other request methods will throw a HTTP Status Code 405 (Method Not Allowed)
|
||||
func KillHandler(resp http.ResponseWriter, req *http.Request) {
|
||||
if req.Method != "DELETE" {
|
||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
// We need to send a HTTP Status Code 200 (OK)
|
||||
// to respond that we have accepted the request.
|
||||
// Here we send a chunked response to the requester.
|
||||
flusher, ok := resp.(http.Flusher)
|
||||
if !ok {
|
||||
resp.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
resp.WriteHeader(http.StatusOK)
|
||||
flusher.Flush()
|
||||
|
||||
// And we kill the server (like requested)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// VersionHandler handles request to the "/version" endpoint.
|
||||
// It prints the Name and Version of this app.
|
||||
func VersionHandler(resp http.ResponseWriter, req *http.Request) {
|
||||
|
|
141
main_test.go
141
main_test.go
|
@ -1,141 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"os/exec"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type dummyStorage struct{}
|
||||
|
||||
func (s *dummyStorage) Ping() (string, error) {
|
||||
return "PONG", nil
|
||||
}
|
||||
|
||||
func TestPingHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/ping", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
backend := &dummyStorage{}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
handler := http.HandlerFunc(PingHandler(backend))
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
if status := rr.Code; status != http.StatusOK {
|
||||
t.Errorf("Wrong status code: got %v, expected %v", status, http.StatusOK)
|
||||
}
|
||||
|
||||
expected := "PONG\n"
|
||||
if rr.Body.String() != expected {
|
||||
t.Errorf("Unexpected body: got %q, want %q", rr.Body.String(), expected)
|
||||
}
|
||||
}
|
||||
|
||||
type dummyErrorStorage struct{}
|
||||
|
||||
func (s *dummyErrorStorage) Ping() (string, error) {
|
||||
return "", fmt.Errorf("Connection timeout to storage backend")
|
||||
}
|
||||
|
||||
func TestPingHandler_Error(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/ping", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
backend := &dummyErrorStorage{}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
handler := http.HandlerFunc(PingHandler(backend))
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
if status := rr.Code; status != http.StatusInternalServerError {
|
||||
t.Errorf("Wrong status code: got %v, expected %v", status, http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
expected := "Connection timeout to storage backend"
|
||||
if rr.Body.String() != expected {
|
||||
t.Errorf("Unexpected body: got %q, want %q", rr.Body.String(), expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVersionHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/version", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
handler := http.HandlerFunc(VersionHandler)
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
if status := rr.Code; status != http.StatusOK {
|
||||
t.Errorf("Wrong status code: got %v, expected %v", status, http.StatusOK)
|
||||
}
|
||||
|
||||
expected := fmt.Sprintf("%s v%s\n", Name, Version)
|
||||
if rr.Body.String() != expected {
|
||||
t.Errorf("Unexpected body: got %q, want %q", rr.Body.String(), expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKillHandler(t *testing.T) {
|
||||
// Here we only test if the end point kills itself.
|
||||
if os.Getenv("KILL_ENDPOINT") == "1" {
|
||||
req, err := http.NewRequest("DELETE", "/kill", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
handler := http.HandlerFunc(KillHandler)
|
||||
handler.ServeHTTP(rr, req)
|
||||
return
|
||||
}
|
||||
|
||||
cmd := exec.Command(os.Args[0], "-test.run=TestKillHandler")
|
||||
cmd.Env = append(os.Environ(), "KILL_ENDPOINT=1")
|
||||
err := cmd.Run()
|
||||
if e, ok := err.(*exec.ExitError); ok && !e.Success() {
|
||||
return
|
||||
}
|
||||
t.Errorf("Process ran with err %v, want exit status 1", err)
|
||||
}
|
||||
|
||||
func TestKillHandler_WrongMethod(t *testing.T) {
|
||||
req, err := http.NewRequest("POST", "/kill", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
handler := http.HandlerFunc(KillHandler)
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
if status := rr.Code; status != http.StatusMethodNotAllowed {
|
||||
t.Errorf("Wrong status code: got %v, expected %v", status, http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnvOrDefault_Fallback(t *testing.T) {
|
||||
expected := "dummy"
|
||||
got := EnvOrDefault("TEST_DEFAULT_ENV", expected)
|
||||
if expected != got {
|
||||
t.Errorf("Wrong fallback value: got %v, expected %v", got, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnvOrDefault_WithEnv(t *testing.T) {
|
||||
expected := "dummy-from-env"
|
||||
os.Setenv("TEST_SET_ENV", expected)
|
||||
got := EnvOrDefault("TEST_SET_ENV", "dummy-fallback")
|
||||
if expected != got {
|
||||
t.Errorf("Wrong env value: got %v, expected %v", got, expected)
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче