Rewrite v2

This commit is contained in:
Jacob Gunther
2022-07-31 22:44:27 -05:00
parent 70601daac0
commit 5cc9492a00
10 changed files with 388 additions and 710 deletions

View File

@@ -1,308 +1,74 @@
package main
import (
"encoding/base64"
"encoding/json"
"fmt"
"log"
"net/http"
"strconv"
"strings"
"github.com/valyala/fasthttp"
"github.com/gofiber/fiber/v2"
)
func PingHandler(ctx *fasthttp.RequestCtx) {
ctx.SetBodyString(http.StatusText(http.StatusOK))
func init() {
app.Get("/status/java/:address", JavaStatusHandler)
app.Get("/status/bedrock/:address", BedrockStatusHandler)
app.Get("/icon/:address", IconHandler)
}
func JavaStatusHandler(ctx *fasthttp.RequestCtx) {
host, port, err := ParseAddress(ctx.UserValue("address").(string), 25565)
func JavaStatusHandler(ctx *fiber.Ctx) error {
host, port, err := ParseAddress(ctx.Params("address"), 25565)
if err != nil {
WriteError(ctx, nil, http.StatusBadRequest, "Invalid/malformed address")
log.Println(err)
return
return ctx.Status(http.StatusBadRequest).SendString("Invalid address value")
}
cacheEnabled, cacheKey, err := IsCacheEnabled(ctx, "java", host, port)
response, err := GetJavaStatus(host, port)
if err != nil {
WriteError(ctx, err, http.StatusInternalServerError)
return
return err
}
if cacheEnabled {
exists, cache, ttl, err := r.GetValueAndTTL(cacheKey)
if err != nil {
WriteError(ctx, err, http.StatusInternalServerError)
return
}
if exists {
ctx.Response.Header.Set("X-Cache-Hit", "TRUE")
ctx.Response.Header.Set("X-Cache-Time-Remaining", strconv.Itoa(int(ttl.Seconds())))
ctx.SetContentType("application/json")
ctx.SetBodyString(cache)
return
}
switch v := response.(type) {
case string:
return ctx.Type("json").SendString(v)
default:
return ctx.JSON(response)
}
ctx.Response.Header.Set("X-Cache-Hit", "FALSE")
status := GetJavaStatus(host, port)
if status.Online && status.Response.Favicon != nil {
data, err := base64.StdEncoding.DecodeString(strings.Replace(*status.Response.Favicon, "data:image/png;base64,", "", 1))
if err != nil {
WriteError(ctx, err, http.StatusInternalServerError)
return
}
if err := r.Set(fmt.Sprintf("favicon:%s-%d", host, port), data, config.FaviconCacheTTL); err != nil {
WriteError(ctx, err, http.StatusInternalServerError)
return
}
}
data, err := json.Marshal(status)
if err != nil {
WriteError(ctx, err, http.StatusInternalServerError)
return
}
if err = r.Set(cacheKey, data, config.StatusCacheTTL); err != nil {
WriteError(ctx, err, http.StatusInternalServerError)
return
}
ctx.SetContentType("application/json")
ctx.SetBody(data)
}
func BedrockStatusHandler(ctx *fasthttp.RequestCtx) {
host, port, err := ParseAddress(ctx.UserValue("address").(string), 19132)
func BedrockStatusHandler(ctx *fiber.Ctx) error {
host, port, err := ParseAddress(ctx.Params("address"), 19132)
if err != nil {
WriteError(ctx, nil, http.StatusBadRequest, "Invalid/malformed address")
return
return ctx.Status(http.StatusBadRequest).SendString("Invalid address value")
}
cacheEnabled, cacheKey, err := IsCacheEnabled(ctx, "bedrock", host, port)
response, err := GetBedrockStatus(host, port)
if err != nil {
WriteError(ctx, err, http.StatusInternalServerError)
return
return err
}
if cacheEnabled {
exists, cache, ttl, err := r.GetValueAndTTL(cacheKey)
if err != nil {
WriteError(ctx, err, http.StatusInternalServerError)
return
}
if exists {
ctx.Response.Header.Set("X-Cache-Hit", "TRUE")
ctx.Response.Header.Set("X-Cache-Time-Remaining", strconv.Itoa(int(ttl.Seconds())))
ctx.SetContentType("application/json")
ctx.SetBodyString(cache)
return
}
switch v := response.(type) {
case string:
return ctx.Type("json").SendString(v)
default:
return ctx.JSON(response)
}
ctx.Response.Header.Set("X-Cache-Hit", "FALSE")
data, err := json.Marshal(GetBedrockStatus(host, port))
if err != nil {
WriteError(ctx, err, http.StatusInternalServerError)
return
}
if err = r.Set(cacheKey, data, config.StatusCacheTTL); err != nil {
WriteError(ctx, err, http.StatusInternalServerError)
return
}
ctx.SetContentType("application/json")
ctx.SetBody(data)
}
func FaviconNoExtensionHandler(ctx *fasthttp.RequestCtx) {
host, port, err := ParseAddress(ctx.UserValue("address").(string), 25565)
func IconHandler(ctx *fiber.Ctx) error {
host, port, err := ParseAddress(ctx.Params("address"), 25565)
if err != nil {
WriteError(ctx, nil, http.StatusBadRequest, "Invalid/malformed address")
return
return ctx.Status(http.StatusBadRequest).SendString("Invalid address value")
}
cacheKey := fmt.Sprintf("favicon:%s-%d", host, port)
exists, err := r.Exists(cacheKey)
icon, err := GetServerIcon(host, port)
if err != nil {
WriteError(ctx, err, http.StatusInternalServerError)
return
return err
}
if exists {
value, err := r.GetBytes(cacheKey)
if err != nil {
WriteError(ctx, err, http.StatusInternalServerError)
return
}
ctx.Response.Header.Set("X-Cache-Hit", "TRUE")
ctx.Response.Header.Set("X-Server-Status", "online-cache")
ctx.SetContentType("image/png")
ctx.SetBody(value)
return
}
ctx.Response.Header.Set("X-Cache-Hit", "FALSE")
status := GetJavaStatus(host, port)
if !status.Online {
ctx.Response.Header.Set("X-Server-Status", "offline")
ctx.SetContentType("image/png")
ctx.SetBody(defaultIconBytes)
return
}
if status.Response.Favicon == nil {
ctx.Response.Header.Set("X-Server-Status", "online-no-icon")
ctx.SetContentType("image/png")
ctx.SetBody(defaultIconBytes)
return
}
data, err := base64.StdEncoding.DecodeString(strings.Replace(*status.Response.Favicon, "data:image/png;base64,", "", 1))
if err != nil {
WriteError(ctx, err, http.StatusInternalServerError)
return
}
if err := r.Set(cacheKey, data, config.FaviconCacheTTL); err != nil {
WriteError(ctx, err, http.StatusInternalServerError)
return
}
ctx.Response.Header.Set("X-Server-Status", "online")
ctx.SetContentType("image/png")
ctx.SetBody(data)
}
func FaviconHandler(ctx *fasthttp.RequestCtx) {
filename := ctx.UserValue("filename").(string)
if !strings.HasSuffix(filename, ".png") {
WriteError(ctx, nil, http.StatusBadRequest, "Filename must end with .png")
return
}
host, port, err := ParseAddress(ctx.UserValue("address").(string), 25565)
if err != nil {
WriteError(ctx, nil, http.StatusBadRequest, "Invalid/malformed address")
return
}
cacheKey := fmt.Sprintf("favicon:%s-%d", host, port)
exists, err := r.Exists(cacheKey)
if err != nil {
WriteError(ctx, err, http.StatusInternalServerError)
return
}
if exists {
value, err := r.GetBytes(cacheKey)
if err != nil {
WriteError(ctx, err, http.StatusInternalServerError)
return
}
ctx.Response.Header.Set("X-Cache-Hit", "TRUE")
ctx.Response.Header.Set("X-Server-Status", "online-cache")
ctx.Response.Header.Set("Content-Disposition", fmt.Sprintf("inline; filename=\"%s\"", filename))
ctx.SetContentType("image/png")
ctx.SetBody(value)
return
}
ctx.Response.Header.Set("X-Cache-Hit", "FALSE")
status := GetJavaStatus(host, port)
if !status.Online {
ctx.Response.Header.Set("X-Server-Status", "offline")
ctx.Response.Header.Set("Content-Disposition", fmt.Sprintf("inline; filename=\"%s\"", filename))
ctx.SetContentType("image/png")
ctx.SetBody(defaultIconBytes)
return
}
if status.Response.Favicon == nil {
ctx.Response.Header.Set("X-Server-Status", "online-no-icon")
ctx.Response.Header.Set("Content-Disposition", fmt.Sprintf("inline; filename=\"%s\"", filename))
ctx.SetContentType("image/png")
ctx.SetBody(defaultIconBytes)
return
}
data, err := base64.StdEncoding.DecodeString(strings.Replace(*status.Response.Favicon, "data:image/png;base64,", "", 1))
if err != nil {
WriteError(ctx, err, http.StatusInternalServerError)
return
}
if err := r.Set(cacheKey, data, config.FaviconCacheTTL); err != nil {
WriteError(ctx, err, http.StatusInternalServerError)
return
}
ctx.Response.Header.Set("X-Server-Status", "online")
ctx.Response.Header.Set("Content-Disposition", fmt.Sprintf("inline; filename=\"%s\"", filename))
ctx.SetContentType("image/png")
ctx.SetBody(data)
return ctx.Type("png").Send(icon)
}