Browse Source

Implement simple /load endpoint

master
NGnius 4 years ago
parent
commit
a123578957
7 changed files with 233 additions and 0 deletions
  1. +6
    -0
      .gitignore
  2. +32
    -0
      config.go
  3. +3
    -0
      go.mod
  4. +74
    -0
      handlers.go
  5. +60
    -0
      json_structs.go
  6. BIN
      leadercraft-s
  7. +58
    -0
      main.go

+ 6
- 0
.gitignore View File

@@ -12,3 +12,9 @@
# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# go mod checksum
go.sum

# build binary
./leaderboard-s


+ 32
- 0
config.go View File

@@ -0,0 +1,32 @@
// NGnius 2020-01-30

package main

import (
"flag"
"fmt"
"os"
)

const (
defaultPort = "1337"
defaultRoot = "."
)

var (
printVersionAndExit bool
)

func initArgs() {
flag.StringVar(&port, "port", defaultPort, "Port to listen on")
flag.StringVar(&root, "root", defaultRoot, "Root working directory")
flag.BoolVar(&printVersionAndExit, "version", false, "Print version and exit")
}

func parseArgs() {
flag.Parse()
if printVersionAndExit {
fmt.Println(Name + " v" + Version)
os.Exit(0)
}
}

+ 3
- 0
go.mod View File

@@ -0,0 +1,3 @@
module git.exmods.org/NGnius/leadercraft-s

go 1.13

+ 74
- 0
handlers.go View File

@@ -0,0 +1,74 @@
// NGnius 2020-01-30

package main

import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"strconv"
)

func boardHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
w.WriteHeader(405)
return
}
w.Header().Add("content-type", "application/json")
w.Header().Add("Access-Control-Allow-Origin", "*")
args := r.URL.Query()
// check args pre-conditions
if !checkArgExists(args, "board", w) {
return
}
board := args.Get("board")
if !checkArgExists(args, "count", w) || !checkArgInt(args, "count", w, 0) {
return
}
count, _ := strconv.Atoi(args.Get("count"))
if !checkArgExists(args, "start", w) || !checkArgInt(args, "start", w, 0) {
return
}
start, _ := strconv.Atoi(args.Get("start"))
// execute query
result := NewResult("", r.URL.String())
b, ok := boards[board]
if !ok {
w.WriteHeader(404)
return
}
if len(b.Entries) < start+count {
count = len(b.Entries) - start
}
// result.Items = b.Entries[start : start+count]
for _, entry := range b.Entries[start : start+count] {
item := entry
result.Items = append(result.Items, &item)
}
result.Query = fmt.Sprintf("load board[%s] from %d to %d", board, start, count+start)
result.Complete()
data, err := json.Marshal(result)
if err != nil {
w.WriteHeader(500)
return
}
w.Write(data)
}

func checkArgExists(values url.Values, key string, w http.ResponseWriter) (ok bool) {
ok = values.Get(key) != ""
if !ok {
w.WriteHeader(400)
}
return
}

func checkArgInt(values url.Values, key string, w http.ResponseWriter, min int) (ok bool) {
intVal, err := strconv.Atoi(values.Get(key))
ok = err == nil && intVal >= min
if !ok {
w.WriteHeader(400)
}
return
}

+ 60
- 0
json_structs.go View File

@@ -0,0 +1,60 @@
// NGnius 2020-01-30

package main

import (
"strconv"
"time"
)

// Board a leaderboard
type Board struct {
ID int64
Entries []Entry
Name string
}

// Entry an entry in a leaderboard
type Entry struct {
ID int64
Rank int64
Score int64
PlayerName string
PlayerURL string
}

// Player a player
type Player struct {
ID int64
Name string
Entries []Entry
}

// URL get the player's URL
func (p *Player) URL() string {
return "/player/" + strconv.Itoa(int(p.ID))
}

// Result a query result
type Result struct {
Items []interface{}
Elapsed int64
Count int
Query string
URL string
Start time.Time
}

// NewResult build a query struct
func NewResult(q string, url string) (r Result) {
r.Start = time.Now()
r.Query = q
r.URL = url
return
}

// Complete finish the result
func (r *Result) Complete() {
r.Count = len(r.Items)
r.Elapsed = time.Since(r.Start).Milliseconds()
}

BIN
leadercraft-s View File


+ 58
- 0
main.go View File

@@ -0,0 +1,58 @@
// NGnius 2020-01-30

package main // leadercraft-server

import (
"fmt"
"net/http"
)

const (
// Version the current version
Version = "0.1"
// Name the program name
Name = "leadercraft-s"
)

var (
server *http.Server
handler http.Handler
port string
root string
boards map[string]Board
)

func init() {
initArgs()
serverMux := http.NewServeMux()
serverMux.HandleFunc("/load", boardHandler)
handler = serverMux
boards = make(map[string]Board)
// test data
boards["test1"] = Board{
ID: 1,
Entries: []Entry{
Entry{ID: 1, Rank: 1, Score: 1000, PlayerName: "NGnius", PlayerURL: "/player/1"},
Entry{ID: 2, Rank: 2, Score: 900, PlayerName: "Also NGnius", PlayerURL: "/player/2"},
Entry{ID: 4, Rank: 3, Score: 400, PlayerName: ".xX||eDgY TeeNaGeR||Xx.", PlayerURL: "/player/3"},
Entry{ID: 3, Rank: 4, Score: 350, PlayerName: "New username who dis?", PlayerURL: "/player/4"},
Entry{ID: 7, Rank: 5, Score: 350, PlayerName: "Extremely Ridiculously Long Name Please don't break things", PlayerURL: "/player/5"},
Entry{ID: 5, Rank: 6, Score: 250, PlayerName: "P|P3 |o|z", PlayerURL: "/player/3333"},
Entry{ID: 6, Rank: 7, Score: 200, PlayerName: "Simon", PlayerURL: "/player/456"},
Entry{ID: 24, Rank: 8, Score: 175, PlayerName: "Zettagram.com", PlayerURL: "/player/32"},
Entry{ID: 42, Rank: 9, Score: 150, PlayerName: "The Doctor", PlayerURL: "/player/9283"},
Entry{ID: 43, Rank: 10, Score: 140, PlayerName: "Marvin the Paranoid Android", PlayerURL: "/player/6"},
Entry{ID: 8, Rank: 11, Score: 100, PlayerName: "IDK HOW", PlayerURL: "/player/666"},
},
}
}

func main() {
parseArgs()
server = &http.Server{
Addr: ":" + port,
Handler: handler,
}
fmt.Println("Starting on " + server.Addr)
fmt.Println(server.ListenAndServe())
}