tddddddd
parent
4241b83721
commit
a1d9e30030
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"embed"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
|
@ -12,6 +13,7 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
|
|
@ -21,11 +23,30 @@ import (
|
|||
type Config struct {
|
||||
Addr string
|
||||
RPS int
|
||||
fsDB string
|
||||
}
|
||||
|
||||
type Handler struct {
|
||||
cfg Config
|
||||
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 {
|
||||
|
|
@ -66,6 +87,7 @@ func (cfg Config) NewHandler() Handler {
|
|||
return Handler{
|
||||
cfg: cfg,
|
||||
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)
|
||||
return nil
|
||||
}
|
||||
switch r.URL.Path {
|
||||
case "/api/v1/question":
|
||||
if strings.HasPrefix(r.URL.Path, "/api/v1/questions/") {
|
||||
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)
|
||||
return nil
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
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) {
|
||||
cfg := Config{}
|
||||
cfg := Config{
|
||||
fsDB: t.TempDir(),
|
||||
}
|
||||
|
||||
h := cfg.NewHandler()
|
||||
|
||||
|
|
@ -53,8 +55,8 @@ func TestRunHTTP(t *testing.T) {
|
|||
}
|
||||
})
|
||||
|
||||
t.Run("/api/v1/question", func(t *testing.T) {
|
||||
r := httptest.NewRequest(http.MethodGet, "/api/v1/question", nil)
|
||||
t.Run("/api/v1/questions/0", func(t *testing.T) {
|
||||
r := httptest.NewRequest(http.MethodGet, "/api/v1/questions/0", nil)
|
||||
r.SetBasicAuth("b", "b")
|
||||
w := httptest.NewRecorder()
|
||||
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.Run("/api/v1/answer", func(t *testing.T) {
|
||||
r := httptest.NewRequest(http.MethodGet, "/api/v1/answer", nil)
|
||||
t.Run("/api/v1/questions", func(t *testing.T) {
|
||||
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")
|
||||
w := httptest.NewRecorder()
|
||||
t.Logf("%s %s", r.Method, r.URL)
|
||||
|
|
|
|||
Loading…
Reference in New Issue