tddddddd
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"embed"
|
"embed"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -12,6 +13,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
@@ -21,11 +23,30 @@ import (
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
Addr string
|
Addr string
|
||||||
RPS int
|
RPS int
|
||||||
|
fsDB string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
cfg Config
|
cfg Config
|
||||||
limiter *rate.Limiter
|
limiter *rate.Limiter
|
||||||
|
db DB
|
||||||
|
}
|
||||||
|
|
||||||
|
type DB interface {
|
||||||
|
GetQuestion(string) (Question, error)
|
||||||
|
PutAnswer(string, Answer) error
|
||||||
|
GetAnswers(string) ([]Answer, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type fsDB string
|
||||||
|
|
||||||
|
type Question struct {
|
||||||
|
Text string
|
||||||
|
Options []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Answer struct {
|
||||||
|
Text string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Session struct {
|
type Session struct {
|
||||||
@@ -66,6 +87,7 @@ func (cfg Config) NewHandler() Handler {
|
|||||||
return Handler{
|
return Handler{
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
limiter: rate.NewLimiter(rate.Limit(cfg.RPS), 10),
|
limiter: rate.NewLimiter(rate.Limit(cfg.RPS), 10),
|
||||||
|
db: fsDB(cfg.fsDB),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,20 +160,58 @@ func (h Handler) handle(session Session, w http.ResponseWriter, r *http.Request)
|
|||||||
http.FileServer(public).ServeHTTP(w, r)
|
http.FileServer(public).ServeHTTP(w, r)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
switch r.URL.Path {
|
if strings.HasPrefix(r.URL.Path, "/api/v1/questions/") {
|
||||||
case "/api/v1/question":
|
|
||||||
return h.handleAPIV1Question(session, w, r)
|
return h.handleAPIV1Question(session, w, r)
|
||||||
case "/api/v1/answer":
|
}
|
||||||
return h.handleAPIV1Answer(session, w, r)
|
if strings.HasPrefix(r.URL.Path, "/api/v1/questions") {
|
||||||
|
return h.handleAPIV1Questions(session, w, r)
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(r.URL.Path, "/api/v1/answers") {
|
||||||
|
return h.handleAPIV1Answers(session, w, r)
|
||||||
}
|
}
|
||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h Handler) handleAPIV1Question(session Session, w http.ResponseWriter, r *http.Request) error {
|
func (h Handler) handleAPIV1Question(session Session, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
id := path.Base(r.URL.Path)
|
||||||
|
q, err := h.db.GetQuestion(id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return json.NewEncoder(w).Encode(q)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Handler) handleAPIV1Questions(session Session, w http.ResponseWriter, r *http.Request) error {
|
||||||
return errors.New("not impl")
|
return errors.New("not impl")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h Handler) handleAPIV1Answer(session Session, w http.ResponseWriter, r *http.Request) error {
|
func (h Handler) handleAPIV1Answers(session Session, w http.ResponseWriter, r *http.Request) error {
|
||||||
return errors.New("not impl")
|
return errors.New("not impl")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db fsDB) GetQuestion(id string) (Question, error) {
|
||||||
|
p := db.path(id)
|
||||||
|
b, err := os.ReadFile(p)
|
||||||
|
if err != nil {
|
||||||
|
return Question{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var q Question
|
||||||
|
if err := json.Unmarshal(b, &q); err != nil {
|
||||||
|
return Question{}, err
|
||||||
|
}
|
||||||
|
return q, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db fsDB) PutAnswer(id string, a Answer) error {
|
||||||
|
return errors.New("not impl")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db fsDB) GetAnswers(id string) ([]Answer, error) {
|
||||||
|
return nil, errors.New("not impl")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db fsDB) path(q string) string {
|
||||||
|
return path.Join(string(db), q)
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestRunHTTP(t *testing.T) {
|
func TestRunHTTP(t *testing.T) {
|
||||||
cfg := Config{}
|
cfg := Config{
|
||||||
|
fsDB: t.TempDir(),
|
||||||
|
}
|
||||||
|
|
||||||
h := cfg.NewHandler()
|
h := cfg.NewHandler()
|
||||||
|
|
||||||
@@ -53,8 +55,8 @@ func TestRunHTTP(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("/api/v1/question", func(t *testing.T) {
|
t.Run("/api/v1/questions/0", func(t *testing.T) {
|
||||||
r := httptest.NewRequest(http.MethodGet, "/api/v1/question", nil)
|
r := httptest.NewRequest(http.MethodGet, "/api/v1/questions/0", nil)
|
||||||
r.SetBasicAuth("b", "b")
|
r.SetBasicAuth("b", "b")
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
t.Logf("%s %s", r.Method, r.URL)
|
t.Logf("%s %s", r.Method, r.URL)
|
||||||
@@ -66,8 +68,21 @@ func TestRunHTTP(t *testing.T) {
|
|||||||
t.Errorf("not impl: %s", w.Body.Bytes())
|
t.Errorf("not impl: %s", w.Body.Bytes())
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("/api/v1/answer", func(t *testing.T) {
|
t.Run("/api/v1/questions", func(t *testing.T) {
|
||||||
r := httptest.NewRequest(http.MethodGet, "/api/v1/answer", nil)
|
r := httptest.NewRequest(http.MethodGet, "/api/v1/questions", nil)
|
||||||
|
r.SetBasicAuth("b", "b")
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
t.Logf("%s %s", r.Method, r.URL)
|
||||||
|
h.ServeHTTP(w, r)
|
||||||
|
t.Logf("(%d) %s", w.Code, w.Body.Bytes())
|
||||||
|
if w.Code != http.StatusNotFound {
|
||||||
|
t.Error(w.Code)
|
||||||
|
}
|
||||||
|
t.Errorf("not impl: %s", w.Body.Bytes())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("/api/v1/answers", func(t *testing.T) {
|
||||||
|
r := httptest.NewRequest(http.MethodGet, "/api/v1/answers", nil)
|
||||||
r.SetBasicAuth("b", "b")
|
r.SetBasicAuth("b", "b")
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
t.Logf("%s %s", r.Method, r.URL)
|
t.Logf("%s %s", r.Method, r.URL)
|
||||||
|
|||||||
Reference in New Issue
Block a user